;; DNS resolver smart contract (implements NFT Collection interface) #include "stdlib.fc"; #include "params.fc"; #include "dns-utils.fc"; ;; storage scheme ;; storage#_ collection_content:^Cell ;; nft_item_code:^Cell ;; = Storage; (cell, cell) load_data() inline { var ds = get_data().begin_parse(); return ( ds~load_ref(), ;; content ds~load_ref() ;; nft_item_code ); } () save_data(cell content, cell nft_item_code) impure inline { set_data(begin_cell() .store_ref(content) .store_ref(nft_item_code) .end_cell()); } cell calculate_nft_item_state_init(int item_index, cell nft_item_code) { cell data = begin_cell().store_uint(item_index, 256).store_slice(my_address()).end_cell(); return begin_cell().store_uint(0, 2).store_dict(nft_item_code).store_dict(data).store_uint(0, 1).end_cell(); } slice calculate_nft_item_address(int wc, cell state_init) { return begin_cell() .store_uint(4, 3) .store_int(wc, 8) .store_uint(cell_hash(state_init), 256) .end_cell() .begin_parse(); } () deploy_nft_item(int item_index, cell nft_item_code, cell nft_content) impure { cell state_init = calculate_nft_item_state_init(item_index, nft_item_code); slice nft_address = calculate_nft_item_address(workchain(), state_init); var msg = begin_cell() .store_uint(0x18, 6) .store_slice(nft_address) .store_coins(0) .store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1) .store_ref(state_init) .store_ref(nft_content); send_raw_message(msg.end_cell(), 64); ;; carry all the remaining value of the inbound message, fee deducted from amount } () recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure { if (in_msg_body.slice_empty?()) { ;; bounce back empty messages throw(0xffff); } 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(); int op = in_msg_body~load_uint(32); var (content, nft_item_code) = load_data(); if (op == 0) { ;; deploy new nft int now_time = now(); throw_unless(199, now_time > auction_start_time); ;; start of auction slice domain = read_domain_from_comment(in_msg_body); int len = slice_bits(domain); throw_unless(200, len > 3 * 8); ;; minimum 4 characters throw_unless(201, len <= 126 * 8); ;; maxmimum 126 characters throw_unless(202, mod(len, 8) == 0); throw_unless(203, check_domain_string(domain)); int min_price = get_min_price(len, now_time); throw_unless(204, msg_value >= min_price); int item_index = slice_hash(domain); cell config_cell = config_param(dns_config_id); if (~ cell_null?(config_cell)) { slice config_cs = config_cell.begin_parse(); cell config = config_cs~load_dict(); (slice config_value, int found) = config.udict_get?(256, item_index); throw_if(205, found); } cell nft_content = begin_cell() .store_slice(sender_address) .store_ref(begin_cell().store_slice(domain).end_cell()) .end_cell(); deploy_nft_item(item_index, nft_item_code, nft_content); return (); } if (op == op::fill_up) { ;; just fill-up balance return (); } throw(0xffff); } ;; Get methods (int, cell, slice) get_collection_data() method_id { var (content, nft_item_code) = load_data(); return (-1, content, zero_address()); } slice get_nft_address_by_index(int index) method_id { var (content, nft_item_code) = load_data(); cell state_init = calculate_nft_item_state_init(index, nft_item_code); return calculate_nft_item_address(workchain(), state_init); } cell get_nft_content(int index, cell individual_nft_content) method_id { return individual_nft_content; } (int, cell) dnsresolve(slice subdomain, int category) method_id { throw_unless(70, mod(slice_bits(subdomain), 8) == 0); int starts_with_zero_byte = subdomain.preload_int(8) == 0; if (starts_with_zero_byte & (slice_bits(subdomain) == 8)) { ;; "." requested return (8, null()); ;; resolved but no dns-records } if (starts_with_zero_byte) { subdomain~load_uint(8); } int top_subdomain_bits = get_top_domain_bits(subdomain); slice top_subdomain = subdomain~load_bits(top_subdomain_bits); int item_index = slice_hash(top_subdomain); cell result = begin_cell() .store_uint(dns_next_resolver_prefix, 16) .store_slice(get_nft_address_by_index(item_index)) .end_cell(); return (top_subdomain_bits + (starts_with_zero_byte ? 8 : 0), result); }