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