Ton
144 строки · 4.8 Кб
1;; DNS resolver smart contract (implements NFT Collection interface)
2
3
4#include "stdlib.fc";
5#include "params.fc";
6#include "dns-utils.fc";
7
8;; storage scheme
9;; storage#_ collection_content:^Cell
10;; nft_item_code:^Cell
11;; = Storage;
12
13(cell, cell) load_data() inline {
14var ds = get_data().begin_parse();
15return (
16ds~load_ref(), ;; content
17ds~load_ref() ;; nft_item_code
18);
19}
20
21() save_data(cell content, cell nft_item_code) impure inline {
22set_data(begin_cell()
23.store_ref(content)
24.store_ref(nft_item_code)
25.end_cell());
26}
27
28cell calculate_nft_item_state_init(int item_index, cell nft_item_code) {
29cell data = begin_cell().store_uint(item_index, 256).store_slice(my_address()).end_cell();
30return begin_cell().store_uint(0, 2).store_dict(nft_item_code).store_dict(data).store_uint(0, 1).end_cell();
31}
32
33slice calculate_nft_item_address(int wc, cell state_init) {
34return begin_cell()
35.store_uint(4, 3)
36.store_int(wc, 8)
37.store_uint(cell_hash(state_init), 256)
38.end_cell()
39.begin_parse();
40}
41
42() deploy_nft_item(int item_index, cell nft_item_code, cell nft_content) impure {
43cell state_init = calculate_nft_item_state_init(item_index, nft_item_code);
44slice nft_address = calculate_nft_item_address(workchain(), state_init);
45var msg = begin_cell()
46.store_uint(0x18, 6)
47.store_slice(nft_address)
48.store_coins(0)
49.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
50.store_ref(state_init)
51.store_ref(nft_content);
52send_raw_message(msg.end_cell(), 64); ;; carry all the remaining value of the inbound message, fee deducted from amount
53}
54
55() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
56if (in_msg_body.slice_empty?()) { ;; bounce back empty messages
57throw(0xffff);
58}
59slice cs = in_msg_full.begin_parse();
60int flags = cs~load_uint(4);
61
62if (flags & 1) { ;; ignore all bounced messages
63return ();
64}
65slice sender_address = cs~load_msg_addr();
66
67int op = in_msg_body~load_uint(32);
68
69var (content, nft_item_code) = load_data();
70
71if (op == 0) { ;; deploy new nft
72int now_time = now();
73throw_unless(199, now_time > auction_start_time); ;; start of auction
74slice domain = read_domain_from_comment(in_msg_body);
75int len = slice_bits(domain);
76throw_unless(200, len > 3 * 8); ;; minimum 4 characters
77throw_unless(201, len <= 126 * 8); ;; maxmimum 126 characters
78throw_unless(202, mod(len, 8) == 0);
79throw_unless(203, check_domain_string(domain));
80int min_price = get_min_price(len, now_time);
81throw_unless(204, msg_value >= min_price);
82
83int item_index = slice_hash(domain);
84
85cell config_cell = config_param(dns_config_id);
86if (~ cell_null?(config_cell)) {
87slice config_cs = config_cell.begin_parse();
88cell config = config_cs~load_dict();
89(slice config_value, int found) = config.udict_get?(256, item_index);
90throw_if(205, found);
91}
92
93cell nft_content = begin_cell()
94.store_slice(sender_address)
95.store_ref(begin_cell().store_slice(domain).end_cell())
96.end_cell();
97deploy_nft_item(item_index, nft_item_code, nft_content);
98return ();
99}
100
101if (op == op::fill_up) { ;; just fill-up balance
102return ();
103}
104throw(0xffff);
105}
106
107;; Get methods
108
109(int, cell, slice) get_collection_data() method_id {
110var (content, nft_item_code) = load_data();
111return (-1, content, zero_address());
112}
113
114slice get_nft_address_by_index(int index) method_id {
115var (content, nft_item_code) = load_data();
116cell state_init = calculate_nft_item_state_init(index, nft_item_code);
117return calculate_nft_item_address(workchain(), state_init);
118}
119
120cell get_nft_content(int index, cell individual_nft_content) method_id {
121return individual_nft_content;
122}
123
124(int, cell) dnsresolve(slice subdomain, int category) method_id {
125throw_unless(70, mod(slice_bits(subdomain), 8) == 0);
126
127int starts_with_zero_byte = subdomain.preload_int(8) == 0;
128
129if (starts_with_zero_byte & (slice_bits(subdomain) == 8)) { ;; "." requested
130return (8, null()); ;; resolved but no dns-records
131}
132if (starts_with_zero_byte) {
133subdomain~load_uint(8);
134}
135
136int top_subdomain_bits = get_top_domain_bits(subdomain);
137slice top_subdomain = subdomain~load_bits(top_subdomain_bits);
138int item_index = slice_hash(top_subdomain);
139cell result = begin_cell()
140.store_uint(dns_next_resolver_prefix, 16)
141.store_slice(get_nft_address_by_index(item_index))
142.end_cell();
143return (top_subdomain_bits + (starts_with_zero_byte ? 8 : 0), result);
144}
145