main.adl
1 program basic_bank.alpha { 2 // A token, issued by a bank. 3 // - 'owner' : The address of the account that owns the record associated with this token. 4 // - 'amount' : The amount of tokens owned by the account. 5 record Token { 6 owner: address, 7 amount: u64, 8 } 9 10 // An on-chain mapping, storing the amount of tokens owned by each account 11 // The account is stored as a hash to preserve user privacy. 12 mapping balances: field => u64; 13 14 // Returns a new Token. 15 // - `owner` : The address of the account to issue the token to. 16 // - `amount`: The amount of tokens to issue. 17 // Requires that the function caller is the bank. 18 // The bank's address is ax12mq8xts3wh22vuuup4nwysxhfgpm43cqmkh279exetljag58v5qqc4suk3. 19 transition issue(owner: address, amount: u64) -> Token { 20 assert_eq(self.caller, ax12mq8xts3wh22vuuup4nwysxhfgpm43cqmkh279exetljag58v5qqc4suk3); 21 return Token { 22 owner: owner, 23 amount: amount, 24 }; 25 } 26 27 // Deposits some amount of money into the bank. 28 // Returns a new Token with the remaining amount of money. 29 // - `token` : A record containing tokens to deposit. 30 // - `amount`: The amount of tokens to deposit. 31 async transition deposit(token: Token, amount: u64) -> (Token, Future) { 32 let difference: u64 = token.amount - amount; 33 34 let remaining: Token = Token { 35 owner: token.owner, 36 amount: difference, 37 }; 38 39 // Compute the hash of the token owner. 40 let hash: field = BHP256::hash_to_field(token.owner); 41 42 return (remaining, finalize_deposit(hash, amount)); 43 } 44 45 // Updates on-chain state by the amount of tokens deposited. 46 // - `hash` : The hash of the token owner. 47 // - `amount`: The amount of tokens that were deposited. 48 async function finalize_deposit(hash: field, amount: u64) { 49 let current_amount: u64 = Mapping::get_or_use(balances, hash, 0u64); 50 Mapping::set(balances, hash, current_amount + amount); 51 } 52 53 // Returns a new Token containing the amount of money withdrawn. 54 // - `recipient`: The address of the account to withdraw the tokens to. 55 // - `amount` : The amount of tokens to withdraw. 56 // - `rate` : The compound interest rate. 57 // - `periods` : The number of periods to compound the interest over. 58 // Requires that the function caller is the bank. 59 async transition withdraw(recipient: address, amount: u64, rate: u64, periods: u64) -> (Token, Future) { 60 assert_eq(self.caller, ax12mq8xts3wh22vuuup4nwysxhfgpm43cqmkh279exetljag58v5qqc4suk3); 61 let hash: field = BHP256::hash_to_field(recipient); 62 63 let total: u64 = calculate_interest(amount, rate, periods); 64 65 let token: Token = Token { 66 owner: recipient, 67 amount: total, 68 }; 69 70 return (token, finalize_withdraw(hash, amount)); 71 } 72 73 // Updates on-chain state by the amount of tokens withdrawn. 74 // - `hash` : The hash of the token owner. 75 // - `amount`: The amount of tokens that were withdrawn. 76 async function finalize_withdraw(hash: field, amount: u64) { 77 let current_amount: u64 = Mapping::get_or_use(balances, hash, 0u64); 78 Mapping::set(balances, hash, current_amount - amount); 79 } 80 81 // Returns the total amount of tokens after compounding interest. 82 // - `principal`: The amount of tokens to compound interest over. 83 // - `rate` : The compound interest rate. 84 // - `periods` : The number of periods to compound the interest over. 85 function calculate_interest(principal: u64, rate: u64, periods: u64) -> u64 { 86 let amount: u64 = principal; 87 88 for i:u64 in 0u64..100u64 { 89 if i < periods { 90 amount += (amount * rate) / 10000u64; 91 } 92 } 93 94 return amount; 95 } 96 97 // The constructor is configured to prevent upgrades. 98 @noupgrade 99 async constructor() {} 100 }