├── .gitignore ├── 0.base ├── .gitignore ├── program.json ├── README.md └── src │ └── main.leo ├── 4.kyc ├── .gitignore ├── program.json ├── README.md ├── imports │ ├── zpass.leo │ └── multisig.leo └── src │ └── main.leo ├── 1.restricted-mint-hardcoded ├── .gitignore ├── program.json ├── README.md └── src │ └── main.leo ├── 2.restricted-mint-owner ├── .gitignore ├── program.json ├── README.md └── src │ └── main.leo ├── 3.restricted-mint-multisig ├── .gitignore ├── program.json ├── README.md ├── src │ └── main.leo └── imports │ └── multisig.leo ├── 5.public-asset-freezing ├── .gitignore ├── program.json ├── README.md ├── imports │ ├── zpass.leo │ └── multisig.leo └── src │ └── main.leo ├── 6.pausability-upgradeability ├── .gitignore ├── program.json ├── README.md ├── placeholder │ └── token.leo ├── imports │ ├── zpass.leo │ ├── multisig.leo │ └── token.leo ├── build.sh └── src │ └── main.leo └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .idea 3 | .env 4 | -------------------------------------------------------------------------------- /0.base/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /4.kyc/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /1.restricted-mint-hardcoded/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /2.restricted-mint-owner/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /3.restricted-mint-multisig/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /5.public-asset-freezing/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.avm 3 | *.prover 4 | *.verifier 5 | outputs/ 6 | -------------------------------------------------------------------------------- /4.kyc/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /0.base/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /2.restricted-mint-owner/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /5.public-asset-freezing/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /1.restricted-mint-hardcoded/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /3.restricted-mint-multisig/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "token.aleo", 3 | "version": "0.0.0", 4 | "description": "", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Workshop presentation link 2 | https://docs.google.com/presentation/d/1JIyJQ8tff-ptwXCeinQr9NDXzFG7E3jvou_3MIPDNJM 3 | https://docs.google.com/presentation/d/1lvoEhvNXz3D4biH3UJN6LVLW1QCZDhH1xGYOFqSTlWY 4 | -------------------------------------------------------------------------------- /0.base/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /4.kyc/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /2.restricted-mint-owner/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /3.restricted-mint-multisig/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /5.public-asset-freezing/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /1.restricted-mint-hardcoded/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/README.md: -------------------------------------------------------------------------------- 1 | # base.aleo 2 | 3 | ## Build Guide 4 | 5 | To compile this Aleo program, run: 6 | ```bash 7 | snarkvm build 8 | ``` 9 | 10 | To execute this Aleo program, run: 11 | ```bash 12 | snarkvm run hello 13 | ``` 14 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/placeholder/token.leo: -------------------------------------------------------------------------------- 1 | 2 | program token.aleo { 3 | record token { 4 | owner: address, 5 | amount: u64, 6 | } 7 | 8 | transition add(a: u64, b: u64) -> u64 { 9 | return a + b; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /4.kyc/imports/zpass.leo: -------------------------------------------------------------------------------- 1 | 2 | 3 | program zpass.aleo { 4 | record identity { 5 | owner: address, 6 | age: u8, 7 | nationality: field, 8 | } 9 | 10 | transition mint_identity(age: u8, nationality: field) -> identity { 11 | return identity { 12 | owner: self.caller, 13 | age: age, 14 | nationality: nationality, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /5.public-asset-freezing/imports/zpass.leo: -------------------------------------------------------------------------------- 1 | 2 | 3 | program zpass.aleo { 4 | record identity { 5 | owner: address, 6 | age: u8, 7 | nationality: field, 8 | } 9 | 10 | transition mint_identity(age: u8, nationality: field) -> identity { 11 | return identity { 12 | owner: self.caller, 13 | age: age, 14 | nationality: nationality, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/imports/zpass.leo: -------------------------------------------------------------------------------- 1 | 2 | 3 | program zpass.aleo { 4 | record identity { 5 | owner: address, 6 | age: u8, 7 | nationality: field, 8 | } 9 | 10 | transition mint_identity(age: u8, nationality: field) -> identity { 11 | return identity { 12 | owner: self.caller, 13 | age: age, 14 | nationality: nationality, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/build.sh: -------------------------------------------------------------------------------- 1 | mkdir tmp 2 | 3 | function copy_all() { 4 | rm -rf tmp 5 | 6 | mkdir tmp 7 | 8 | cp -rf src tmp/src 9 | cp -rf imports tmp/imports 10 | cp program.json tmp/program.json 11 | } 12 | 13 | # Build token 14 | copy_all 15 | mv tmp/imports/token.leo src/main.leo 16 | echo '{ 17 | "program": "token.aleo", 18 | "version": "0.0.0", 19 | "description": "", 20 | "license": "MIT" 21 | }' > tmp/program.json 22 | cd tmp && leo build && cd .. 23 | cp -rf tmp/build/ build/ 24 | cp tmp/build/main.aleo build/imports/token.aleo 25 | 26 | # Build new token 27 | copy_all 28 | cp placeholder/token.leo tmp/imports/token.leo 29 | cd tmp && leo build && cd .. 30 | cp tmp/build/main.aleo build/main.aleo 31 | 32 | # Cleanup 33 | rm -rf tmp 34 | -------------------------------------------------------------------------------- /0.base/src/main.leo: -------------------------------------------------------------------------------- 1 | program token.aleo { 2 | record token { 3 | owner: address, 4 | amount: u64, 5 | } 6 | 7 | transition mint(receiver: address, amount: u64) -> token { 8 | return token { 9 | owner: receiver, 10 | amount: amount, 11 | }; 12 | } 13 | 14 | transition transfer(sender: token, receiver: address, amount: u64) -> (token, token) { 15 | let difference: u64 = sender.amount - amount; 16 | 17 | let remaining: token = token { 18 | owner: sender.owner, 19 | amount: difference, 20 | }; 21 | 22 | let transferred: token = token { 23 | owner: receiver, 24 | amount: amount, 25 | }; 26 | 27 | return (remaining, transferred); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /1.restricted-mint-hardcoded/src/main.leo: -------------------------------------------------------------------------------- 1 | program token.aleo { 2 | 3 | record token { 4 | owner: address, 5 | amount: u64, 6 | } 7 | 8 | transition mint(receiver: address, amount: u64) -> token { 9 | assert_eq(self.caller, aleo1n34an9qj0h732pceqct0ery9g2u6vgeut4xzgnxzjr72xmnl4yps8wlzul); 10 | 11 | return token { 12 | owner: receiver, 13 | amount: amount, 14 | }; 15 | } 16 | 17 | transition transfer(sender: token, receiver: address, amount: u64) -> (token, token) { 18 | let difference: u64 = sender.amount - amount; 19 | 20 | let remaining: token = token { 21 | owner: sender.owner, 22 | amount: difference, 23 | }; 24 | 25 | let transferred: token = token { 26 | owner: receiver, 27 | amount: amount, 28 | }; 29 | 30 | return (remaining, transferred); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /3.restricted-mint-multisig/src/main.leo: -------------------------------------------------------------------------------- 1 | import multisig.leo; 2 | 3 | program token.aleo { 4 | const MINT_FN: field = 1field; 5 | 6 | record token { 7 | owner: address, 8 | amount: u64, 9 | } 10 | 11 | struct MintArgs { 12 | receiver: address, 13 | amount: u64, 14 | } 15 | 16 | transition mint(ticket_: multisig.leo/ticket.record, args: MintArgs) -> token { 17 | assert_eq( 18 | ticket_.program_address, 19 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 20 | ); 21 | assert_eq(ticket_.function_id, MINT_FN); 22 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(args)); 23 | multisig.leo/burn(ticket_); 24 | 25 | return token { 26 | owner: args.receiver, 27 | amount: args.amount, 28 | }; 29 | } 30 | 31 | transition transfer(sender: token, receiver: address, amount: u64) -> (token, token) { 32 | let difference: u64 = sender.amount - amount; 33 | 34 | let remaining: token = token { 35 | owner: sender.owner, 36 | amount: difference, 37 | }; 38 | 39 | let transferred: token = token { 40 | owner: receiver, 41 | amount: amount, 42 | }; 43 | 44 | return (remaining, transferred); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /2.restricted-mint-owner/src/main.leo: -------------------------------------------------------------------------------- 1 | program token.aleo { 2 | mapping owner_: bool => address; 3 | mapping pending_owner: bool => address; 4 | 5 | record token { 6 | owner: address, 7 | amount: u64, 8 | } 9 | 10 | transition transfer_owner(new_owner: address) { 11 | return then finalize(self.caller, new_owner); 12 | } 13 | 14 | finalize transfer_owner(caller: address, new_owner: address) { 15 | assert_eq(Mapping::get_or_use(owner_, true, caller), caller); 16 | Mapping::set(pending_owner, true, new_owner); 17 | } 18 | 19 | transition accept_owner() { 20 | return then finalize(self.caller); 21 | } 22 | 23 | finalize accept_owner(new_owner: address) { 24 | assert_eq(Mapping::get(pending_owner, true), new_owner); 25 | Mapping::set(owner_, true, new_owner); 26 | } 27 | 28 | transition mint(receiver: address, amount: u64) -> token { 29 | return token { 30 | owner: receiver, 31 | amount: amount, 32 | } then finalize(self.caller); 33 | } 34 | 35 | finalize mint(caller: address) { 36 | assert_eq(Mapping::get(owner_, true), caller); 37 | } 38 | 39 | transition transfer(sender: token, receiver: address, amount: u64) -> (token, token) { 40 | let difference: u64 = sender.amount - amount; 41 | 42 | let remaining: token = token { 43 | owner: sender.owner, 44 | amount: difference, 45 | }; 46 | 47 | let transferred: token = token { 48 | owner: receiver, 49 | amount: amount, 50 | }; 51 | 52 | return (remaining, transferred); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /4.kyc/src/main.leo: -------------------------------------------------------------------------------- 1 | import multisig.leo; 2 | import zpass.leo; 3 | 4 | program token.aleo { 5 | const MINT_FN: field = 1field; 6 | const REGISTER_MULTISIG_FN: field = 2field; 7 | 8 | record token { 9 | owner: address, 10 | amount: u64, 11 | } 12 | 13 | record kyc { 14 | owner: address, 15 | } 16 | 17 | struct MintArgs { 18 | receiver: address, 19 | amount: u64, 20 | } 21 | 22 | transition mint(ticket_: multisig.leo/ticket.record, args: MintArgs) -> token { 23 | assert_eq( 24 | ticket_.program_address, 25 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 26 | ); 27 | assert_eq(ticket_.function_id, MINT_FN); 28 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(args)); 29 | multisig.leo/burn(ticket_); 30 | 31 | return token { 32 | owner: args.receiver, 33 | amount: args.amount, 34 | }; 35 | } 36 | 37 | transition transfer(kyc_: kyc, sender: token, receiver: address, amount: u64) -> (kyc, token, token) { 38 | let difference: u64 = sender.amount - amount; 39 | 40 | let remaining: token = token { 41 | owner: sender.owner, 42 | amount: difference, 43 | }; 44 | 45 | let transferred: token = token { 46 | owner: receiver, 47 | amount: amount, 48 | }; 49 | 50 | return (kyc { owner: kyc_.owner }, remaining, transferred); 51 | } 52 | 53 | transition register_zpass(identity_: zpass.leo/identity.record) -> kyc { 54 | assert(identity_.age >= 18u8); 55 | 56 | if (identity_.nationality == 1field) { 57 | assert(identity_.age >= 21u8); 58 | } 59 | 60 | if (identity_.nationality == 2field) { 61 | // etc 62 | } 63 | 64 | return kyc { owner: self.caller }; 65 | } 66 | 67 | transition register_multisig(ticket_: multisig.leo/ticket.record, receiver: address) -> kyc { 68 | assert_eq( 69 | ticket_.program_address, 70 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 71 | ); 72 | assert_eq(ticket_.function_id, REGISTER_MULTISIG_FN); 73 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(receiver)); 74 | multisig.leo/burn(ticket_); 75 | 76 | return kyc { owner: receiver }; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /4.kyc/imports/multisig.leo: -------------------------------------------------------------------------------- 1 | program multisig.aleo { 2 | const ADD_SIGNER_FN: field = 1field; 3 | const CHANGE_REQUIRED_SIGNATURES_FN: field = 2field; 4 | 5 | mapping required_signatures: bool => u64; 6 | mapping proposals: Proposal => u64; 7 | mapping signers: address => bool; 8 | 9 | struct Proposal { 10 | program_address: address, 11 | function_id: field, 12 | args_hash: field, 13 | } 14 | 15 | record ticket { 16 | owner: address, 17 | program_address: address, 18 | function_id: field, 19 | args_hash: field, 20 | } 21 | 22 | transition mint_ticket(proposal: Proposal) -> ticket { 23 | return ticket { 24 | owner: self.caller, 25 | program_address: proposal.program_address, 26 | function_id: proposal.function_id, 27 | args_hash: proposal.args_hash, 28 | } then finalize(proposal); 29 | } 30 | 31 | finalize mint_ticket(proposal: Proposal) { 32 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 33 | let min_signatures: u64 = Mapping::get_or_use(required_signatures, true, 0u64); 34 | assert(signatures >= min_signatures); 35 | Mapping::set(proposals, proposal, 0u64); 36 | } 37 | 38 | transition sign(proposal: Proposal) { 39 | return then finalize(self.caller, proposal); 40 | } 41 | 42 | finalize sign(caller: address, proposal: Proposal) { 43 | assert(Mapping::get(signers, caller)); 44 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 45 | Mapping::set(proposals, proposal, signatures + 1u64); 46 | } 47 | 48 | transition add_signer(ticket_: ticket, new_signer: address) { 49 | assert_eq( 50 | ticket_.program_address, 51 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 52 | ); 53 | assert_eq(ticket_.function_id, ADD_SIGNER_FN); 54 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_signer)); 55 | return then finalize(new_signer); 56 | } 57 | 58 | finalize add_signer(new_signer: address) { 59 | Mapping::set(signers, new_signer, true); 60 | } 61 | 62 | transition change_required_signatures(ticket_: ticket, new_required_signatures: u64) { 63 | assert_eq( 64 | ticket_.program_address, 65 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 66 | ); 67 | assert_eq(ticket_.function_id, CHANGE_REQUIRED_SIGNATURES_FN); 68 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_required_signatures)); 69 | 70 | return then finalize(new_required_signatures); 71 | } 72 | 73 | finalize change_required_signatures(new_required_signatures: u64) { 74 | Mapping::set(required_signatures, true, new_required_signatures); 75 | } 76 | 77 | transition burn(ticket_: ticket) {} 78 | } 79 | -------------------------------------------------------------------------------- /5.public-asset-freezing/imports/multisig.leo: -------------------------------------------------------------------------------- 1 | program multisig.aleo { 2 | const ADD_SIGNER_FN: field = 1field; 3 | const CHANGE_REQUIRED_SIGNATURES_FN: field = 2field; 4 | 5 | mapping required_signatures: bool => u64; 6 | mapping proposals: Proposal => u64; 7 | mapping signers: address => bool; 8 | 9 | struct Proposal { 10 | program_address: address, 11 | function_id: field, 12 | args_hash: field, 13 | } 14 | 15 | record ticket { 16 | owner: address, 17 | program_address: address, 18 | function_id: field, 19 | args_hash: field, 20 | } 21 | 22 | transition mint_ticket(proposal: Proposal) -> ticket { 23 | return ticket { 24 | owner: self.caller, 25 | program_address: proposal.program_address, 26 | function_id: proposal.function_id, 27 | args_hash: proposal.args_hash, 28 | } then finalize(proposal); 29 | } 30 | 31 | finalize mint_ticket(proposal: Proposal) { 32 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 33 | let min_signatures: u64 = Mapping::get_or_use(required_signatures, true, 0u64); 34 | assert(signatures >= min_signatures); 35 | Mapping::set(proposals, proposal, 0u64); 36 | } 37 | 38 | transition sign(proposal: Proposal) { 39 | return then finalize(self.caller, proposal); 40 | } 41 | 42 | finalize sign(caller: address, proposal: Proposal) { 43 | assert(Mapping::get(signers, caller)); 44 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 45 | Mapping::set(proposals, proposal, signatures + 1u64); 46 | } 47 | 48 | transition add_signer(ticket_: ticket, new_signer: address) { 49 | assert_eq( 50 | ticket_.program_address, 51 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 52 | ); 53 | assert_eq(ticket_.function_id, ADD_SIGNER_FN); 54 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_signer)); 55 | return then finalize(new_signer); 56 | } 57 | 58 | finalize add_signer(new_signer: address) { 59 | Mapping::set(signers, new_signer, true); 60 | } 61 | 62 | transition change_required_signatures(ticket_: ticket, new_required_signatures: u64) { 63 | assert_eq( 64 | ticket_.program_address, 65 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 66 | ); 67 | assert_eq(ticket_.function_id, CHANGE_REQUIRED_SIGNATURES_FN); 68 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_required_signatures)); 69 | 70 | return then finalize(new_required_signatures); 71 | } 72 | 73 | finalize change_required_signatures(new_required_signatures: u64) { 74 | Mapping::set(required_signatures, true, new_required_signatures); 75 | } 76 | 77 | transition burn(ticket_: ticket) {} 78 | } 79 | -------------------------------------------------------------------------------- /3.restricted-mint-multisig/imports/multisig.leo: -------------------------------------------------------------------------------- 1 | program multisig.aleo { 2 | const ADD_SIGNER_FN: field = 1field; 3 | const CHANGE_REQUIRED_SIGNATURES_FN: field = 2field; 4 | 5 | mapping required_signatures: bool => u64; 6 | mapping proposals: Proposal => u64; 7 | mapping signers: address => bool; 8 | 9 | struct Proposal { 10 | program_address: address, 11 | function_id: field, 12 | args_hash: field, 13 | } 14 | 15 | record ticket { 16 | owner: address, 17 | program_address: address, 18 | function_id: field, 19 | args_hash: field, 20 | } 21 | 22 | transition mint_ticket(proposal: Proposal) -> ticket { 23 | return ticket { 24 | owner: self.caller, 25 | program_address: proposal.program_address, 26 | function_id: proposal.function_id, 27 | args_hash: proposal.args_hash, 28 | } then finalize(proposal); 29 | } 30 | 31 | finalize mint_ticket(proposal: Proposal) { 32 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 33 | let min_signatures: u64 = Mapping::get_or_use(required_signatures, true, 0u64); 34 | assert(signatures >= min_signatures); 35 | Mapping::set(proposals, proposal, 0u64); 36 | } 37 | 38 | transition sign(proposal: Proposal) { 39 | return then finalize(self.caller, proposal); 40 | } 41 | 42 | finalize sign(caller: address, proposal: Proposal) { 43 | assert(Mapping::get(signers, caller)); 44 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 45 | Mapping::set(proposals, proposal, signatures + 1u64); 46 | } 47 | 48 | transition add_signer(ticket_: ticket, new_signer: address) { 49 | assert_eq( 50 | ticket_.program_address, 51 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 52 | ); 53 | assert_eq(ticket_.function_id, ADD_SIGNER_FN); 54 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_signer)); 55 | return then finalize(new_signer); 56 | } 57 | 58 | finalize add_signer(new_signer: address) { 59 | Mapping::set(signers, new_signer, true); 60 | } 61 | 62 | transition change_required_signatures(ticket_: ticket, new_required_signatures: u64) { 63 | assert_eq( 64 | ticket_.program_address, 65 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 66 | ); 67 | assert_eq(ticket_.function_id, CHANGE_REQUIRED_SIGNATURES_FN); 68 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_required_signatures)); 69 | 70 | return then finalize(new_required_signatures); 71 | } 72 | 73 | finalize change_required_signatures(new_required_signatures: u64) { 74 | Mapping::set(required_signatures, true, new_required_signatures); 75 | } 76 | 77 | transition burn(ticket_: ticket) {} 78 | } 79 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/imports/multisig.leo: -------------------------------------------------------------------------------- 1 | program multisig.aleo { 2 | const ADD_SIGNER_FN: field = 1field; 3 | const CHANGE_REQUIRED_SIGNATURES_FN: field = 2field; 4 | 5 | mapping required_signatures: bool => u64; 6 | mapping proposals: Proposal => u64; 7 | mapping signers: address => bool; 8 | 9 | struct Proposal { 10 | program_address: address, 11 | function_id: field, 12 | args_hash: field, 13 | } 14 | 15 | record ticket { 16 | owner: address, 17 | program_address: address, 18 | function_id: field, 19 | args_hash: field, 20 | } 21 | 22 | transition mint_ticket(proposal: Proposal) -> ticket { 23 | return ticket { 24 | owner: self.caller, 25 | program_address: proposal.program_address, 26 | function_id: proposal.function_id, 27 | args_hash: proposal.args_hash, 28 | } then finalize(proposal); 29 | } 30 | 31 | finalize mint_ticket(proposal: Proposal) { 32 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 33 | let min_signatures: u64 = Mapping::get_or_use(required_signatures, true, 0u64); 34 | assert(signatures >= min_signatures); 35 | Mapping::set(proposals, proposal, 0u64); 36 | } 37 | 38 | transition sign(proposal: Proposal) { 39 | return then finalize(self.caller, proposal); 40 | } 41 | 42 | finalize sign(caller: address, proposal: Proposal) { 43 | assert(Mapping::get(signers, caller)); 44 | let signatures: u64 = Mapping::get_or_use(proposals, proposal, 0u64); 45 | Mapping::set(proposals, proposal, signatures + 1u64); 46 | } 47 | 48 | transition add_signer(ticket_: ticket, new_signer: address) { 49 | assert_eq( 50 | ticket_.program_address, 51 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 52 | ); 53 | assert_eq(ticket_.function_id, ADD_SIGNER_FN); 54 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_signer)); 55 | return then finalize(new_signer); 56 | } 57 | 58 | finalize add_signer(new_signer: address) { 59 | Mapping::set(signers, new_signer, true); 60 | } 61 | 62 | transition change_required_signatures(ticket_: ticket, new_required_signatures: u64) { 63 | assert_eq( 64 | ticket_.program_address, 65 | aleo10frku8hz8zyyh03avmr2gjg6zyqz98g2fmcew96a50vxeke995qsuf90f2 // address("multisig.aleo") 66 | ); 67 | assert_eq(ticket_.function_id, CHANGE_REQUIRED_SIGNATURES_FN); 68 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_required_signatures)); 69 | 70 | return then finalize(new_required_signatures); 71 | } 72 | 73 | finalize change_required_signatures(new_required_signatures: u64) { 74 | Mapping::set(required_signatures, true, new_required_signatures); 75 | } 76 | 77 | transition burn(ticket_: ticket) {} 78 | } 79 | -------------------------------------------------------------------------------- /5.public-asset-freezing/src/main.leo: -------------------------------------------------------------------------------- 1 | import multisig.leo; 2 | import zpass.leo; 3 | 4 | program token.aleo { 5 | const MINT_FN: field = 1field; 6 | const REGISTER_MULTISIG_FN: field = 2field; 7 | const FREEZE_ADDRESS_FN: field = 3field; 8 | 9 | mapping frozen_addresses: address => bool; 10 | 11 | record token { 12 | owner: address, 13 | amount: u64, 14 | } 15 | 16 | record kyc { 17 | owner: address, 18 | } 19 | 20 | struct MintArgs { 21 | receiver: address, 22 | amount: u64, 23 | } 24 | 25 | transition mint(ticket_: multisig.leo/ticket.record, args: MintArgs) -> token { 26 | assert_eq( 27 | ticket_.program_address, 28 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 29 | ); 30 | assert_eq(ticket_.function_id, MINT_FN); 31 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(args)); 32 | multisig.leo/burn(ticket_); 33 | 34 | return token { 35 | owner: args.receiver, 36 | amount: args.amount, 37 | }; 38 | } 39 | 40 | transition transfer(kyc_: kyc, sender: token, receiver: address, amount: u64) -> (kyc, token, token) { 41 | let difference: u64 = sender.amount - amount; 42 | 43 | let remaining: token = token { 44 | owner: sender.owner, 45 | amount: difference, 46 | }; 47 | 48 | let transferred: token = token { 49 | owner: receiver, 50 | amount: amount, 51 | }; 52 | 53 | return (kyc { owner: kyc_.owner }, remaining, transferred) then finalize(sender.owner, receiver); 54 | } 55 | 56 | finalize transfer(sender: address, receiver: address) { 57 | assert(!Mapping::get_or_use(frozen_addresses, sender, false)); 58 | assert(!Mapping::get_or_use(frozen_addresses, receiver, false)); 59 | } 60 | 61 | transition register_zpass(identity_: zpass.leo/identity.record) -> kyc { 62 | assert(identity_.age >= 18u8); 63 | 64 | if (identity_.nationality == 1field) { 65 | assert(identity_.age >= 21u8); 66 | } 67 | 68 | if (identity_.nationality == 2field) { 69 | // etc 70 | } 71 | 72 | return kyc { owner: self.caller }; 73 | } 74 | 75 | transition register_multisig(ticket_: multisig.leo/ticket.record, receiver: address) -> kyc { 76 | assert_eq( 77 | ticket_.program_address, 78 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 79 | ); 80 | assert_eq(ticket_.function_id, REGISTER_MULTISIG_FN); 81 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(receiver)); 82 | multisig.leo/burn(ticket_); 83 | 84 | return kyc { owner: receiver }; 85 | } 86 | 87 | transition freeze_address(ticket_: multisig.leo/ticket.record, to_freeze: address) { 88 | assert_eq( 89 | ticket_.program_address, 90 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 91 | ); 92 | assert_eq(ticket_.function_id, FREEZE_ADDRESS_FN); 93 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(to_freeze)); 94 | multisig.leo/burn(ticket_); 95 | 96 | return then finalize(to_freeze); 97 | } 98 | 99 | finalize freeze_address(to_freeze: address) { 100 | Mapping::set(frozen_addresses, to_freeze, true); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/src/main.leo: -------------------------------------------------------------------------------- 1 | import multisig.leo; 2 | import zpass.leo; 3 | 4 | program token.aleo { 5 | const MINT_FN: field = 1field; 6 | const REGISTER_MULTISIG_FN: field = 2field; 7 | const FREEZE_ADDRESS_FN: field = 3field; 8 | const SET_PAUSER_FN: field = 4field; 9 | const UPGRADE_FN: field = 5field; 10 | 11 | mapping frozen_addresses: address => bool; 12 | 13 | mapping pauser: bool => address; 14 | mapping paused: bool => bool; 15 | 16 | mapping next_implementation: bool => address; 17 | 18 | record token { 19 | owner: address, 20 | amount: u64, 21 | } 22 | 23 | record kyc { 24 | owner: address, 25 | } 26 | 27 | struct MintArgs { 28 | receiver: address, 29 | amount: u64, 30 | } 31 | 32 | transition mint(ticket_: multisig.leo/ticket.record, args: MintArgs) -> token { 33 | assert_eq( 34 | ticket_.program_address, 35 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 36 | ); 37 | assert_eq(ticket_.function_id, MINT_FN); 38 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(args)); 39 | multisig.leo/burn(ticket_); 40 | 41 | return token { 42 | owner: args.receiver, 43 | amount: args.amount, 44 | }; 45 | } 46 | 47 | transition burn_private(token_: token) {} 48 | 49 | transition transfer(kyc_: kyc, sender: token, receiver: address, amount: u64) -> (kyc, token, token) { 50 | let difference: u64 = sender.amount - amount; 51 | 52 | let remaining: token = token { 53 | owner: sender.owner, 54 | amount: difference, 55 | }; 56 | 57 | let transferred: token = token { 58 | owner: receiver, 59 | amount: amount, 60 | }; 61 | 62 | return (kyc { owner: kyc_.owner }, remaining, transferred) then finalize(sender.owner, receiver); 63 | } 64 | 65 | finalize transfer(sender: address, receiver: address) { 66 | assert(!Mapping::get_or_use(frozen_addresses, sender, false)); 67 | assert(!Mapping::get_or_use(frozen_addresses, receiver, false)); 68 | assert(!Mapping::get_or_use(paused, true, false)); 69 | } 70 | 71 | transition register_zpass(identity_: zpass.leo/identity.record) -> kyc { 72 | assert(identity_.age >= 18u8); 73 | 74 | if (identity_.nationality == 1field) { 75 | assert(identity_.age >= 21u8); 76 | } 77 | 78 | if (identity_.nationality == 2field) { 79 | // etc 80 | } 81 | 82 | return kyc { owner: self.caller } then finalize(); 83 | } 84 | 85 | finalize register_zpass() { 86 | assert(!Mapping::get_or_use(paused, true, false)); 87 | } 88 | 89 | transition register_multisig(ticket_: multisig.leo/ticket.record, receiver: address) -> kyc { 90 | assert_eq( 91 | ticket_.program_address, 92 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 93 | ); 94 | assert_eq(ticket_.function_id, REGISTER_MULTISIG_FN); 95 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(receiver)); 96 | multisig.leo/burn(ticket_); 97 | 98 | return kyc { owner: receiver }; 99 | } 100 | 101 | transition freeze_address(ticket_: multisig.leo/ticket.record, to_freeze: address) { 102 | assert_eq( 103 | ticket_.program_address, 104 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 105 | ); 106 | assert_eq(ticket_.function_id, FREEZE_ADDRESS_FN); 107 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(to_freeze)); 108 | multisig.leo/burn(ticket_); 109 | 110 | return then finalize(to_freeze); 111 | } 112 | 113 | finalize freeze_address(to_freeze: address) { 114 | Mapping::set(frozen_addresses, to_freeze, true); 115 | } 116 | 117 | transition set_pauser(ticket_: multisig.leo/ticket.record, new_pauser: address) { 118 | assert_eq( 119 | ticket_.program_address, 120 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 121 | ); 122 | assert_eq(ticket_.function_id, SET_PAUSER_FN); 123 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_pauser)); 124 | multisig.leo/burn(ticket_); 125 | 126 | return then finalize(new_pauser); 127 | } 128 | 129 | finalize set_pauser(new_pauser: address) { 130 | Mapping::set(pauser, true, new_pauser); 131 | } 132 | 133 | transition pause() { 134 | return then finalize(self.caller); 135 | } 136 | 137 | finalize pause(caller: address) { 138 | assert_eq(Mapping::get(pauser, true), caller); 139 | Mapping::set(paused, true, true); 140 | } 141 | 142 | transition unpause() { 143 | return then finalize(self.caller); 144 | } 145 | 146 | finalize unpause(caller: address) { 147 | assert_eq(Mapping::get(pauser, true), caller); 148 | Mapping::set(paused, true, false); 149 | } 150 | 151 | transition upgrade(ticket_: multisig.leo/ticket.record, new_implementation: address) { 152 | assert_eq( 153 | ticket_.program_address, 154 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 155 | ); 156 | assert_eq(ticket_.function_id, UPGRADE_FN); 157 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_implementation)); 158 | multisig.leo/burn(ticket_); 159 | 160 | return then finalize(new_implementation); 161 | } 162 | 163 | finalize upgrade(new_implementation: address) { 164 | Mapping::set(next_implementation, true, new_implementation); 165 | Mapping::set(paused, true, true); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /6.pausability-upgradeability/imports/token.leo: -------------------------------------------------------------------------------- 1 | import multisig.leo; 2 | import zpass.leo; 3 | 4 | program token.aleo { 5 | const MINT_FN: field = 1field; 6 | const REGISTER_MULTISIG_FN: field = 2field; 7 | const FREEZE_ADDRESS_FN: field = 3field; 8 | const SET_PAUSER_FN: field = 4field; 9 | const UPGRADE_FN: field = 5field; 10 | 11 | mapping frozen_addresses: address => bool; 12 | 13 | mapping pauser: bool => address; 14 | mapping paused: bool => bool; 15 | 16 | mapping next_implementation: bool => address; 17 | 18 | record token { 19 | owner: address, 20 | amount: u64, 21 | } 22 | 23 | record kyc { 24 | owner: address, 25 | } 26 | 27 | struct MintArgs { 28 | receiver: address, 29 | amount: u64, 30 | } 31 | 32 | transition mint(ticket_: multisig.leo/ticket.record, args: MintArgs) -> token { 33 | assert_eq( 34 | ticket_.program_address, 35 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 36 | ); 37 | assert_eq(ticket_.function_id, MINT_FN); 38 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(args)); 39 | multisig.leo/burn(ticket_); 40 | 41 | return token { 42 | owner: args.receiver, 43 | amount: args.amount, 44 | }; 45 | } 46 | 47 | transition burn_private(token_: token) {} 48 | 49 | transition transfer(kyc_: kyc, sender: token, receiver: address, amount: u64) -> (kyc, token, token) { 50 | let difference: u64 = sender.amount - amount; 51 | 52 | let remaining: token = token { 53 | owner: sender.owner, 54 | amount: difference, 55 | }; 56 | 57 | let transferred: token = token { 58 | owner: receiver, 59 | amount: amount, 60 | }; 61 | 62 | return (kyc { owner: kyc_.owner }, remaining, transferred) then finalize(sender.owner, receiver); 63 | } 64 | 65 | finalize transfer(sender: address, receiver: address) { 66 | assert(!Mapping::get_or_use(frozen_addresses, sender, false)); 67 | assert(!Mapping::get_or_use(frozen_addresses, receiver, false)); 68 | assert(!Mapping::get_or_use(paused, true, false)); 69 | } 70 | 71 | transition register_zpass(identity_: zpass.leo/identity.record) -> kyc { 72 | assert(identity_.age >= 18u8); 73 | 74 | if (identity_.nationality == 1field) { 75 | assert(identity_.age >= 21u8); 76 | } 77 | 78 | if (identity_.nationality == 2field) { 79 | // etc 80 | } 81 | 82 | return kyc { owner: self.caller } then finalize(); 83 | } 84 | 85 | finalize register_zpass() { 86 | assert(!Mapping::get_or_use(paused, true, false)); 87 | } 88 | 89 | transition register_multisig(ticket_: multisig.leo/ticket.record, receiver: address) -> kyc { 90 | assert_eq( 91 | ticket_.program_address, 92 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 93 | ); 94 | assert_eq(ticket_.function_id, REGISTER_MULTISIG_FN); 95 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(receiver)); 96 | multisig.leo/burn(ticket_); 97 | 98 | return kyc { owner: receiver }; 99 | } 100 | 101 | transition freeze_address(ticket_: multisig.leo/ticket.record, to_freeze: address) { 102 | assert_eq( 103 | ticket_.program_address, 104 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 105 | ); 106 | assert_eq(ticket_.function_id, FREEZE_ADDRESS_FN); 107 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(to_freeze)); 108 | multisig.leo/burn(ticket_); 109 | 110 | return then finalize(to_freeze); 111 | } 112 | 113 | finalize freeze_address(to_freeze: address) { 114 | Mapping::set(frozen_addresses, to_freeze, true); 115 | } 116 | 117 | transition set_pauser(ticket_: multisig.leo/ticket.record, new_pauser: address) { 118 | assert_eq( 119 | ticket_.program_address, 120 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 121 | ); 122 | assert_eq(ticket_.function_id, SET_PAUSER_FN); 123 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_pauser)); 124 | multisig.leo/burn(ticket_); 125 | 126 | return then finalize(new_pauser); 127 | } 128 | 129 | finalize set_pauser(new_pauser: address) { 130 | Mapping::set(pauser, true, new_pauser); 131 | } 132 | 133 | transition pause() { 134 | return then finalize(self.caller); 135 | } 136 | 137 | finalize pause(caller: address) { 138 | assert_eq(Mapping::get(pauser, true), caller); 139 | Mapping::set(paused, true, true); 140 | } 141 | 142 | transition unpause() { 143 | return then finalize(self.caller); 144 | } 145 | 146 | finalize unpause(caller: address) { 147 | assert_eq(Mapping::get(pauser, true), caller); 148 | Mapping::set(paused, true, false); 149 | } 150 | 151 | transition upgrade(ticket_: multisig.leo/ticket.record, new_implementation: address) { 152 | assert_eq( 153 | ticket_.program_address, 154 | aleo16l909ch9c9zujjlthk47knk72zq0r4wd7eveqm8ukgta6cfszsgs4nd7p4 // address("token.aleo") 155 | ); 156 | assert_eq(ticket_.function_id, UPGRADE_FN); 157 | assert_eq(ticket_.args_hash, BHP256::hash_to_field(new_implementation)); 158 | multisig.leo/burn(ticket_); 159 | 160 | return then finalize(new_implementation); 161 | } 162 | 163 | finalize upgrade(new_implementation: address) { 164 | Mapping::set(next_implementation, true, new_implementation); 165 | Mapping::set(paused, true, true); 166 | } 167 | } 168 | --------------------------------------------------------------------------------