mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Add legacy_tester for existing funC contracts (#588)
* Add legacy_tester for existing funC contracts * Add storage-contracts and pragma options
This commit is contained in:
parent
13b9f460af
commit
6b49d6a382
70 changed files with 14495 additions and 0 deletions
416
crypto/func/auto-tests/legacy_tests/tele-nft-item/common.fc
Normal file
416
crypto/func/auto-tests/legacy_tests/tele-nft-item/common.fc
Normal file
|
@ -0,0 +1,416 @@
|
|||
const int one_ton = 1000000000;
|
||||
const int dns_next_resolver_prefix = 0xba93; ;; dns_next_resolver prefix - https://github.com/ton-blockchain/ton/blob/7e3df93ca2ab336716a230fceb1726d81bac0a06/crypto/block/block.tlb#L819
|
||||
|
||||
const int op::fill_up = 0x370fec51;
|
||||
const int op::outbid_notification = 0x557cea20;
|
||||
const int op::change_dns_record = 0x4eb1f0f9;
|
||||
const int op::dns_balance_release = 0x4ed14b65;
|
||||
|
||||
const int op::telemint_msg_deploy = 0x4637289a;
|
||||
const int op::teleitem_msg_deploy = 0x299a3e15;
|
||||
const int op::teleitem_start_auction = 0x487a8e81;
|
||||
const int op::teleitem_cancel_auction = 0x371638ae;
|
||||
const int op::teleitem_bid_info = 0x38127de1;
|
||||
const int op::teleitem_return_bid = 0xa43227e1;
|
||||
const int op::teleitem_ok = 0xa37a0983;
|
||||
|
||||
const int op::nft_cmd_transfer = 0x5fcc3d14;
|
||||
const int op::nft_cmd_get_static_data = 0x2fcb26a2;
|
||||
const int op::nft_cmd_edit_content = 0x1a0b9d51;
|
||||
const int op::nft_answer_ownership_assigned = 0x05138d91;
|
||||
const int op::nft_answer_excesses = 0xd53276db;
|
||||
|
||||
const int op::ownership_assigned = 0x05138d91;
|
||||
const int op::excesses = 0xd53276db;
|
||||
const int op::get_static_data = 0x2fcb26a2;
|
||||
const int op::report_static_data = 0x8b771735;
|
||||
const int op::get_royalty_params = 0x693d3950;
|
||||
const int op::report_royalty_params = 0xa8cb00ad;
|
||||
|
||||
const int err::invalid_length = 201;
|
||||
const int err::invalid_signature = 202;
|
||||
const int err::wrong_subwallet_id = 203;
|
||||
const int err::not_yet_valid_signature = 204;
|
||||
const int err::expired_signature = 205;
|
||||
const int err::not_enough_funds = 206;
|
||||
const int err::wrong_topup_comment = 207;
|
||||
const int err::unknown_op = 208;
|
||||
const int err::uninited = 210;
|
||||
const int err::too_small_stake = 211;
|
||||
const int err::expected_onchain_content = 212;
|
||||
const int err::forbidden_not_deploy = 213;
|
||||
const int err::forbidden_not_stake = 214;
|
||||
const int err::forbidden_topup = 215;
|
||||
const int err::forbidden_transfer = 216;
|
||||
const int err::forbidden_change_dns = 217;
|
||||
const int err::forbidden_touch = 218;
|
||||
const int err::no_auction = 219;
|
||||
const int err::forbidden_auction = 220;
|
||||
const int err::already_has_stakes = 221;
|
||||
const int err::auction_already_started = 222;
|
||||
const int err::invalid_auction_config = 223;
|
||||
const int err::incorrect_workchain = 333;
|
||||
const int err::no_first_zero_byte = 413;
|
||||
const int err::bad_subdomain_length = 70;
|
||||
|
||||
const int min_tons_for_storage = one_ton;
|
||||
const int workchain = 0;
|
||||
|
||||
int equal_slices(slice a, slice b) asm "SDEQ";
|
||||
int builder_null?(builder b) asm "ISNULL";
|
||||
builder store_builder(builder to, builder from) asm "STBR";
|
||||
slice zero_address() asm "b{00} PUSHSLICE";
|
||||
(slice, int) skip_first_zero_byte?(slice cs) asm "x{00} SDBEGINSQ";
|
||||
|
||||
() force_chain(slice addr) impure inline {
|
||||
(int wc, _) = parse_std_addr(addr);
|
||||
throw_unless(err::incorrect_workchain, wc == workchain);
|
||||
}
|
||||
|
||||
|
||||
;; "ton\0test\0" -> "ton"
|
||||
int get_top_domain_bits(slice domain) inline {
|
||||
int i = -8;
|
||||
int char = 1;
|
||||
while (char) {
|
||||
i += 8;
|
||||
char = domain~load_uint(8); ;; we do not check domain.length because it MUST contains \0 character
|
||||
}
|
||||
throw_unless(201, i); ;; should not start with \0
|
||||
return i;
|
||||
}
|
||||
|
||||
_ load_text(slice cs) inline {
|
||||
int len = cs~load_uint(8);
|
||||
slice text = cs~load_bits(len * 8);
|
||||
return (cs, text);
|
||||
}
|
||||
|
||||
_ load_text_ref(slice cs) inline {
|
||||
slice text_cs = cs~load_ref().begin_parse();
|
||||
slice text = text_cs~load_text();
|
||||
return (cs, text);
|
||||
}
|
||||
|
||||
builder store_text(builder b, slice text) inline {
|
||||
int len = slice_bits(text);
|
||||
(int bytes, int rem) = len /% 8;
|
||||
throw_if(err::invalid_length, rem);
|
||||
return b.store_uint(bytes, 8)
|
||||
.store_slice(text);
|
||||
}
|
||||
|
||||
(slice, slice) unpack_token_info(cell c) inline {
|
||||
slice cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_text(),
|
||||
cs~load_text()
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
cell pack_token_info(slice name, slice domain) {
|
||||
return begin_cell()
|
||||
.store_text(name)
|
||||
.store_text(domain)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
cell pack_state_init(cell code, cell data) inline {
|
||||
return begin_cell()
|
||||
.store_uint(0, 2)
|
||||
.store_maybe_ref(code)
|
||||
.store_maybe_ref(data)
|
||||
.store_uint(0, 1)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
cell pack_init_int_message(slice dest, cell state_init, cell body) inline {
|
||||
return begin_cell()
|
||||
.store_uint(0x18, 6) ;; 011000 tag=0, ihr_disabled=1, allow_bounces=1, bounced=0, add_none
|
||||
.store_slice(dest)
|
||||
.store_grams(0) ;; grams
|
||||
.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
|
||||
.store_ref(state_init)
|
||||
.store_ref(body)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
() send_msg(slice to_address, int amount, int op, int query_id, builder payload, int 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_grams(amount)
|
||||
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
|
||||
.store_uint(op, 32)
|
||||
.store_uint(query_id, 64);
|
||||
|
||||
ifnot (builder_null?(payload)) {
|
||||
msg = msg.store_builder(payload);
|
||||
}
|
||||
|
||||
send_raw_message(msg.end_cell(), mode);
|
||||
}
|
||||
|
||||
slice calculate_address(int wc, cell state_init) inline {
|
||||
slice res = begin_cell()
|
||||
.store_uint(4, 3)
|
||||
.store_int(wc, 8)
|
||||
.store_uint(cell_hash(state_init), 256)
|
||||
.end_cell()
|
||||
.begin_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
(int, slice) unpack_item_config(cell c) inline {
|
||||
slice cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_uint(256),
|
||||
cs~load_msg_addr()
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
cell pack_item_config(int item_index, slice collection_address) inline {
|
||||
return begin_cell()
|
||||
.store_uint(item_index, 256)
|
||||
.store_slice(collection_address)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
(cell, cell) unpack_item_data() inline {
|
||||
var cs = get_data().begin_parse();
|
||||
var res = (cs~load_ref(), cs~load_maybe_ref());
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
cell pack_nft_royalty_params(int numerator, int denominator, slice destination) inline {
|
||||
return begin_cell()
|
||||
.store_uint(numerator, 16)
|
||||
.store_uint(denominator, 16)
|
||||
.store_slice(destination)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
(int, int, slice) unpack_nft_royalty_params(cell c) inline {
|
||||
var cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_uint(16),
|
||||
cs~load_uint(16),
|
||||
cs~load_msg_addr()
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
cell pack_item_data(cell config, cell state) inline {
|
||||
return begin_cell()
|
||||
.store_ref(config)
|
||||
.store_maybe_ref(state)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
cell pack_item_content(cell nft_content, cell dns, cell token_info) inline {
|
||||
return begin_cell()
|
||||
.store_ref(nft_content)
|
||||
.store_dict(dns)
|
||||
.store_ref(token_info)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
(cell, cell, cell) unpack_item_content(cell c) inline {
|
||||
var cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_ref(),
|
||||
cs~load_dict(),
|
||||
cs~load_ref()
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
(slice, cell, cell, cell) unpack_item_state(cell c) inline {
|
||||
var cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_msg_addr(),
|
||||
cs~load_ref(),
|
||||
cs~load_maybe_ref(),
|
||||
cs~load_ref()
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
cell pack_item_state(slice owner_address, cell content, cell auction, cell royalty_params) inline {
|
||||
return begin_cell()
|
||||
.store_slice(owner_address)
|
||||
.store_ref(content)
|
||||
.store_maybe_ref(auction)
|
||||
.store_ref(royalty_params)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
_ save_item_data(config, state) impure inline {
|
||||
set_data(pack_item_data(config, state));
|
||||
}
|
||||
|
||||
cell pack_item_state_init(int item_index, cell item_code) inline {
|
||||
var item_config = pack_item_config(item_index, my_address());
|
||||
var item_data = pack_item_data(item_config, null());
|
||||
return pack_state_init(item_code, item_data);
|
||||
}
|
||||
|
||||
cell pack_teleitem_msg_deploy(slice sender_address, int bid, cell info, cell content, cell auction_config, cell royalty_params) inline {
|
||||
return begin_cell()
|
||||
.store_uint(op::teleitem_msg_deploy, 32)
|
||||
.store_slice(sender_address)
|
||||
.store_grams(bid)
|
||||
.store_ref(info)
|
||||
.store_ref(content)
|
||||
.store_ref(auction_config)
|
||||
.store_ref(royalty_params)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
(slice, int, cell, cell, cell, cell) unpack_teleitem_msg_deploy(slice cs) inline {
|
||||
return (cs~load_msg_addr(),
|
||||
cs~load_grams(),
|
||||
cs~load_ref(),
|
||||
cs~load_ref(),
|
||||
cs~load_ref(),
|
||||
cs~load_ref());
|
||||
}
|
||||
|
||||
(int, int, int, cell, cell, slice, cell) unpack_collection_data() inline {
|
||||
var cs = get_data().begin_parse();
|
||||
var res = (
|
||||
cs~load_int(1), ;; touched
|
||||
cs~load_uint(32), ;; subwallet_id
|
||||
cs~load_uint(256), ;; owner_key
|
||||
cs~load_ref(), ;; content
|
||||
cs~load_ref(), ;; item_code
|
||||
cs~load_text_ref(), ;; full_domain
|
||||
cs~load_ref() ;; royalty_params
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
_ save_collection_data(int touched, int subwallet_id, int owner_key, cell content, cell item_code, slice full_domain, cell royalty_params) impure inline {
|
||||
cell data = begin_cell()
|
||||
.store_int(touched, 1)
|
||||
.store_uint(subwallet_id, 32)
|
||||
.store_uint(owner_key, 256)
|
||||
.store_ref(content)
|
||||
.store_ref(item_code)
|
||||
.store_ref(begin_cell().store_text(full_domain).end_cell())
|
||||
.store_ref(royalty_params)
|
||||
.end_cell();
|
||||
set_data(data);
|
||||
}
|
||||
|
||||
_ unpack_signed_cmd(slice cs) inline {
|
||||
return (
|
||||
cs~load_bits(512), ;; signature
|
||||
slice_hash(cs), ;; hash
|
||||
cs~load_uint(32), ;; subwallet_id
|
||||
cs~load_uint(32), ;; valid_since
|
||||
cs~load_uint(32), ;; valid_till
|
||||
cs ;; cmd
|
||||
);
|
||||
}
|
||||
|
||||
_ unpack_deploy_msg(slice cs) inline {
|
||||
var res = (
|
||||
cs~load_text(), ;; token_name
|
||||
cs~load_ref(), ;; content
|
||||
cs~load_ref(), ;; auction_config
|
||||
cs~load_maybe_ref() ;; royalty
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
;;teleitem_last_bid bidder_address:MsgAddressInt bid:Grams bid_ts:uint32 = TeleitemLastBid;
|
||||
(slice, int, int) unpack_last_bid(cell c) inline {
|
||||
slice cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_msg_addr(), ;; bidder_address
|
||||
cs~load_grams(), ;; bid
|
||||
cs~load_uint(32) ;; bid_ts
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
cell pack_last_bid(slice bidder_address, int bid, int bid_ts) inline {
|
||||
return begin_cell()
|
||||
.store_slice(bidder_address)
|
||||
.store_grams(bid)
|
||||
.store_uint(bid_ts, 32)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
;;teleitem_auction_state$_ last_bid:(Maybe ^TeleitemLastBid) min_bid:Grams end_time:uint32 = TeleitemAuctionState;
|
||||
(cell, int, int) unpack_auction_state(cell c) inline {
|
||||
slice cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_maybe_ref(), ;; maybe last_bid
|
||||
cs~load_grams(), ;; min_bid
|
||||
cs~load_uint(32) ;; end_time
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
cell pack_auction_state(cell last_bid, int min_bid, int end_time) inline {
|
||||
return begin_cell()
|
||||
.store_maybe_ref(last_bid)
|
||||
.store_grams(min_bid)
|
||||
.store_uint(end_time, 32)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
(slice, int, int, int, int, int) unpack_auction_config(cell c) inline {
|
||||
slice cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_msg_addr(), ;; beneficiary address
|
||||
cs~load_grams(), ;; initial_min_bid
|
||||
cs~load_grams(), ;; max_bid
|
||||
cs~load_uint(8), ;; min_bid_step
|
||||
cs~load_uint(32), ;; min_extend_time
|
||||
cs~load_uint(32) ;; duration
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
;;teleitem_auction$_ state:^TeleitemAuctionState config:^TeleitemConfig = TeleitemAuction;
|
||||
(cell, cell) unpack_auction(cell c) inline {
|
||||
slice cs = c.begin_parse();
|
||||
var res = (
|
||||
cs~load_ref(),
|
||||
cs~load_ref()
|
||||
);
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
cell pack_auction(cell state, cell config) inline {
|
||||
return begin_cell()
|
||||
.store_ref(state)
|
||||
.store_ref(config)
|
||||
.end_cell();
|
||||
}
|
||||
|
||||
(int, slice, slice, cell, int, slice) unpack_nft_cmd_transfer(slice cs) inline {
|
||||
return (
|
||||
cs~load_uint(64),
|
||||
cs~load_msg_addr(),
|
||||
cs~load_msg_addr(),
|
||||
cs~load_maybe_ref(),
|
||||
cs~load_grams(),
|
||||
cs
|
||||
);
|
||||
}
|
367
crypto/func/auto-tests/legacy_tests/tele-nft-item/nft-item.fc
Normal file
367
crypto/func/auto-tests/legacy_tests/tele-nft-item/nft-item.fc
Normal file
|
@ -0,0 +1,367 @@
|
|||
#include "stdlib.fc";
|
||||
#include "common.fc";
|
||||
|
||||
int send_money(int my_balance, slice address, int value) impure {
|
||||
int amount_to_send = min(my_balance - min_tons_for_storage, value);
|
||||
if (amount_to_send > 0) {
|
||||
send_msg(address, amount_to_send, op::fill_up, cur_lt(), null(), 2); ;; ignore errors
|
||||
my_balance -= amount_to_send;
|
||||
}
|
||||
return my_balance;
|
||||
}
|
||||
|
||||
(int, slice, cell) maybe_end_auction(int my_balance, slice owner, cell auction, cell royalty_params, int is_external) impure {
|
||||
(cell auction_state, cell auction_config) = unpack_auction(auction);
|
||||
(cell last_bid, int min_bid, int end_time) = unpack_auction_state(auction_state);
|
||||
if (now() < end_time) {
|
||||
return (my_balance, owner, auction);
|
||||
}
|
||||
if (is_external) {
|
||||
accept_message();
|
||||
}
|
||||
;; should end auction
|
||||
if (null?(last_bid)) {
|
||||
;; no stakes were made
|
||||
;; NB: owner is not null now
|
||||
return (my_balance, owner, null());
|
||||
}
|
||||
(slice beneficiary_address, _, _, _, _, _) = unpack_auction_config(auction_config);
|
||||
(slice bidder_address, int bid, int bid_ts) = unpack_last_bid(last_bid);
|
||||
(int royalty_num, int royalty_denom, slice royalty_address) = unpack_nft_royalty_params(royalty_params);
|
||||
|
||||
send_msg(bidder_address, 0, op::ownership_assigned, cur_lt(),
|
||||
begin_cell()
|
||||
.store_slice(owner)
|
||||
.store_int(0, 1)
|
||||
.store_uint(op::teleitem_bid_info, 32)
|
||||
.store_grams(bid)
|
||||
.store_uint(bid_ts, 32),
|
||||
1); ;; paying fees, revert on errors
|
||||
|
||||
if ((royalty_num > 0) & (royalty_denom > 0) & ~ equal_slices(royalty_address, beneficiary_address)) {
|
||||
int royalty_value = min(bid, muldiv(bid, royalty_num, royalty_denom));
|
||||
bid -= royalty_value;
|
||||
my_balance = send_money(my_balance, royalty_address, royalty_value);
|
||||
}
|
||||
|
||||
my_balance = send_money(my_balance, beneficiary_address, bid);
|
||||
|
||||
return (my_balance, bidder_address, null());
|
||||
}
|
||||
|
||||
(int, cell) process_new_bid(int my_balance, slice new_bid_address, int new_bid, cell auction) impure {
|
||||
(cell auction_state, cell auction_config) = unpack_auction(auction);
|
||||
(cell old_last_bid, int min_bid, int end_time) = unpack_auction_state(auction_state);
|
||||
throw_if(err::too_small_stake, new_bid < min_bid);
|
||||
(slice beneficiary_address, int initial_min_bid, int max_bid, int min_bid_step, int min_extend_time, _) = unpack_auction_config(auction_config);
|
||||
cell new_last_bid = pack_last_bid(new_bid_address, new_bid, now());
|
||||
int new_end_time = max(end_time, now() + min_extend_time);
|
||||
if ((max_bid > 0) & (new_bid >= max_bid)) {
|
||||
;; for maybe_end_auction
|
||||
new_end_time = 0;
|
||||
}
|
||||
;; step is at least GR$1
|
||||
int new_min_bid = max(new_bid + one_ton, (new_bid * (100 + min_bid_step) + 99) / 100);
|
||||
ifnot (cell_null?(old_last_bid)) {
|
||||
(slice old_bidder_address, int old_bid, _) = unpack_last_bid(old_last_bid);
|
||||
int to_send = min(my_balance - min_tons_for_storage, old_bid);
|
||||
if (to_send > 0) {
|
||||
send_msg(old_bidder_address, to_send, op::outbid_notification, cur_lt(), null(), 1);
|
||||
my_balance -= to_send;
|
||||
}
|
||||
}
|
||||
cell new_auction_state = pack_auction_state(new_last_bid, new_min_bid, new_end_time);
|
||||
return (my_balance, pack_auction(new_auction_state, auction_config));
|
||||
}
|
||||
|
||||
cell prepare_auction(cell auction_config) {
|
||||
(slice beneficiary_address, int initial_min_bid, int max_bid, int min_bid_step, int min_extend_time, int duration) = unpack_auction_config(auction_config);
|
||||
;; check beneficiary address
|
||||
parse_std_addr(beneficiary_address);
|
||||
if ((initial_min_bid < 2 * min_tons_for_storage) | ((max_bid != 0) & (max_bid < initial_min_bid)) |
|
||||
(min_bid_step <= 0) | (min_extend_time > 60 * 60 * 24 * 7) | (duration > 60 * 60 * 24 * 365)) {
|
||||
return null();
|
||||
}
|
||||
cell auction_state = pack_auction_state(null(), initial_min_bid, now() + duration);
|
||||
return pack_auction(auction_state, auction_config);
|
||||
}
|
||||
|
||||
cell deploy_item(int my_balance, slice msg) {
|
||||
;; Do not throw errors here!
|
||||
(slice bidder_address, int bid, cell token_info, cell nft_content, cell auction_config, cell royalty_params) = unpack_teleitem_msg_deploy(msg);
|
||||
cell auction = prepare_auction(auction_config);
|
||||
if (cell_null?(auction)) {
|
||||
return null();
|
||||
}
|
||||
(my_balance, cell new_auction) = process_new_bid(my_balance, bidder_address, bid, auction);
|
||||
(my_balance, slice owner, new_auction) = maybe_end_auction(my_balance, zero_address(), new_auction, royalty_params, 0);
|
||||
cell content = pack_item_content(nft_content, null(), token_info);
|
||||
return pack_item_state(owner, content, new_auction, royalty_params);
|
||||
|
||||
}
|
||||
|
||||
slice transfer_ownership(int my_balance, slice owner_address, slice in_msg_body, int fwd_fees) impure inline {
|
||||
(int query_id, slice new_owner_address, slice response_destination, cell custom_payload, int forward_amount, slice forward_payload)
|
||||
= unpack_nft_cmd_transfer(in_msg_body);
|
||||
|
||||
force_chain(new_owner_address);
|
||||
|
||||
int rest_amount = my_balance - min_tons_for_storage;
|
||||
if (forward_amount) {
|
||||
rest_amount -= (forward_amount + fwd_fees);
|
||||
}
|
||||
int need_response = response_destination.preload_uint(2) != 0; ;; if NOT addr_none: 00
|
||||
if (need_response) {
|
||||
rest_amount -= fwd_fees;
|
||||
}
|
||||
|
||||
throw_unless(err::not_enough_funds, rest_amount >= 0); ;; base nft spends fixed amount of gas, will not check for response
|
||||
|
||||
if (forward_amount) {
|
||||
send_msg(new_owner_address, forward_amount, op::ownership_assigned, query_id,
|
||||
begin_cell().store_slice(owner_address).store_slice(forward_payload), 1); ;; paying fees, revert on errors
|
||||
|
||||
}
|
||||
if (need_response) {
|
||||
force_chain(response_destination);
|
||||
send_msg(response_destination, rest_amount, op::excesses, query_id, null(), 1); ;; paying fees, revert on errors
|
||||
}
|
||||
|
||||
return new_owner_address;
|
||||
}
|
||||
|
||||
cell change_dns_record(cell dns, slice in_msg_body) {
|
||||
int key = in_msg_body~load_uint(256);
|
||||
int has_value = in_msg_body.slice_refs() > 0;
|
||||
|
||||
if (has_value) {
|
||||
cell value = in_msg_body~load_ref();
|
||||
dns~udict_set_ref(256, key, value);
|
||||
} else {
|
||||
dns~udict_delete?(256, key);
|
||||
}
|
||||
|
||||
return dns;
|
||||
}
|
||||
|
||||
() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
|
||||
int my_balance = pair_first(get_balance());
|
||||
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();
|
||||
|
||||
cs~load_msg_addr(); ;; skip dst
|
||||
cs~load_grams(); ;; skip value
|
||||
cs~load_maybe_ref(); ;; skip extracurrency collection
|
||||
cs~load_grams(); ;; skip ihr_fee
|
||||
int fwd_fee = muldiv(cs~load_grams(), 3, 2); ;; we use message fwd_:fee for estimation of forward_payload costs
|
||||
|
||||
int op = in_msg_body.slice_empty?() ? 0 : in_msg_body~load_uint(32);
|
||||
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(int index, slice collection_address) = unpack_item_config(config);
|
||||
|
||||
if (equal_slices(collection_address, sender_address)) {
|
||||
throw_unless(err::forbidden_not_deploy, op == op::teleitem_msg_deploy);
|
||||
if (cell_null?(state)) {
|
||||
cell new_state = deploy_item(my_balance, in_msg_body);
|
||||
ifnot (cell_null?(new_state)) {
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
}
|
||||
slice bidder_address = in_msg_body~load_msg_addr(); ;; first field in teleitem_msg_deploy
|
||||
send_msg(bidder_address, 0, op::teleitem_return_bid, cur_lt(), null(), 64); ;; carry all the remaining value of the inbound message
|
||||
return ();
|
||||
}
|
||||
|
||||
throw_if(err::uninited, cell_null?(state));
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
|
||||
if (op == op::get_royalty_params) {
|
||||
int query_id = in_msg_body~load_uint(64);
|
||||
send_msg(sender_address, 0, op::report_royalty_params, query_id, begin_cell().store_slice(royalty_params.begin_parse()), 64); ;; carry all the remaining value of the inbound message
|
||||
return ();
|
||||
}
|
||||
|
||||
if (op == op::nft_cmd_get_static_data) {
|
||||
int query_id = in_msg_body~load_uint(64);
|
||||
send_msg(sender_address, 0, op::report_static_data, query_id, begin_cell().store_uint(index, 256).store_slice(collection_address), 64); ;; carry all the remaining value of the inbound message
|
||||
return ();
|
||||
}
|
||||
|
||||
int is_topup = (op == 0) & equal_slices(in_msg_body, "#topup") & (in_msg_body.slice_refs() == 0);
|
||||
if (is_topup) {
|
||||
return ();
|
||||
}
|
||||
|
||||
ifnot (cell_null?(auction)) {
|
||||
;; sender do not pay for auction with its message
|
||||
my_balance -= msg_value;
|
||||
(my_balance, owner_address, auction) = maybe_end_auction(my_balance, owner_address, auction, royalty_params, 0);
|
||||
if (cell_null?(auction)) {
|
||||
cell new_state = pack_item_state(owner_address, content, auction, royalty_params);
|
||||
save_item_data(config, new_state);
|
||||
}
|
||||
my_balance += msg_value;
|
||||
}
|
||||
|
||||
if (op == op::teleitem_cancel_auction) {
|
||||
throw_if(err::no_auction, cell_null?(auction));
|
||||
throw_unless(err::forbidden_auction, equal_slices(sender_address, owner_address));
|
||||
int query_id = in_msg_body~load_uint(64);
|
||||
(cell auction_state, cell auction_config) = unpack_auction(auction);
|
||||
(cell last_bid, int min_bid, int end_time) = unpack_auction_state(auction_state);
|
||||
throw_unless(err::already_has_stakes, cell_null?(last_bid));
|
||||
cell new_state = pack_item_state(owner_address, content, null(), royalty_params);
|
||||
if (query_id) {
|
||||
send_msg(sender_address, 0, op::teleitem_ok, query_id, null(), 64); ;; carry all the remaining value of the inbound message
|
||||
}
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
|
||||
ifnot (cell_null?(auction)) {
|
||||
throw_unless(err::forbidden_not_stake, op == 0);
|
||||
(my_balance, auction) = process_new_bid(my_balance, sender_address, msg_value, auction);
|
||||
(my_balance, owner_address, auction) = maybe_end_auction(my_balance, owner_address, auction, royalty_params, 0);
|
||||
cell new_state = pack_item_state(owner_address, content, auction, royalty_params);
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
|
||||
if (op == 0) {
|
||||
throw_unless(err::forbidden_topup, equal_slices(sender_address, owner_address)); ;; only owner can fill-up balance, prevent coins lost right after the auction
|
||||
;; if owner send bid right after auction he can restore it by transfer response message
|
||||
return ();
|
||||
}
|
||||
|
||||
if (op == op::teleitem_start_auction) {
|
||||
throw_unless(err::forbidden_auction, equal_slices(sender_address, owner_address));
|
||||
int query_id = in_msg_body~load_uint(64);
|
||||
cell new_auction_config = in_msg_body~load_ref();
|
||||
cell new_auction = prepare_auction(new_auction_config);
|
||||
throw_if(err::invalid_auction_config, cell_null?(new_auction));
|
||||
cell new_state = pack_item_state(owner_address, content, new_auction, royalty_params);
|
||||
if (query_id) {
|
||||
send_msg(sender_address, 0, op::teleitem_ok, query_id, null(), 64); ;; carry all the remaining value of the inbound message
|
||||
}
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
|
||||
if (op == op::nft_cmd_transfer) {
|
||||
throw_unless(err::forbidden_transfer, equal_slices(sender_address, owner_address));
|
||||
slice new_owner_address = transfer_ownership(my_balance, owner_address, in_msg_body, fwd_fee);
|
||||
cell new_state = pack_item_state(new_owner_address, content, auction, royalty_params);
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
|
||||
if (op == op::change_dns_record) { ;; change dns record
|
||||
int query_id = in_msg_body~load_uint(64);
|
||||
throw_unless(err::forbidden_change_dns, equal_slices(sender_address, owner_address));
|
||||
(cell nft_content, cell dns, cell token_info) = unpack_item_content(content);
|
||||
cell new_dns = change_dns_record(dns, in_msg_body);
|
||||
cell new_content = pack_item_content(nft_content, new_dns, token_info);
|
||||
cell new_state = pack_item_state(owner_address, new_content, auction, royalty_params);
|
||||
send_msg(sender_address, 0, op::teleitem_ok, query_id, null(), 64); ;; carry all the remaining value of the inbound message
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
throw(err::unknown_op);
|
||||
}
|
||||
|
||||
() recv_external(slice in_msg) impure {
|
||||
int my_balance = pair_first(get_balance());
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
(my_balance, owner_address, auction) = maybe_end_auction(my_balance, owner_address, auction, royalty_params, -1);
|
||||
cell new_state = pack_item_state(owner_address, content, auction, royalty_params);
|
||||
return save_item_data(config, new_state);
|
||||
}
|
||||
|
||||
;;
|
||||
;; GET Methods
|
||||
;;
|
||||
|
||||
(int, int, slice, slice, cell) get_nft_data() method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(int item_index, slice collection_address) = unpack_item_config(config);
|
||||
if (cell_null?(state)) {
|
||||
return (0, item_index, collection_address, zero_address(), null());
|
||||
}
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
(cell nft_content, cell dns, cell token_info) = unpack_item_content(content);
|
||||
return (-1, item_index, collection_address, owner_address, nft_content);
|
||||
}
|
||||
|
||||
slice get_full_domain() method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
(cell nft_content, cell dns, cell token_info) = unpack_item_content(content);
|
||||
(slice token_name, slice domain) = unpack_token_info(token_info);
|
||||
return begin_cell().store_slice(domain).store_slice(token_name).store_int(0, 8).end_cell().begin_parse();
|
||||
}
|
||||
|
||||
slice get_telemint_token_name() method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
(cell nft_content, cell dns, cell token_info) = unpack_item_content(content);
|
||||
(slice token_name, slice domain) = unpack_token_info(token_info);
|
||||
return token_name;
|
||||
}
|
||||
|
||||
(slice, int, int, int, int) get_telemint_auction_state() method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
throw_if (err::no_auction, cell_null?(auction));
|
||||
(cell auction_state, cell auction_config) = unpack_auction(auction);
|
||||
(cell last_bid, int min_bid, int end_time) = unpack_auction_state(auction_state);
|
||||
(slice bidder_address, int bid, int bid_ts) = (null(), 0, 0);
|
||||
ifnot (cell_null?(last_bid)) {
|
||||
(bidder_address, bid, bid_ts) = unpack_last_bid(last_bid);
|
||||
}
|
||||
return (bidder_address, bid, bid_ts, min_bid, end_time);
|
||||
}
|
||||
|
||||
(slice, int, int, int, int, int) get_telemint_auction_config() method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
if (cell_null?(auction)) {
|
||||
;; Do not throw error, so it is easy to check if get_telemint_auction_config method exists
|
||||
return (null(), 0, 0, 0, 0, 0);
|
||||
}
|
||||
(cell auction_state, cell auction_config) = unpack_auction(auction);
|
||||
(slice beneficiary_address, int initial_min_bid, int max_bid, int min_bid_step, int min_extend_time, int duration) =
|
||||
unpack_auction_config(auction_config);
|
||||
return (beneficiary_address, initial_min_bid, max_bid, min_bid_step, min_extend_time, duration);
|
||||
}
|
||||
|
||||
(int, int, slice) royalty_params() method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
(int numerator, int denominator, slice destination) = unpack_nft_royalty_params(royalty_params);
|
||||
return (numerator, denominator, destination);
|
||||
}
|
||||
|
||||
(int, cell) dnsresolve(slice subdomain, int category) method_id {
|
||||
(cell config, cell state) = unpack_item_data();
|
||||
(slice owner_address, cell content, cell auction, cell royalty_params) = unpack_item_state(state);
|
||||
(cell nft_content, cell dns, cell token_info) = unpack_item_content(content);
|
||||
|
||||
int subdomain_bits = slice_bits(subdomain);
|
||||
throw_unless(err::bad_subdomain_length, subdomain_bits % 8 == 0);
|
||||
|
||||
int starts_with_zero_byte = subdomain.preload_int(8) == 0;
|
||||
throw_unless(err::no_first_zero_byte, starts_with_zero_byte);
|
||||
|
||||
if (subdomain_bits > 8) { ;; more than "." requested
|
||||
category = "dns_next_resolver"H;
|
||||
}
|
||||
|
||||
if (category == 0) { ;; all categories are requested
|
||||
return (8, dns);
|
||||
}
|
||||
|
||||
(cell value, int found) = dns.udict_get_ref?(256, category);
|
||||
return (8, value);
|
||||
}
|
208
crypto/func/auto-tests/legacy_tests/tele-nft-item/stdlib.fc
Normal file
208
crypto/func/auto-tests/legacy_tests/tele-nft-item/stdlib.fc
Normal file
|
@ -0,0 +1,208 @@
|
|||
;; Standard library for funC
|
||||
;;
|
||||
|
||||
forall X -> tuple cons(X head, tuple tail) asm "CONS";
|
||||
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
|
||||
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
|
||||
forall X -> X car(tuple list) asm "CAR";
|
||||
tuple cdr(tuple list) asm "CDR";
|
||||
tuple empty_tuple() asm "NIL";
|
||||
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
|
||||
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
|
||||
forall X -> [X] single(X x) asm "SINGLE";
|
||||
forall X -> X unsingle([X] t) asm "UNSINGLE";
|
||||
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
|
||||
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
|
||||
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
|
||||
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
|
||||
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
|
||||
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
|
||||
forall X -> X first(tuple t) asm "FIRST";
|
||||
forall X -> X second(tuple t) asm "SECOND";
|
||||
forall X -> X third(tuple t) asm "THIRD";
|
||||
forall X -> X fourth(tuple t) asm "3 INDEX";
|
||||
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
|
||||
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
|
||||
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
|
||||
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
|
||||
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
|
||||
forall X -> X null() asm "PUSHNULL";
|
||||
forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP";
|
||||
|
||||
int now() asm "NOW";
|
||||
slice my_address() asm "MYADDR";
|
||||
[int, cell] get_balance() asm "BALANCE";
|
||||
int cur_lt() asm "LTIME";
|
||||
int block_lt() asm "BLOCKLT";
|
||||
|
||||
int cell_hash(cell c) asm "HASHCU";
|
||||
int slice_hash(slice s) asm "HASHSU";
|
||||
int string_hash(slice s) asm "SHA256U";
|
||||
|
||||
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
|
||||
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
|
||||
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
|
||||
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
|
||||
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
|
||||
(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
|
||||
|
||||
;; () throw_if(int excno, int cond) impure asm "THROWARGIF";
|
||||
|
||||
() dump_stack() impure asm "DUMPSTK";
|
||||
|
||||
cell get_data() asm "c4 PUSH";
|
||||
() set_data(cell c) impure asm "c4 POP";
|
||||
cont get_c3() impure asm "c3 PUSH";
|
||||
() set_c3(cont c) impure asm "c3 POP";
|
||||
cont bless(slice s) impure asm "BLESS";
|
||||
|
||||
() accept_message() impure asm "ACCEPT";
|
||||
() set_gas_limit(int limit) impure asm "SETGASLIMIT";
|
||||
() commit() impure asm "COMMIT";
|
||||
() buy_gas(int gram) impure asm "BUYGAS";
|
||||
|
||||
int min(int x, int y) asm "MIN";
|
||||
int max(int x, int y) asm "MAX";
|
||||
(int, int) minmax(int x, int y) asm "MINMAX";
|
||||
int abs(int x) asm "ABS";
|
||||
|
||||
slice begin_parse(cell c) asm "CTOS";
|
||||
() end_parse(slice s) impure asm "ENDS";
|
||||
(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF";
|
||||
cell preload_ref(slice s) asm "PLDREF";
|
||||
;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX";
|
||||
;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX";
|
||||
;; int preload_int(slice s, int len) asm "PLDIX";
|
||||
;; int preload_uint(slice s, int len) asm "PLDUX";
|
||||
;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";
|
||||
;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
|
||||
(slice, int) load_grams(slice s) asm( -> 1 0) "LDGRAMS";
|
||||
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
|
||||
(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
|
||||
slice first_bits(slice s, int len) asm "SDCUTFIRST";
|
||||
slice skip_last_bits(slice s, int len) asm "SDSKIPLAST";
|
||||
(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST";
|
||||
slice slice_last(slice s, int len) asm "SDCUTLAST";
|
||||
(slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT";
|
||||
cell preload_dict(slice s) asm "PLDDICT";
|
||||
slice skip_dict(slice s) asm "SKIPDICT";
|
||||
|
||||
(slice, cell) load_maybe_ref(slice s) asm( -> 1 0) "LDOPTREF";
|
||||
cell preload_maybe_ref(slice s) asm "PLDOPTREF";
|
||||
builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF";
|
||||
|
||||
int cell_depth(cell c) asm "CDEPTH";
|
||||
|
||||
int slice_refs(slice s) asm "SREFS";
|
||||
int slice_bits(slice s) asm "SBITS";
|
||||
(int, int) slice_bits_refs(slice s) asm "SBITREFS";
|
||||
int slice_empty?(slice s) asm "SEMPTY";
|
||||
int slice_data_empty?(slice s) asm "SDEMPTY";
|
||||
int slice_refs_empty?(slice s) asm "SREMPTY";
|
||||
int slice_depth(slice s) asm "SDEPTH";
|
||||
|
||||
int builder_refs(builder b) asm "BREFS";
|
||||
int builder_bits(builder b) asm "BBITS";
|
||||
int builder_depth(builder b) asm "BDEPTH";
|
||||
|
||||
builder begin_cell() asm "NEWC";
|
||||
cell end_cell(builder b) asm "ENDC";
|
||||
builder store_ref(builder b, cell c) asm(c b) "STREF";
|
||||
;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
|
||||
;; builder store_int(builder b, int x, int len) asm(x b len) "STIX";
|
||||
builder store_slice(builder b, slice s) asm "STSLICER";
|
||||
builder store_grams(builder b, int x) asm "STGRAMS";
|
||||
builder store_dict(builder b, cell c) asm(c b) "STDICT";
|
||||
|
||||
(slice, slice) load_msg_addr(slice s) asm( -> 1 0) "LDMSGADDR";
|
||||
tuple parse_addr(slice s) asm "PARSEMSGADDR";
|
||||
(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR";
|
||||
(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR";
|
||||
|
||||
cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
|
||||
(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
|
||||
cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
|
||||
(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
|
||||
cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF";
|
||||
(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF" "NULLSWAPIFNOT";
|
||||
(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF" "NULLSWAPIFNOT";
|
||||
(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF";
|
||||
(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF";
|
||||
(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL";
|
||||
(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL";
|
||||
(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
|
||||
(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT";
|
||||
(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
|
||||
(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
|
||||
(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
|
||||
(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
|
||||
cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
|
||||
(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
|
||||
cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
|
||||
(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
|
||||
cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
|
||||
(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
|
||||
(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD";
|
||||
(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE";
|
||||
(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD";
|
||||
(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE";
|
||||
cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
|
||||
(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
|
||||
cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
|
||||
(cell, ()) ~idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
|
||||
cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
|
||||
(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
|
||||
(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB";
|
||||
(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB";
|
||||
(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB";
|
||||
(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB";
|
||||
(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
|
||||
(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
|
||||
(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
|
||||
(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
|
||||
(cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
|
||||
(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
|
||||
(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
|
||||
(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
|
||||
(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
|
||||
(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
|
||||
(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
|
||||
(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAX" "NULLSWAPIFNOT2";
|
||||
(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2";
|
||||
(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAX" "NULLSWAPIFNOT2";
|
||||
(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2";
|
||||
(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT2";
|
||||
(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2";
|
||||
cell new_dict() asm "NEWDICT";
|
||||
int dict_empty?(cell c) asm "DICTEMPTY";
|
||||
|
||||
(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTGETQ" "NULLSWAPIFNOT2";
|
||||
(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) "PFXDICTSET";
|
||||
(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTDEL";
|
||||
|
||||
cell config_param(int x) asm "CONFIGOPTPARAM";
|
||||
int cell_null?(cell c) asm "ISNULL";
|
||||
|
||||
() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
|
||||
() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX";
|
||||
() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG";
|
||||
() set_code(cell new_code) impure asm "SETCODE";
|
||||
|
||||
int random() impure asm "RANDU256";
|
||||
int rand(int range) impure asm "RAND";
|
||||
int get_seed() impure asm "RANDSEED";
|
||||
int set_seed() impure asm "SETRAND";
|
||||
() randomize(int x) impure asm "ADDRAND";
|
||||
() randomize_lt() impure asm "LTIME" "ADDRAND";
|
Loading…
Add table
Add a link
Reference in a new issue