diff --git a/src/test/contracts/FA1.2.ligo b/src/test/contracts/FA1.2.ligo new file mode 100644 index 000000000..15d3bb917 --- /dev/null +++ b/src/test/contracts/FA1.2.ligo @@ -0,0 +1,116 @@ +type tokens is big_map (address, nat) +type allowances is big_map (address * address, nat) (* (sender,account) -> value *) + +type storage is record [ + tokens : tokens; + allowances : allowances; + total_amount : nat; +] + +type transfer is record [ + address_from : address; + address_to : address; + value : nat; +] + +type approve is record [ + spender : address; + value : nat; +] + +type getAllowance is record [ + owner : address; + spender : address; + callback : contract (nat); +] + +type getBalance is record [ + owner : address; + callback : contract (nat); +] + +type getTotalSupply is record [ + callback : contract (nat); +] + +type action is + Transfer of transfer +| Approve of approve +| GetAllowance of getAllowance +| GetBalance of getBalance +| GetTotalSupply of getTotalSupply + +function transfer (const p : transfer; const s: storage) : list (operation) * storage is block { + var new_allowances : allowances := Big_map.empty; + if Tezos.sender = p.address_from + then { new_allowances := s.allowances; } + else { + var authorized_value : nat := + case (Big_map.find_opt ((Tezos.sender,p.address_from), s.allowances)) of + Some (value) -> value + | None -> 0n + end; + if (authorized_value < p.value) + then { failwith("Not Enough Allowance")} + else { new_allowances := Big_map.update ((Tezos.sender,p.address_from), (Some (abs(authorized_value - p.value))), s.allowances) } + }; + var sender_balance : nat := case (Big_map.find_opt (p.address_from, s.tokens)) of + Some (value) -> value + | None -> 0n + end; + var new_tokens : tokens := Big_map.empty; + if (sender_balance < p.value) + then { failwith ("Not Enough Balance")} + else { + new_tokens := Big_map.update (p.address_from, (Some (abs(sender_balance - p.value))), s.tokens); + var receiver_balance : nat := case (Big_map.find_opt (p.address_to, s.tokens)) of + Some (value) -> value + | None -> 0n + end; + new_tokens := Big_map.update (p.address_to, (Some (receiver_balance + p.value)), new_tokens); + } +} with ((nil: list (operation)), s with record [tokens = new_tokens; allowances = new_allowances]) + +function approve (const p : approve; const s : storage) : list (operation) * storage is block { + var previous_value : nat := case Big_map.find_opt ((p.spender, Tezos.sender), s.allowances) of + Some (value) -> value + | None -> 0n + end; + var new_allowances : allowances := Big_map.empty; + if previous_value > 0n and p.value > 0n + then { failwith ("Unsafe Allowance Change")} + else { + new_allowances := Big_map.update ((p.spender, Tezos.sender), (Some (p.value)), s.allowances); + } +} with ((nil: list (operation)), s with record [allowances = new_allowances]) + +function getAllowance (const p : getAllowance; const s : storage) : list (operation) * storage is block { + var value : nat := case Big_map.find_opt ((p.owner, p.spender), s.allowances) of + Some (value) -> value + | None -> 0n + end; + var op : operation := Tezos.transaction (value, 0mutez, p.callback); +} with (list [op],s) + +function getBalance (const p : getBalance; const s : storage) : list (operation) * storage is block { + var value : nat := case Big_map.find_opt (p.owner, s.tokens) of + Some (value) -> value + | None -> 0n + end; + var op : operation := Tezos.transaction (value, 0mutez, p.callback); +} with (list [op],s) + +function getTotalSupply (const p : getTotalSupply; const s : storage) : list (operation) * storage is block { + var total : nat := s.total_amount; + var op : operation := Tezos.transaction (total, 0mutez, p.callback); +} with (list [op],s) + + +function main (const a : action; const s : storage) : list (operation) * storage is + case a of + 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) + end;