-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
marketplace.func
144 lines (119 loc) · 5.29 KB
/
marketplace.func
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
136
137
138
139
140
141
142
143
144
;; Libermall main marketplace contract
;; Copyright (C) 2022 libermall.com
(int, slice, int, cell, cell) load_data() inline {
var ds = get_data().begin_parse();
return
(
ds~load_uint(1), ;; initialized?
ds~load_msg_addr(), ;; owner_address
ds~load_uint(256), ;; authorization public key
ds~load_ref(), ;; sale_code
ds~load_ref() ;; amounts_cell
);
}
(int, int) load_amounts(cell amounts_cell) inline {
var ds = amounts_cell.begin_parse();
return (
ds~load_coins(), ;; deploy_amount, how much does it cost to deploy a sale contract
ds~load_coins() ;; transfer_amount, how much does it cost to transfer an item
);
}
() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
if (in_msg_body.slice_empty?()) { ;; ignore empty messages
return ();
}
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
if (flags & 1) { ;; ignore all bounced messages
return ();
}
slice sender_address = cs~load_msg_addr();
var (initialized, owner_address, public_key, sale_code, amounts_cell) = load_data();
int op = in_msg_body~load_uint(32);
int query_id = in_msg_body~load_uint(64);
if(equal_slices(sender_address, owner_address)) {
if(op == 420) { ;; Change/set public key
var new_public_key = in_msg_body~load_uint(256);
set_data(begin_cell()
.store_uint(1, 1) ;; initialized
.store_slice(owner_address)
.store_uint(new_public_key, 256)
.store_ref(sale_code)
.store_ref(amounts_cell)
.end_cell());
}
if(op == 1337) { ;; Setcode baby, just in case
var code = in_msg_body~load_ref();
var data = in_msg_body~load_ref();
set_code(code);
set_data(data);
}
return ();
}
if(op == op::ownership_assigned()) { ;; It's showtime
slice prev_owner_address = in_msg_body~load_msg_addr(); ;; Previous owner is the account that put item up for sale
cell payload = in_msg_body~load_ref(); ;; Load all of the necessary info
slice check = in_msg_body~load_ref().begin_parse(); ;; signature is stored there
var signature = check~load_bits(512); ;; apparent signature
throw_unless(0xDEAD, check_signature(cell_hash(payload), signature, public_key)); ;; Make sure that the message is legit
;; To protect against someone potentially malicious duplicating messages with lower/no fees we make sure to
;; add some random string at the end of the payload. Sicnce payload is yeeted directly into the seller's contract
;; data, it doesn't matter what it contains past useful data
cell state_init = begin_cell()
.store_uint(0, 2)
.store_dict(sale_code)
.store_dict(payload)
.store_uint(0, 1)
.end_cell();
slice sale_address = begin_cell()
.store_uint(4, 3)
.store_int(workchain(), 8)
.store_uint(cell_hash(state_init), 256)
.end_cell()
.begin_parse();
;; load amounts
var (deploy_amount, transfer_amount) = load_amounts(amounts_cell);
;; Deploying seller contract
var sale_msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(sale_address)
.store_coins(deploy_amount)
.store_uint(4 + 2 + 0, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
.store_ref(state_init);
send_raw_message(sale_msg.end_cell(), 1); ;; pay transfer fees separately, revert on errors
;; Transferring the item to the newly created seller contract
var item_msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(sender_address)
.store_coins(transfer_amount)
.store_uint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_ref(begin_cell()
.store_uint(op::transfer(), 32)
.store_uint(query_id, 64)
.store_slice(sale_address) ;; new_owner_address
.store_slice(sale_address) ;; response_address - rest of the coins goes there. Owner will get them on sale/cancel
.store_int(0, 1) ;; empty custom_payload
.store_coins(0) ;; forward amount to new_owner_address
.store_int(0, 1) ;; empty forward_payload
.end_cell()
);
send_raw_message(item_msg.end_cell(), 1); ;; Fees separately
return ();
}
throw(0xFFFF);
}
() recv_external(slice in_msg) impure {
var (initialized, owner_address, public_key, sale_code, amounts_cell) = load_data();
if(initialized == 0) {
accept_message();
set_data(begin_cell()
.store_uint(1, 1) ;; initialized
.store_slice(owner_address)
.store_uint(public_key, 256)
.store_ref(sale_code)
.store_ref(amounts_cell)
.end_cell());
return ();
}
throw(0xFFFF);
}