|
| 1 | +# PotLock Donation Contract |
| 2 | + |
| 3 | +## Purpose |
| 4 | + |
| 5 | +Provide a way to donate NEAR or FTs to any account, with a protocol fee taken out |
| 6 | + |
| 7 | +## Contract Structure |
| 8 | + |
| 9 | +### General Types |
| 10 | + |
| 11 | +```rs |
| 12 | +type DonationId = u64; |
| 13 | +type TimestampMs = u64; |
| 14 | +``` |
| 15 | + |
| 16 | +### Contract |
| 17 | + |
| 18 | +```rs |
| 19 | +pub struct Contract { |
| 20 | + contract_source_metadata: LazyOption<VersionedContractSourceMetadata>, |
| 21 | + owner: AccountId, |
| 22 | + protocol_fee_basis_points: u32, |
| 23 | + referral_fee_basis_points: u32, |
| 24 | + protocol_fee_recipient_account: AccountId, |
| 25 | + donations_by_id: UnorderedMap<DonationId, VersionedDonation>, |
| 26 | + donation_ids_by_recipient_id: LookupMap<AccountId, UnorderedSet<DonationId>>, |
| 27 | + donation_ids_by_donor_id: LookupMap<AccountId, UnorderedSet<DonationId>>, |
| 28 | + donation_ids_by_ft_id: LookupMap<AccountId, UnorderedSet<DonationId>>, |
| 29 | +} |
| 30 | + |
| 31 | +/// NOT stored in contract storage; only used for get_config response |
| 32 | +pub struct Config { |
| 33 | + pub owner: AccountId, |
| 34 | + pub protocol_fee_basis_points: u32, |
| 35 | + pub referral_fee_basis_points: u32, |
| 36 | + pub protocol_fee_recipient_account: AccountId, |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +### Donations |
| 41 | + |
| 42 | +_NB: Projects are automatically approved by default._ |
| 43 | + |
| 44 | +```rs |
| 45 | +pub struct Donation { |
| 46 | + /// Unique identifier for the donation |
| 47 | + pub id: DonationId, |
| 48 | + /// ID of the donor |
| 49 | + pub donor_id: AccountId, |
| 50 | + /// Amount donated |
| 51 | + pub total_amount: U128, |
| 52 | + /// FT id (e.g. "near") |
| 53 | + pub ft_id: AccountId, |
| 54 | + /// Optional message from the donor |
| 55 | + pub message: Option<String>, |
| 56 | + /// Timestamp when the donation was made |
| 57 | + pub donated_at_ms: TimestampMs, |
| 58 | + /// ID of the account receiving the donation |
| 59 | + pub recipient_id: AccountId, |
| 60 | + /// Protocol fee |
| 61 | + pub protocol_fee: U128, |
| 62 | + /// Referrer ID |
| 63 | + pub referrer_id: Option<AccountId>, |
| 64 | + /// Referrer fee |
| 65 | + pub referrer_fee: Option<U128>, |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +### Contract Source Metadata |
| 70 | + |
| 71 | +_NB: Below implemented as per NEP 0330 (https://github.com/near/NEPs/blob/master/neps/nep-0330.md), with addition of `commit_hash`_ |
| 72 | + |
| 73 | +```rs |
| 74 | +pub struct ContractSourceMetadata { |
| 75 | + /// Version of source code, e.g. "v1.0.0", could correspond to Git tag |
| 76 | + pub version: String, |
| 77 | + /// Git commit hash of currently deployed contract code |
| 78 | + pub commit_hash: String, |
| 79 | + /// GitHub repo url for currently deployed contract code |
| 80 | + pub link: String, |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +## Methods |
| 85 | + |
| 86 | +### Write Methods |
| 87 | + |
| 88 | +```rs |
| 89 | +// DONATIONS |
| 90 | + |
| 91 | +#[payable] |
| 92 | +pub fn donate( |
| 93 | + &mut self, |
| 94 | + recipient_id: AccountId, |
| 95 | + message: Option<String>, |
| 96 | + referrer_id: Option<AccountId>, |
| 97 | +) -> Donation |
| 98 | + |
| 99 | +// OWNER |
| 100 | + |
| 101 | +#[payable] |
| 102 | +pub fn owner_change_owner(&mut self, owner: AccountId) |
| 103 | + |
| 104 | +pub fn owner_set_protocol_fee_basis_points(&mut self, protocol_fee_basis_points: u32) |
| 105 | + |
| 106 | +pub fn owner_set_referral_fee_basis_points(&mut self, referral_fee_basis_points: u32) |
| 107 | + |
| 108 | +pub fn owner_set_protocol_fee_recipient_account(&mut self, protocol_fee_recipient_account: AccountId) |
| 109 | + |
| 110 | +// SOURCE METADATA |
| 111 | + |
| 112 | +pub fn self_set_source_metadata(&mut self, source_metadata: ContractSourceMetadata) // only callable by the contract account (reasoning is that this should be able to be updated by the same account that can deploy code to the account) |
| 113 | + |
| 114 | +``` |
| 115 | + |
| 116 | +### Read Methods |
| 117 | + |
| 118 | +```rs |
| 119 | +// CONFIG |
| 120 | + |
| 121 | +pub fn get_config(&self) -> Config |
| 122 | + |
| 123 | +// DONATIONS |
| 124 | +pub fn get_donations(&self, from_index: Option<u128>, limit: Option<u64>) -> Vec<Donation> |
| 125 | + |
| 126 | +pub fn get_donation_by_id(&self, donation_id: DonationId) -> Option<Donation> |
| 127 | + |
| 128 | +pub fn get_donations_for_recipient( |
| 129 | + &self, |
| 130 | + recipient_id: AccountId, |
| 131 | + from_index: Option<u128>, |
| 132 | + limit: Option<u64>, |
| 133 | + ) -> Vec<Donation> |
| 134 | + |
| 135 | +pub fn get_donations_for_donor( |
| 136 | + &self, |
| 137 | + donor_id: AccountId, |
| 138 | + from_index: Option<u128>, |
| 139 | + limit: Option<u64>, |
| 140 | +) -> Vec<Donation> |
| 141 | + |
| 142 | +pub fn get_donations_for_ft( |
| 143 | + &self, |
| 144 | + ft_id: AccountId, |
| 145 | + from_index: Option<u128>, |
| 146 | + limit: Option<u64>, |
| 147 | +) -> Vec<Donation> |
| 148 | + |
| 149 | +// OWNER |
| 150 | + |
| 151 | +pub fn get_owner(&self) -> AccountId |
| 152 | + |
| 153 | +// SOURCE METADATA |
| 154 | + |
| 155 | +pub fn get_contract_source_metadata(&self) -> Option<ContractSourceMetadata> |
| 156 | +``` |
| 157 | + |
| 158 | +## Events |
| 159 | + |
| 160 | +### `donation` |
| 161 | + |
| 162 | +Indicates that a `Donation` object has been created. |
| 163 | + |
| 164 | +**Example:** |
| 165 | + |
| 166 | +```json |
| 167 | +{ |
| 168 | + "standard": "potlock", |
| 169 | + "version": "1.0.0", |
| 170 | + "event": "donation", |
| 171 | + "data": [ |
| 172 | + { |
| 173 | + "donation": { |
| 174 | + "donated_at_ms": 1698948121940, |
| 175 | + "donor_id":"lachlan.near", |
| 176 | + "ft_id":"near", |
| 177 | + "id":9, |
| 178 | + "message": "Go go go!", |
| 179 | + "protocol_fee": "7000000000000000000000", |
| 180 | + "recipient_id": "magicbuild.near", |
| 181 | + "referrer_fee": "2000000000000000000000", |
| 182 | + "referrer_id": "plugrel.near", |
| 183 | + "total_amount": "100000000000000000000000" |
| 184 | + }, |
| 185 | + } |
| 186 | + ] |
| 187 | +} |
| 188 | +``` |
| 189 | + |
| 190 | +### `set_source_metadata` |
| 191 | + |
| 192 | +Indicates that `ContractSourceMetadata` object has been set/updated. |
| 193 | + |
| 194 | +**Example:** |
| 195 | + |
| 196 | +```json |
| 197 | +{ |
| 198 | + "standard": "potlock", |
| 199 | + "version": "1.0.0", |
| 200 | + "event": "set_source_metadata", |
| 201 | + "data": [ |
| 202 | + { |
| 203 | + "source_metadata": { |
| 204 | + "commit_hash":"ec02294253b22c2d4c50a75331df23ada9eb04db", |
| 205 | + "link":"https://github.com/PotLock/core", |
| 206 | + "version":"0.1.0", |
| 207 | + } |
| 208 | + } |
| 209 | + ] |
| 210 | +} |
| 211 | +``` |
0 commit comments