diff --git a/contracts/imports/dns-utils.fc b/contracts/imports/dns-utils.fc index 885791a..8580e54 100644 --- a/contracts/imports/dns-utils.fc +++ b/contracts/imports/dns-utils.fc @@ -8,11 +8,7 @@ const int dns_next_resolver_prefix = 0xba93; ;; dns_next_resolver prefix - https const int dns_config_id = 80; ;; dns black list config param; in testnet -80 -const int op::fill_up = 0x370fec51; -const int op::outbid_notification = 0x557cea20; -const int op::change_dns_record = 0x4eb1f0f9; -const int op::process_governance_decision = 0x44beae41; -const int op::dns_balance_release = 0x4ed14b65; + int mod(int x, int y) asm "MOD"; diff --git a/contracts/imports/op-codes.fc b/contracts/imports/op-codes.fc index a1e8de2..c2ceb3f 100644 --- a/contracts/imports/op-codes.fc +++ b/contracts/imports/op-codes.fc @@ -13,4 +13,16 @@ int op::editorship_assigned() asm "0x511a4463 PUSHINT"; ;; Collection int op::new_nft() asm "0x1a039a51 PUSHINT"; -int op::fill_up_balance() asm "0x2fa39a10 PUSHINT"; + +;; DNS +const int op::fill_up = 0x370fec51; +const int op::outbid_notification = 0x557cea20; +const int op::change_dns_record = 0x4eb1f0f9; +const int op::process_governance_decision = 0x44beae41; +const int op::dns_balance_release = 0x4ed14b65; + +;; Wrapper +int op::fill_up_wrapper() asm "0x140aec51 PUSHINT"; +int op::change_wrapper_code() asm "0x4eb110a9 PUSHINT"; +;; For owner - set owner, for agorata - set agorata address +int op::update_wrapper_address() asm "0x4bd15269 PUSHINT"; diff --git a/contracts/main.fc b/contracts/main.fc index 7002344..79ecf78 100644 --- a/contracts/main.fc +++ b/contracts/main.fc @@ -36,6 +36,20 @@ int min_tons_for_storage() asm "1000000000 PUSHINT"; ;; 1 TON } } +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(); +} + () store_data(cell collection_content, cell nft_item_code, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) impure { set_data( begin_cell() @@ -109,25 +123,43 @@ int min_tons_for_storage() asm "1000000000 PUSHINT"; ;; 1 TON } slice get_editor() method_id { - (cell coll_content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); + (cell content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); return owner_address; } slice get_domain() method_id { - (cell coll_content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); + (cell content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); return domain.begin_parse(); } ;; (slice, int, int) get_auction_info() method_id { -;; (cell coll_content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, cell auction, int last_fill_up_time) = load_data(); +;; (cell content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, cell auction, int last_fill_up_time) = load_data(); ;; return unpack_auction(auction); ;; } int get_last_fill_up_time() method_id { - (cell coll_content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); + (cell content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); return last_fill_up_time; } +;; Collection methods + + +(int, cell, slice) get_collection_data() method_id { + (cell content, cell item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = load_data(); + return (-1, content, zero_address()); +} + +slice get_nft_address_by_index(int index) method_id { + (cell content, cell nft_item_code, int init?, int index, slice collection_address, slice owner_address, cell domain, cell auction, int last_fill_up_time) = 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 { int subdomain_bits = slice_bits(subdomain); diff --git a/contracts/wrapper.fc b/contracts/wrapper.fc new file mode 100644 index 0000000..3ef63c1 --- /dev/null +++ b/contracts/wrapper.fc @@ -0,0 +1,86 @@ +;; This wrapper contract is used to be the interface to a domain managed by Agorata + +;; It makes it so that both the owner and the domain manager can call the functions of the contract -- with some permission management + +#pragma version >=0.2.0; +#include "imports/stdlib.fc"; +#include "imports/constants.fc"; +#include "imports/utils.fc"; +#include "imports/op-codes.fc"; + +;; Storage schema: + +;; Address contract: the domain owned by the wrapper +;; Address owner: the original domain owner +;; Address agorata: the address of the Agorata + +(slice, slice, slice) load_data() inline_ref { + slice ds = get_data().begin_parse(); + slice target = ds~load_msg_addr(); + slice owner = ds~load_msg_addr(); + slice agorata = ds~load_msg_addr(); + return (target, owner, agorata); +} + +() store_data(slice target, slice owner, slice agorata) impure inline_ref { + set_data( + begin_cell() + .store_slice(target) + .store_slice(owner) + .store_slice(agorata) + .end_cell()); +} + +() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure { + if (in_msg_body.slice_empty?()) { ;; bounce back empty messages + throw(0xffff); + } + ;; handle internal messages + int op = in_msg_body~load_uint(32); + 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(); + (slice target, slice owner, slice agorata) = load_data(); + if (equal_slices(sender_address, owner)) { + if ((op == op::transfer()) | (op == op::transfer_editorship())) { + ;; todo: the owner can transfer the ownership, but only to Agorata (just like Agorata can transfer the ownership to the owner) + return (); + } + if (op == op::fill_up_wrapper()) { + ;; do nothing + return (); + } + if (op == op::change_wrapper_code()) { + ;; todo + } + ;; otherwise, send the message to the target + } +} + +() send_msg(slice to_address, int amount, int op, int query_id, builder payload, int send_mode) impure inline { + var msg = begin_cell() + .store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 010000 + .store_slice(to_address) + .store_coins(amount) + .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) + .store_uint(op, 32) + .store_uint(query_id, 64); + + if (~ builder_null?(payload)) { + msg = msg.store_builder(payload); + } + + send_raw_message(msg.end_cell(), send_mode); +} + +() recv_external(slice in_msg_body) impure { + ;; handle external messages +} + +_ get_owner() method_id { + +}