// TODO: Update this readme to be relevant for this Rust repo.
See original project written in AssemblyScript at https://github.com/ryancwalsh/donation-matching
Someone (let's call them "Matcher") wants to pledge to match donations to a certain account (the "Recipient") and says "I'll match donations up to X amount." So he/she sends the max amount to the controlling contract (sort of like escrow) and earmarks those funds for Recipient.
For simplicity (to avoid complexity of expiration dates and cron jobs and whatever), any Matcher can at any time rescind any unclaimed funds. If the promised funds from that Matcher towards a specific Recipient become 0, the Matcher is removed (is no longer listed as a Matcher related to that Recipient).
Any other account (other Donors) can choose to donate to the Recipient account (via the controlling contract, which is this project).
On each donation:
- Funds that the Donor deposited into this escrow contract get transferred immediately to the Recipient.
- For each and every "Matcher" account currently associated with the Recipient, the following happens:
- This escrow contract will automatically transfer to the Recipient an amount (called "matchedAmount") that equals the minimum of the donor's donated amount and that Matcher's remaining commitment to this Recipient.
- The Matcher's commitment will be decreased by that "matchedAmount".
- clone this repo to a local folder
cargo install raen
- // TODO
- Read https://docs.near.org/docs/tools/near-cli#near-call and decide whether you want to use
--depositYocto
or--deposit
in the steps below.
export NEAR_ENV=local
- [how to deploy contract locally?]
near dev-deploy $(raen build --release -q)
near create-account justatemporarylocalaccount.node0 --masterAccount node0 --initialBalance 1000 --keyPath ~/.near/localnet/node0/validator_key.json
near create-account recipient.justatemporarylocalaccount.node0 --masterAccount justatemporarylocalaccount.node0 --initialBalance 1
near create-account matcher1.justatemporarylocalaccount.node0 --masterAccount justatemporarylocalaccount.node0 --initialBalance 1
near create-account matcher2.justatemporarylocalaccount.node0 --masterAccount justatemporarylocalaccount.node0 --initialBalance 1
near create-account donor.justatemporarylocalaccount.node0 --masterAccount justatemporarylocalaccount.node0 --initialBalance 1
export PARENT=justatemporarylocalaccount.node0
export MATCHER1=matcher1.justatemporarylocalaccount.node0
export MATCHER2=matcher2.justatemporarylocalaccount.node0
export RECIPIENT=recipient.justatemporarylocalaccount.node0
export DONOR=donor.justatemporarylocalaccount.node0
-
export NEAR_ENV=testnet
-
near dev-deploy $(raen build --release -q)
orcargo build --target wasm32-unknown-unknown --release && near dev-deploy target/wasm32-unknown-unknown/release/donation_matcher_contract.wasm
-
Run something like
export CONTRACT=dev-1638053233399-4079004334
. -
near call $CONTRACT new --accountId $CONTRACT --gas=15000000000000
-
You will need at least 3 other NEAR accounts: one to act as a recipient (such as a charity), one to act as a regular donor, and one to act as a "matcher" (someone who commits to match others' donations to a certain recipient).
- If you don't already have 3 testnet accounts that you want to use, you can create one (to serve as Matcher) at https://wallet.testnet.near.org/. Then you can create RECIPIENT and DONOR accounts as sub-accounts of that one. E.g.:
near create-account recipient_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 near create-account matcher1_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 near create-account matcher2_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 near create-account donor_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1
-
Call
export
commands to define RECIPIENT, MATCHER, and DONOR with the accountIds from the previous steps. E.g.:export PARENT=ryancwalsh.testnet export MATCHER1=matcher1_b.ryancwalsh.testnet export MATCHER2=matcher2_b.ryancwalsh.testnet export RECIPIENT=recipient_b.ryancwalsh.testnet export DONOR=donor_b.ryancwalsh.testnet
near state $MATCHER1 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $MATCHER2 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $RECIPIENT | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $DONOR | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near call $CONTRACT offer_matching_funds "{\"recipient\": \"$RECIPIENT\"}" --accountId $MATCHER1 --deposit .3 --gas=15000000000000
near call $CONTRACT offer_matching_funds "{\"recipient\": \"$RECIPIENT\"}" --accountId $MATCHER2 --deposit .1 --gas=15000000000000
near view $CONTRACT get_commitments "{\"recipient\": \"$RECIPIENT\"}"
near state $MATCHER1 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $MATCHER2 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
In the approximate expected amounts below (denoted with ~
), consider that the amounts will actually be slightly less because some funds will have been sacrificed as gas costs.
(The result should reflect the values from above, and the CLI/Explorer should now also show Matcher1's balance as ~0.7 and Matcher2's balance as ~0.9.)
near call $CONTRACT rescind_matching_funds "{\"recipient\": \"$RECIPIENT\", \"requested_withdrawal_amount\": \"0.02 Ⓝ\"}" --accountId $MATCHER1 --gas=90000000000000
near view $CONTRACT get_commitments "{\"recipient\": \"$RECIPIENT\"}"
near state $MATCHER1 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
(Matcher1 should now only have 0.30 - 0.02 = 0.28 committed to this Recipient. The CLI/Explorer should now also show Matcher1's balance as ~0.72.)
near call $CONTRACT donate "{\"recipient\": \"$RECIPIENT\"}" --accountId $DONOR --deposit .1 --gas 300000000000000
near state $MATCHER1 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $MATCHER2 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $RECIPIENT | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near state $DONOR | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near view $CONTRACT get_commitments "{\"recipient\": \"$RECIPIENT\"}"
(Only Matcher1 should be committed to 0.28 - 0.1 = 0.18. Matcher2 no longer has funds committed.)
(The CLI/Explorer should now show: Recipient's balance as 1 + (0.1 * 3) = 1.3 exactly. Matcher1's balance as still ~0.72. Matcher2's balance as still ~0.9. Donor's balance is ~0.9.)
near call $CONTRACT rescind_matching_funds "{\"recipient\": \"$RECIPIENT\", \"requested_withdrawal_amount\": \"999 Ⓝ\"}" --accountId $MATCHER1 --gas=90000000000000
near state $MATCHER1 | sed -n "s/.*formattedAmount: '\([^\\]*\).*'/\1/p"
near view $CONTRACT get_commitments "{\"recipient\": \"$RECIPIENT\"}"
(The CLI/Explorer should now show Matcher1's balance as ~0.702 + 0.198 = ~0.9 and get_commitments as empty.)
Optionally nuke the match relationships if they weren't already emptied: near call $CONTRACT delete_all_matches_associated_with_recipient "{\"recipient\": \"$RECIPIENT\"}" --accountId $CONTRACT --gas=15000000000000
Optionally clean up accounts with:
near delete $DONOR $PARENT
near delete $RECIPIENT $PARENT
near delete $MATCHER1 $PARENT
near delete $MATCHER2 $PARENT
near delete $CONTRACT $PARENT
Or do recreate all in one line and dev-deploy and delete_all_matches_associated_with_recipient:
near delete $DONOR $PARENT && near delete $RECIPIENT $PARENT && near delete $MATCHER1 $PARENT && near delete $MATCHER2 $PARENT && near create-account recipient_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 && near create-account matcher1_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 && near create-account matcher2_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 && near create-account donor_b.ryancwalsh.testnet --masterAccount ryancwalsh.testnet --initialBalance 1 && near dev-deploy $(raen build --release -q) && near call $CONTRACT delete_all_matches_associated_with_recipient "{\"recipient\": \"$RECIPIENT\"}" --accountId $CONTRACT --gas=15000000000000