This repository has been archived by the owner on Feb 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathfa2_multi_token.mligo
132 lines (112 loc) · 4.62 KB
/
fa2_multi_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
#if !FA2_MAC_TOKEN
#define FA2_MAC_TOKEN
#include "../fa2/fa2_interface.mligo"
#include "../fa2/fa2_permissions_descriptor.mligo"
#include "../fa2/fa2_errors.mligo"
#include "../fa2/lib/fa2_operator_lib.mligo"
#include "../fa2/lib/fa2_owner_hooks_lib.mligo"
#include "../fa2_modules/token_sig.mligo"
module type MultiTokenSig = sig
type ledger
type storage
type token_total_supply
val inc_balance : address * token_id * nat * ledger -> ledger
val dec_balance : address * token_id * nat * ledger -> ledger
end
module TokenImpl = struct
(* (owner,token_id) -> balance *)
type ledger = ((address * token_id), nat) big_map
(* token_id -> total_supply *)
type token_total_supply = (token_id, nat) big_map
type storage = {
ledger : ledger;
operators : operator_storage;
token_total_supply : token_total_supply;
token_metadata : token_metadata_storage;
permissions : permissions_descriptor;
}
let get_balance_amt (key, ledger : (address * nat) * ledger) : nat =
let bal_opt = Big_map.find_opt key ledger in
match bal_opt with
| None -> 0n
| Some b -> b
let inc_balance (owner, token_id, amt, ledger
: address * token_id * nat * ledger) : ledger =
let key = owner, token_id in
let bal = get_balance_amt (key, ledger) in
let updated_bal = bal + amt in
if updated_bal = 0n
then Big_map.remove key ledger
else Big_map.update key (Some updated_bal) ledger
let dec_balance (owner, token_id, amt, ledger
: address * token_id * nat * ledger) : ledger =
let key = owner, token_id in
let bal = get_balance_amt (key, 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 key ledger
else Big_map.update key (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 can be transferred.
*)
let transfer (txs, validate_op, storage
: (transfer list) * operator_validator * storage)
: ledger =
let make_transfer = fun (l, tx : ledger * transfer) ->
List.fold
(fun (ll, dst : ledger * transfer_destination) ->
if not Big_map.mem dst.token_id storage.token_metadata
then (failwith fa2_token_undefined : ledger)
else
let sender = Tezos.get_sender() in
let _ = validate_op (tx.from_, sender, dst.token_id, storage.operators) in
let lll = dec_balance (tx.from_, dst.token_id, dst.amount, ll) in
inc_balance(dst.to_, dst.token_id, dst.amount, lll)
) tx.txs l
in
List.fold make_transfer txs storage.ledger
let get_balance (p, ledger, tokens
: balance_of_param * ledger * token_metadata_storage) : operation =
let to_balance = fun (r : balance_of_request) ->
if not Big_map.mem r.token_id tokens
then (failwith fa2_token_undefined : balance_of_response)
else
let key = r.owner, r.token_id in
let bal = get_balance_amt (key, 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
let get_owner_hook_ops (txs, p_descriptor : (transfer list) * permissions_descriptor) : operation list =
let sender = Tezos.get_sender() in
let tx_descriptor = transfers_to_transfer_descriptor_param (txs, sender) in
get_owner_hook_ops_for (tx_descriptor, p_descriptor)
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_ledger = transfer (txs, default_operator_validator, storage) in
let new_storage = { storage with ledger = new_ledger; } in
let hook_ops = get_owner_hook_ops (txs, storage.permissions) in
(hook_ops), new_storage
| Balance_of p ->
let op = get_balance (p, storage.ledger, storage.token_metadata) 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 MultiToken : MultiTokenSig = TokenImpl
#endif