From 59cb2a458427a98444540e27499af4fd41841539 Mon Sep 17 00:00:00 2001 From: Steve Korshakov Date: Mon, 17 Apr 2023 16:30:08 +0100 Subject: [PATCH] ref: add bug of func --- func/bug_0_4_3/echo_Echo.code.fc | 132 ++++++++++++++++++ func/bug_0_4_3/echo_Echo.constants.fc | 2 + func/bug_0_4_3/echo_Echo.headers.fc | 92 +++++++++++++ func/bug_0_4_3/echo_Echo.stdlib.fc | 188 ++++++++++++++++++++++++++ func/bug_0_4_3/echo_Echo.storage.fc | 70 ++++++++++ 5 files changed, 484 insertions(+) create mode 100644 func/bug_0_4_3/echo_Echo.code.fc create mode 100644 func/bug_0_4_3/echo_Echo.constants.fc create mode 100644 func/bug_0_4_3/echo_Echo.headers.fc create mode 100644 func/bug_0_4_3/echo_Echo.stdlib.fc create mode 100644 func/bug_0_4_3/echo_Echo.storage.fc diff --git a/func/bug_0_4_3/echo_Echo.code.fc b/func/bug_0_4_3/echo_Echo.code.fc new file mode 100644 index 000000000..35389f469 --- /dev/null +++ b/func/bug_0_4_3/echo_Echo.code.fc @@ -0,0 +1,132 @@ +#include "echo_Echo.headers.fc"; +#include "echo_Echo.stdlib.fc"; +#include "echo_Echo.constants.fc"; +#include "echo_Echo.storage.fc"; + +;; +;; Contract Echo functions +;; + +tuple $Echo$_contract_init(int $a) impure inline_ref { + tuple $self = null(); + return $self; +} + +(tuple, slice) $Echo$_fun_hello(tuple $self, slice $src) impure inline_ref { + var ($self) = $self; + tuple $builder = __tact_string_builder_start_string(); + $builder~__tact_string_builder_append(__gen_slice_string_f370faf8638967dd9ace3fe077417700dc2370082f3795482bcb6285b962df24()); + $builder~__tact_string_builder_append($src); + return ($self, __tact_string_builder_end_slice($builder)); +} + +;; +;; Receivers of a Contract Echo +;; + +((tuple), ()) $Echo$_internal_binary_EchoMessage(tuple $self, tuple $msg) impure inline { + var $self = $self; + var $msg = $msg; + $self~$Echo$_fun_reply($EchoMessage$_store_cell($msg)); + return ($self, ()); +} + +(tuple, ()) $Echo$_internal_any_text(tuple $self, slice $msg) impure inline { + var $self = $self; + $self~$Echo$_fun_reply($String$_fun_asComment($msg)); + return ($self, ()); +} + +(tuple, ()) $Echo$_internal_any(tuple $self, slice $msg) impure inline { + var $self = $self; + $self~$Echo$_fun_reply($Slice$_fun_asCell($msg)); + return ($self, ()); +} + +;; +;; Get methods of a Contract Echo +;; + +_ %hello(slice $$src) method_id(115554) { + slice $src = $$src; + var self = $Echo$_contract_load(); + var res = self~$Echo$_fun_hello($src); + return res; +} + +_ supported_interfaces() method_id { + return ( + "org.ton.introspection.v0"H >> 128, + "org.ton.abi.ipfs.v0"H >> 128, + "org.ton.deploy.lazy.v0"H >> 128, + "org.ton.chain.workchain.v0"H >> 128 + ); +} + +_ get_abi_ipfs() method_id { + return "ipfs://QmXa2PZRMKJz3A9tGDdANBWoKAAeiyhrVE4CRz2aitkj1z"; +} + +_ lazy_deployment_completed() method_id { + return get_data().begin_parse().load_int(1); +} + +;; +;; Routing of a Contract Echo +;; + +(tuple, int) $Echo$_contract_router_internal(tuple self, int msg_bounced, slice in_msg) impure inline_ref { + ;; Handle bounced messages + if (msg_bounced) { + return (self, true); + } + + ;; Parse incoming message + int op = 0; + if (slice_bits(in_msg) >= 32) { + op = in_msg.preload_uint(32); + } + + + ;; Receive EchoMessage message + if (op == 2074217921) { + var msg = in_msg~$EchoMessage$_load(); + self~$Echo$_internal_binary_EchoMessage(msg); + return (self, true); + } + + ;; Text Receivers + if (op == 0) { + if (slice_bits(in_msg) >= 32) { + self~$Echo$_internal_any_text(in_msg.skip_bits(32)); + return (self, true); + } + } + + ;; Receiver fallback + self~$Echo$_internal_any(in_msg); + return (self, true); +} + +() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { + + ;; Context + var cs = in_msg_cell.begin_parse(); + var msg_flags = cs~load_uint(4); + var msg_bounced = -(msg_flags & 1); + slice msg_sender_addr = __tact_verify_address(cs~load_msg_addr()); + __tact_context = (msg_bounced, msg_sender_addr, msg_value, cs); + __tact_context_sender = msg_sender_addr; + + ;; Load contract data + var self = $Echo$_contract_load(); + + ;; Handle operation + int handled = self~$Echo$_contract_router_internal(msg_bounced, in_msg); + + ;; Throw if not handled + throw_unless(130, handled); + + ;; Persist state + $Echo$_contract_store(self); +} diff --git a/func/bug_0_4_3/echo_Echo.constants.fc b/func/bug_0_4_3/echo_Echo.constants.fc new file mode 100644 index 000000000..1fca771b6 --- /dev/null +++ b/func/bug_0_4_3/echo_Echo.constants.fc @@ -0,0 +1,2 @@ +;; String "Hello, " +slice __gen_slice_string_f370faf8638967dd9ace3fe077417700dc2370082f3795482bcb6285b962df24() asm "B{b5ee9c7241010101000900000e48656c6c6f2c20e8d197d2} B>boc X __tact_not_null(X x) inline; + +;; __tact_context_get +(int, slice, int, slice) __tact_context_get() inline; + +;; __tact_context_get_sender +slice __tact_context_get_sender() inline; + +;; __tact_store_bool +builder __tact_store_bool(builder b, int v) inline; + +;; __tact_string_builder_start +tuple __tact_string_builder_start(builder b) inline; + +;; __tact_string_builder_start_comment +tuple __tact_string_builder_start_comment() inline; + +;; __tact_string_builder_start_string +tuple __tact_string_builder_start_string() inline; + +;; __tact_string_builder_end +cell __tact_string_builder_end(tuple builders) inline; + +;; __tact_string_builder_end_slice +slice __tact_string_builder_end_slice(tuple builders) inline; + +;; __tact_string_builder_append +((tuple), ()) __tact_string_builder_append(tuple builders, slice sc) inline_ref; + +;; $EchoMessage$_store +builder $EchoMessage$_store(builder build_0, tuple v) inline; + +;; $EchoMessage$_store_cell +cell $EchoMessage$_store_cell(tuple v) inline; + +;; $EchoMessage$_load +(slice, (tuple)) $EchoMessage$_load(slice sc_0) inline; + +;; $StateInit$_not_null +((cell, cell)) $StateInit$_not_null(tuple v) inline; + +;; $Echo$init$_load +(slice, ((int))) $Echo$init$_load(slice sc_0) inline; + +;; $Echo$_contract_init +tuple $Echo$_contract_init(int $a) impure inline_ref; + +;; $Echo$_contract_load +tuple $Echo$_contract_load() impure inline_ref; + +;; $Echo$_contract_store +() $Echo$_contract_store(tuple v) impure inline; + +;; $global_send +() $global_send((int, slice, int, int, cell, cell, cell) $params) impure inline_ref; + +;; $Slice$_fun_asCell +cell $Slice$_fun_asCell(slice $self) impure inline; + +;; $String$_fun_asComment +cell $String$_fun_asComment(slice $self) impure inline_ref; + +;; $Echo$_fun_hello +(tuple, slice) $Echo$_fun_hello(tuple $self, slice $src) impure inline_ref; + +;; $SendParameters$_constructor_bounce_to_value_mode_body_code_data +((int, slice, int, int, cell, cell, cell)) $SendParameters$_constructor_bounce_to_value_mode_body_code_data(int bounce, slice to, int value, int mode, cell body, cell code, cell data) inline; + +;; $Echo$_fun_forward +(tuple, ()) $Echo$_fun_forward(tuple $self, slice $to, cell $body, int $bounce, tuple $init) impure inline_ref; + +;; $Echo$_fun_reply +(tuple, ()) $Echo$_fun_reply(tuple $self, cell $body) impure inline; diff --git a/func/bug_0_4_3/echo_Echo.stdlib.fc b/func/bug_0_4_3/echo_Echo.stdlib.fc new file mode 100644 index 000000000..05dce6060 --- /dev/null +++ b/func/bug_0_4_3/echo_Echo.stdlib.fc @@ -0,0 +1,188 @@ +global (int, slice, int, slice) __tact_context; +global slice __tact_context_sender; +global cell __tact_context_sys; +global int __tact_randomized; + +slice __tact_verify_address(slice address) inline { + throw_unless(136, address.slice_bits() == 267); + var h = address.preload_uint(11); + throw_if(137, h == 1279); + throw_unless(136, h == 1024); + return address; +} + +builder __tact_store_address(builder b, slice address) inline { + return b.store_slice(__tact_verify_address(address)); +} + +int __tact_my_balance() inline { + return pair_first(get_balance()); +} + +forall X -> X __tact_not_null(X x) inline { + throw_if(128, null?(x)); return x; +} + +(int, slice, int, slice) __tact_context_get() inline { + return __tact_context; +} + +slice __tact_context_get_sender() inline { + return __tact_context_sender; +} + +builder __tact_store_bool(builder b, int v) inline { + return b.store_int(v, 1); +} + +forall X0, X1 -> (X0, X1) __tact_tuple_destroy_2(tuple v) asm "2 UNTUPLE"; + +tuple __tact_string_builder_start(builder b) inline { + return tpush(tpush(empty_tuple(), b), null()); +} + +tuple __tact_string_builder_start_comment() inline { + return __tact_string_builder_start(begin_cell().store_uint(0, 32)); +} + +tuple __tact_string_builder_start_string() inline { + return __tact_string_builder_start(begin_cell()); +} + +cell __tact_string_builder_end(tuple builders) inline { + (builder b, tuple tail) = uncons(builders); + cell c = b.end_cell(); + while(~ null?(tail)) { + (b, tail) = uncons(tail); + c = b.store_ref(c).end_cell(); + } + return c; +} + +slice __tact_string_builder_end_slice(tuple builders) inline { + return __tact_string_builder_end(builders).begin_parse(); +} + +((tuple), ()) __tact_string_builder_append(tuple builders, slice sc) inline_ref { + int sliceRefs = slice_refs(sc); + int sliceBits = slice_bits(sc); + + while((sliceBits > 0) | (sliceRefs > 0)) { + + ;; Load the current builder + (builder b, tuple tail) = uncons(builders); + int remBytes = 127 - (builder_bits(b) / 8); + int exBytes = sliceBits / 8; + + ;; Append bits + int amount = min(remBytes, exBytes); + if (amount > 0) { + slice read = sc~load_bits(amount * 8); + b = b.store_slice(read); + } + + ;; Update builders + builders = cons(b, tail); + + ;; Check if we need to add a new cell and continue + if (exBytes - amount > 0) { + var bb = begin_cell(); + builders = cons(bb, builders); + sliceBits = (exBytes - amount) * 8; + } elseif (sliceRefs > 0) { + sc = sc~load_ref().begin_parse(); + sliceRefs = slice_refs(sc); + sliceBits = slice_bits(sc); + } else { + sliceBits = 0; + sliceRefs = 0; + } + } + + return ((builders), ()); +} + +() $global_send((int, slice, int, int, cell, cell, cell) $params) impure inline_ref { + var (($params'bounce, $params'to, $params'value, $params'mode, $params'body, $params'code, $params'data)) = $params; + builder $b = begin_cell(); + $b = store_int($b, 1, 2); + $b = __tact_store_bool($b, $params'bounce); + $b = store_int($b, 0, 3); + $b = __tact_store_address($b, $params'to); + $b = store_coins($b, $params'value); + $b = store_int($b, 0, ((((1 + 4) + 4) + 64) + 32)); + if (( ((~ null?($params'code))) ? (true) : ((~ null?($params'data))) )) { + $b = __tact_store_bool($b, true); + builder $bc = begin_cell(); + $bc = __tact_store_bool($bc, false); + $bc = __tact_store_bool($bc, false); + if ((~ null?($params'code))) { + $bc = __tact_store_bool($bc, true); + $bc = store_ref($bc, __tact_not_null($params'code)); + } else { + $bc = __tact_store_bool($bc, false); + } + if ((~ null?($params'data))) { + $bc = __tact_store_bool($bc, true); + $bc = store_ref($bc, __tact_not_null($params'data)); + } else { + $bc = __tact_store_bool($bc, false); + } + $bc = __tact_store_bool($bc, false); + $b = __tact_store_bool($b, true); + $b = store_ref($b, end_cell($bc)); + } else { + $b = __tact_store_bool($b, false); + } + cell $body = $params'body; + if ((~ null?($body))) { + $b = __tact_store_bool($b, true); + $b = store_ref($b, __tact_not_null($body)); + } else { + $b = __tact_store_bool($b, false); + } + cell $c = end_cell($b); + send_raw_message($c, $params'mode); +} + +cell $Slice$_fun_asCell(slice $self) impure inline { + var ($self) = $self; + return end_cell(store_slice(begin_cell(), $self)); +} + +cell $String$_fun_asComment(slice $self) impure inline_ref { + var ($self) = $self; + tuple $b = __tact_string_builder_start_comment(); + $b~__tact_string_builder_append($self); + return __tact_string_builder_end($b); +} + +(tuple, ()) $Echo$_fun_forward(tuple $self, slice $to, cell $body, int $bounce, tuple $init) impure inline_ref { + var ($self) = $self; + var ($init) = $init; + cell $code = null(); + cell $data = null(); + if ((~ null?($init))) { + var ($init2'code, $init2'data) = $StateInit$_not_null($init); + $code = $init2'code; + $data = $init2'data; + } + if ((0 > 0)) { + var ($ctx'bounced, $ctx'sender, $ctx'value, $ctx'raw) = __tact_context_get(); + int $balance = __tact_my_balance(); + int $balanceBeforeMessage = ($balance - $ctx'value); + if (($balanceBeforeMessage < 0)) { + raw_reserve(0, 0); + $global_send($SendParameters$_constructor_bounce_to_value_mode_body_code_data($bounce, $to, 0, (128 + 2), $body, $code, $data)); + return ($self, ()); + } + } + $global_send($SendParameters$_constructor_bounce_to_value_mode_body_code_data($bounce, $to, 0, (64 + 2), $body, $code, $data)); + return ($self, ()); +} + +(tuple, ()) $Echo$_fun_reply(tuple $self, cell $body) impure inline { + var ($self) = $self; + $self~$Echo$_fun_forward(__tact_context_get_sender(), $body, true, null()); + return ($self, ()); +} \ No newline at end of file diff --git a/func/bug_0_4_3/echo_Echo.storage.fc b/func/bug_0_4_3/echo_Echo.storage.fc new file mode 100644 index 000000000..f11f58730 --- /dev/null +++ b/func/bug_0_4_3/echo_Echo.storage.fc @@ -0,0 +1,70 @@ +;; +;; Type: StateInit +;; TLB: _ code:^cell data:^cell = StateInit +;; + +((cell, cell)) $StateInit$_not_null(tuple v) inline { + throw_if(128, null?(v)); + var (cell vvv'code, cell vvv'data) = __tact_tuple_destroy_2(v); + return (vvv'code, vvv'data); +} + +;; +;; Type: SendParameters +;; TLB: _ bounce:bool to:address value:int257 mode:int257 body:Maybe ^cell code:Maybe ^cell data:Maybe ^cell = SendParameters +;; + +((int, slice, int, int, cell, cell, cell)) $SendParameters$_constructor_bounce_to_value_mode_body_code_data(int bounce, slice to, int value, int mode, cell body, cell code, cell data) inline { + return (bounce, to, value, mode, body, code, data); +} + +;; +;; Type: EchoMessage +;; Header: 0x7ba20dc1 +;; TLB: echo_message#7ba20dc1 = EchoMessage +;; + +builder $EchoMessage$_store(builder build_0, tuple v) inline { + build_0 = store_uint(build_0, 2074217921, 32); + return build_0; +} + +cell $EchoMessage$_store_cell(tuple v) inline { + return $EchoMessage$_store(begin_cell(), v).end_cell(); +} + +(slice, (tuple)) $EchoMessage$_load(slice sc_0) inline { + throw_unless(129, sc_0~load_uint(32) == 2074217921); + return (sc_0, null()); +} + +;; +;; Type: Echo +;; + +(slice, ((int))) $Echo$init$_load(slice sc_0) inline { + var v'a = sc_0~load_int(257); + return (sc_0, (v'a)); +} + +tuple $Echo$_contract_load() impure inline_ref { + slice $sc = get_data().begin_parse(); + __tact_context_sys = $sc~load_ref(); + int $loaded = $sc~load_int(1); + if ($loaded) { + return null(); + } else { + ;; Allow only workchain deployments + throw_unless(137, my_address().preload_uint(11) == 1024); + (int a) = $sc~$Echo$init$_load(); + $sc.end_parse(); + return $Echo$_contract_init(a); + } +} + +() $Echo$_contract_store(tuple v) impure inline { + builder b = begin_cell(); + b = b.store_ref(__tact_context_sys); + b = b.store_int(true, 1); + set_data(b.end_cell()); +} \ No newline at end of file