diff --git a/token/README.md b/token/README.md index f1509b7..d1aa9f6 100644 --- a/token/README.md +++ b/token/README.md @@ -27,6 +27,8 @@ The `.env` file contains a private key and address. This is the account that wil * [Step 3: Private Transfer](#step3) * [Step 4: Public to Private Transfer](#step4) * [Step 5: Private to Public Transfer](#step5) +* [Step 6: Public Burn](#step6) +* [Step 7: Private Burn](#step7) We'll be conducting a transfer between two parties. @@ -137,3 +139,33 @@ leo run transfer_private_to_public "{ ``` When we call `transfer_private_to_public`, we take Bob's private record that contains 110 tokens, and outputs a record owned by Bob with 70 tokens, and calls the finalize function under `transfer_private_to_public` with Alice's address and 40 tokens as arguments. This changes the public mapping under Alice's address to contain 100 public tokens. Again, public mappings are queryable on-chain. + +## Public Burn + +Let's burn 30 of Alice's public tokens. Switch the private key back to Alice. + +```bash +echo " +NETWORK=testnet3 +PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR +" > .env + +leo run burn_public 30u64 +``` + +The output of the finalize function of `burn_public`, which takes the arguments Alice's address and the amount of tokens to burn publicly. This information is shown on-chain and can be queried on a network. + +## Private Burn + +Now let's privately burn 20 tokens for Bob. Switch to Bob's private key and privately burn 20 tokens for Bob. + +```bash +echo " +NETWORK=testnet3 +PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF +" > .env + +leo run burn_private 20u64 +``` + +The output is a private record. diff --git a/token/build/main.aleo b/token/build/main.aleo index 8f45b49..be567e8 100644 --- a/token/build/main.aleo +++ b/token/build/main.aleo @@ -12,7 +12,8 @@ mapping account: function mint_public: input r0 as address.public; input r1 as u64.public; - async mint_public r0 r1 into r2; output r2 as token.aleo/mint_public.future; + async mint_public r0 r1 into r2; + output r2 as token.aleo/mint_public.future; finalize mint_public: input r0 as address.public; @@ -32,7 +33,8 @@ function mint_private: function transfer_public: input r0 as address.public; input r1 as u64.public; - async transfer_public self.caller r0 r1 into r2; output r2 as token.aleo/transfer_public.future; + async transfer_public self.caller r0 r1 into r2; + output r2 as token.aleo/transfer_public.future; finalize transfer_public: input r0 as address.public; @@ -63,7 +65,8 @@ function transfer_private_to_public: input r2 as u64.public; sub r0.amount r2 into r3; cast r0.owner r3 into r4 as token.record; - async transfer_private_to_public r1 r2 into r5; output r4 as token.record; + async transfer_private_to_public r1 r2 into r5; + output r4 as token.record; output r5 as token.aleo/transfer_private_to_public.future; finalize transfer_private_to_public: @@ -78,7 +81,8 @@ function transfer_public_to_private: input r0 as address.public; input r1 as u64.public; cast r0 r1 into r2 as token.record; - async transfer_public_to_private self.caller r1 into r3; output r2 as token.record; + async transfer_public_to_private self.caller r1 into r3; + output r2 as token.record; output r3 as token.aleo/transfer_public_to_private.future; finalize transfer_public_to_private: @@ -87,3 +91,24 @@ finalize transfer_public_to_private: get.or_use account[r0] 0u64 into r2; sub r2 r1 into r3; set r3 into account[r0]; + + +function burn_public: + input r0 as u64.public; + cast self.caller r0 into r1 as token.record; + async burn_public self.caller r0 into r2; + output r1 as token.record; + output r2 as token.aleo/burn_public.future; + +finalize burn_public: + input r0 as address.public; + input r1 as u64.public; + get.or_use account[r0] 0u64 into r2; + sub r2 r1 into r3; + set r3 into account[r0]; + + +function burn_private: + input r0 as u64.private; + cast self.caller r0 into r1 as token.record; + output r1 as token.record; diff --git a/token/run.sh b/token/run.sh index 99e76d9..3abb9ad 100755 --- a/token/run.sh +++ b/token/run.sh @@ -311,3 +311,96 @@ When we call transfer_private_to_public, we take Bob's private record that conta ######## ######## ############################################################################### " + +echo " +Let's burn 30 of Alice's public tokens. Switch the private key back to Alice. + +echo ' +NETWORK=testnet3 +PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR +' > .env + +leo run burn_public 30u64 +" + +echo " +NETWORK=testnet3 +PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR +" > .env + +leo run burn_public 30u64 + +echo " +When we call burn_public, we take Alice's public record that contains 100 tokens, and outputs a record owned by Alice with 70 tokens, and calls the finalize function under burn_public with Alice's address via "self.caller" and 30 tokens as arguments. This changes the public mapping under Alice's address to contain 70 public tokens. Again, public mappings are queryable on-chain. + +############################################################################### +######## ######## +######## STEP 6: Burn 30 of Alice's public tokens ######## +######## ######## +######## ----------------------------------------- ######## +######## | PUBLIC BALANCES | ######## +######## ----------------------------------------- ######## +######## ----------------------------------------- ######## +######## | Alice | 70 | ######## +######## ----------------------------------------- ######## +######## | Bob | 10 | ######## +######## ----------------------------------------- ######## +######## ######## +######## ----------------------------------------- ######## +######## | PRIVATE BALANCES | ######## +######## ----------------------------------------- ######## +######## ----------------------------------------- ######## +######## | Alice | 20 | ######## +######## ----------------------------------------- ######## +######## | Bob | 70 | ######## +######## ----------------------------------------- ######## +######## ######## +############################################################################### +" + + +echo " +Now let's privately burn 20 tokens for Bob. Switch to Bob's private key and privately burn 20 tokens for Bob. + +echo ' +NETWORK=testnet3 +PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF +' > .env + +leo run burn_private 20u64 +" + +echo " +NETWORK=testnet3 +PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF +" > .env + +leo run burn_private 20u64 + +echo " +When burn_private is called by Bob, the output is a private record where Bob's 20 tokens from his private balance will be deducted. + +############################################################################### +######## ######## +######## STEP 7: Burn 20 of Alice's private tokens ######## +######## ######## +######## ----------------------------------------- ######## +######## | PUBLIC BALANCES | ######## +######## ----------------------------------------- ######## +######## ----------------------------------------- ######## +######## | Alice | 70 | ######## +######## ----------------------------------------- ######## +######## | Bob | 10 | ######## +######## ----------------------------------------- ######## +######## ######## +######## ----------------------------------------- ######## +######## | PRIVATE BALANCES | ######## +######## ----------------------------------------- ######## +######## ----------------------------------------- ######## +######## | Alice | 20 | ######## +######## ----------------------------------------- ######## +######## | Bob | 50 | ######## +######## ----------------------------------------- ######## +######## ######## +############################################################################### +" \ No newline at end of file diff --git a/token/src/main.leo b/token/src/main.leo index 58a02cd..495236d 100644 --- a/token/src/main.leo +++ b/token/src/main.leo @@ -126,4 +126,34 @@ program token.aleo { let sender_amount: u64 = Mapping::get_or_use(account, sender, 0u64); Mapping::set(account, sender, sender_amount - amount); } + + transition burn_public(public amount: u64) -> token { + // Produce a burn token record for the token receiver. + let burn: token = token { + owner: self.caller, + amount: amount + }; + + // Output the burnt record. + // Decrement the token amount of the caller publicly + return burn then finalize(self.caller, amount); + } + + finalize burn_public(public sender: address, public amount: u64) { + // Decrements `acount[sender]` by `amount` + // If `account[sender]` does not exist, it will be created (Technically should already be created) + // If `account[sender] - amount` underflows, `burnt_public` is reverted. + let sender_amount: u64 = Mapping::get_or_use(account, sender, 0u64); + Mapping::set(account, sender, sender_amount - amount); + } + + transition burn_private(amount: u64) -> token { + // Produce a burn token record for the token receiver. + let burn: token = token { + owner: self.caller, + amount: amount + }; + + return burn; + } }