-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathfa2_fungible_token.mligo
135 lines (114 loc) · 4.34 KB
/
fa2_fungible_token.mligo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
(**
Implementation of the FA2 interface for the single fungible token contract.
*)
#if !FA2_FUNGIBLE_TOKEN
#define FA2_FUNGIBLE_TOKEN
#include "token_sig.mligo"
#include "../fa2/fa2_interface.mligo"
#include "../fa2/fa2_errors.mligo"
#include "../fa2/lib/fa2_operator_lib.mligo"
module type FungibleTokenSig = sig
type ledger
type storage
val inc_balance : address * nat * ledger -> ledger
val dec_balance : address * nat * ledger -> ledger
end
module TokenImpl = struct
(** owner address -> balance *)
type ledger = (address, nat) big_map
type storage = {
ledger : ledger;
operators : operator_storage;
token_metadata : (nat, token_metadata) big_map;
total_supply : nat;
}
let get_balance_amt (owner, ledger : address * ledger) : nat =
let bal_opt = Big_map.find_opt owner ledger in
match bal_opt with
| None -> 0n
| Some b -> b
let inc_balance (owner, amt, ledger
: address * nat * ledger) : ledger =
let bal = get_balance_amt (owner, ledger) in
let updated_bal = bal + amt in
if updated_bal = 0n
then Big_map.remove owner ledger
else Big_map.update owner (Some updated_bal) ledger
let dec_balance (owner, amt, ledger
: address * nat * ledger) : ledger =
let bal = get_balance_amt (owner, ledger) in
match is_nat (bal - amt) with
| None -> (failwith fa2_insufficient_balance : ledger)
| Some new_bal ->
if new_bal = 0n
then Big_map.remove owner ledger
else Big_map.update owner (Some new_bal) ledger
(**
Update leger balances according to the specified transfers. Fails if any of the
permissions or constraints are violated.
@param txs transfers to be applied to the ledger
@param validate_op function that validates of the tokens from the particular owner and token id can be transferred.
*)
let transfer (txs, validate_op, ops_storage, ledger
: (transfer list) * operator_validator * operator_storage * ledger)
: ledger =
let make_transfer = fun (l, tx : ledger * transfer) ->
List.fold
(fun (ll, dst : ledger * transfer_destination) ->
if dst.token_id <> 0n
then (failwith fa2_token_undefined : ledger)
else
let _ = validate_op
(tx.from_, (Tezos.get_sender ()), dst.token_id, ops_storage) in
let lll = dec_balance (tx.from_, dst.amount, ll)
in
inc_balance(dst.to_, dst.amount, lll)
) tx.txs l
in
List.fold make_transfer txs ledger
(**
Retrieve the balances for the specified tokens and owners
@return callback operation
*)
let get_balance (p, ledger : balance_of_param * ledger) : operation =
let to_balance = fun (r : balance_of_request) ->
if r.token_id <> 0n
then (failwith fa2_token_undefined : balance_of_response)
else
let bal = get_balance_amt (r.owner, ledger) in
let response : balance_of_response = { request = r; balance = bal; } in
response
in
let responses = List.map to_balance p.requests in
Tezos.transaction responses 0mutez p.callback
(** Validate if all provided token_ids are `0n` and correspond to a single token ID *)
let validate_token_ids (tokens : token_id list) : unit =
List.iter (fun (id : nat) ->
if id = 0n then unit else failwith fa2_token_undefined
) tokens
let fa2_transfer (txs, storage : (transfer list) * storage) : storage =
let new_ledger = transfer
(txs, default_operator_validator, storage.operators, storage.ledger) in
let new_storage = { storage with ledger = new_ledger; } in
new_storage
let fa2_main (param, storage : fa2_entry_points * storage)
: (operation list) * storage =
match param with
| Transfer txs ->
(*
will validate that a sender is either `from_` parameter of each transfer
or a permitted operator for the owner `from_` address.
*)
let new_storage = fa2_transfer (txs, storage) in
([] : operation list), new_storage
| Balance_of p ->
let op = get_balance (p, storage.ledger) in
[op], storage
| Update_operators updates ->
let new_ops = fa2_update_operators (updates, storage.operators) in
let new_storage = { storage with operators = new_ops; } in
([] : operation list), new_storage
end
module Token : TokenSig = TokenImpl
module FungibleToken : FungibleTokenSig = TokenImpl
#endif