diff --git a/src/test/contracts/FA1.2.religo b/src/test/contracts/FA1.2.religo new file mode 100644 index 000000000..37b194738 --- /dev/null +++ b/src/test/contracts/FA1.2.religo @@ -0,0 +1,115 @@ +type tokens = big_map (address, nat) +type allowances = big_map ((address, address), nat) /* (sender,account) -> value */ + +type storage = { + tokens : tokens, + allowances : allowances, + total_amount : nat, +} + +type transfer = { + address_from : address, + address_to : address, + value : nat, +} + +type approve = { + spender : address, + value : nat, +} + +type getAllowance = { + owner : address, + spender : address, + callback : contract (nat), +} + +type getBalance = { + owner : address, + callback : contract (nat), +} + +type getTotalSupply = { + callback : contract (nat), +} + +type action = +| Transfer ( transfer ) +| Approve ( approve ) +| GetAllowance ( getAllowance ) +| GetBalance ( getBalance ) +| GetTotalSupply ( getTotalSupply ) + +let transfer = ((p,s) : (transfer, storage)) : (list (operation), storage) => { + let new_allowances = + if (Tezos.sender == p.address_from) { s.allowances; } + else { + let authorized_value = switch (Big_map.find_opt ((Tezos.sender,p.address_from), s.allowances)) { + | Some value => value + | None => 0n + }; + if (authorized_value < p.value) { (failwith ("Not Enough Allowance") : allowances); } + else { Big_map.update ((Tezos.sender,p.address_from), (Some (abs(authorized_value - p.value))), s.allowances); }; + }; + let sender_balance = switch (Big_map.find_opt (p.address_from, s.tokens)) { + | Some value => value + | None => 0n + }; + if (sender_balance < p.value) { (failwith ("Not Enough Balance") : (list (operation), storage)); } + else { + let new_tokens = Big_map.update (p.address_from, (Some (abs(sender_balance - p.value))), s.tokens); + let receiver_balance = switch (Big_map.find_opt (p.address_to, s.tokens)) { + | Some value => value + | None => 0n + }; + let new_tokens = Big_map.update (p.address_to, (Some (receiver_balance + p.value)), new_tokens); + (([]: list (operation)), { ...s,tokens:new_tokens, allowances:new_allowances}); + }; +}; + +let approve = ((p,s) : (approve, storage)) : (list (operation), storage) => { + let previous_value = switch (Big_map.find_opt ((p.spender, Tezos.sender), s.allowances)){ + | Some value => value + | None => 0n + }; + if (previous_value > 0n && p.value > 0n) + { (failwith ("Unsafe Allowance Change") : (list (operation), storage)); } + else { + let new_allowances = Big_map.update ((p.spender, Tezos.sender), (Some (p.value)), s.allowances); + (([] : list (operation)), { ...s, allowances : new_allowances}); + }; +}; + +let getAllowance = ((p,s) : (getAllowance, storage)) : (list (operation), storage) => { + let value = switch (Big_map.find_opt ((p.owner, p.spender), s.allowances)) { + | Some value => value + | None => 0n + }; + let op = Tezos.transaction (value, 0mutez, p.callback); + ([op],s) +}; + +let getBalance = ((p,s) : (getBalance, storage)) : (list (operation), storage) => { + let value = switch (Big_map.find_opt (p.owner, s.tokens)) { + | Some value => value + | None => 0n + }; + let op = Tezos.transaction (value, 0mutez, p.callback); + ([op],s) +}; + +let getTotalSupply = ((p,s) : (getTotalSupply, storage)) : (list (operation), storage) => { + let total = s.total_amount; + let op = Tezos.transaction (total, 0mutez, p.callback); + ([op],s) +}; + + +let main = ((a,s): (action, storage)) => + switch a { + | Transfer p => transfer ((p,s)) + | Approve p => approve ((p,s)) + | GetAllowance p => getAllowance ((p,s)) + | GetBalance p => getBalance ((p,s)) + | GetTotalSupply p => getTotalSupply ((p,s)) + };