From cee1dd5de4798233e928439040601872c111b547 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 11:07:53 +0200 Subject: [PATCH 01/32] Remove unneeded statements from tests --- test/examples/dispatch/Revert.solc | 3 --- test/examples/dispatch/basic.solc | 4 ---- test/examples/dispatch/concat.solc | 4 ---- test/examples/dispatch/miniERC20.solc | 4 ---- test/examples/dispatch/neg.solc | 5 +---- 5 files changed, 1 insertion(+), 19 deletions(-) diff --git a/test/examples/dispatch/Revert.solc b/test/examples/dispatch/Revert.solc index 1e5569370..88e8229da 100644 --- a/test/examples/dispatch/Revert.solc +++ b/test/examples/dispatch/Revert.solc @@ -1,8 +1,5 @@ import std.{*}; import std.dispatch.{*}; -pragma no-patterson-condition ; -pragma no-coverage-condition ; -pragma no-bounded-variable-condition ; function my_revert() -> word { revertLit("regression"); diff --git a/test/examples/dispatch/basic.solc b/test/examples/dispatch/basic.solc index c49ee5af7..7eee12aa6 100644 --- a/test/examples/dispatch/basic.solc +++ b/test/examples/dispatch/basic.solc @@ -1,9 +1,5 @@ import std.{*}; -import std.{uint256, Add}; import std.dispatch.{*}; -pragma no-patterson-condition ; -pragma no-coverage-condition ; -pragma no-bounded-variable-condition ; contract C { constructor() {} diff --git a/test/examples/dispatch/concat.solc b/test/examples/dispatch/concat.solc index 74bc4322a..4d0b59bfe 100644 --- a/test/examples/dispatch/concat.solc +++ b/test/examples/dispatch/concat.solc @@ -1,9 +1,5 @@ import std.{*}; -import std.{bytes32, uint256, memory, Typedef, concat, to_bytes, empty}; import std.dispatch.{*}; -pragma no-patterson-condition ; -pragma no-coverage-condition ; -pragma no-bounded-variable-condition ; contract C { constructor() {} diff --git a/test/examples/dispatch/miniERC20.solc b/test/examples/dispatch/miniERC20.solc index e7455ea83..017fdb1c7 100644 --- a/test/examples/dispatch/miniERC20.solc +++ b/test/examples/dispatch/miniERC20.solc @@ -1,9 +1,5 @@ import std.{*}; -import std.{address, uint256, mapping, string, memory, Num, Add, Sub, Bounded, Eq, Ord, Typedef}; import std.dispatch.{*}; -pragma no-patterson-condition ; -pragma no-coverage-condition ; -pragma no-bounded-variable-condition ; function caller() -> address { let res: word; diff --git a/test/examples/dispatch/neg.solc b/test/examples/dispatch/neg.solc index ea2b63b4b..b04d0a8a9 100644 --- a/test/examples/dispatch/neg.solc +++ b/test/examples/dispatch/neg.solc @@ -1,8 +1,5 @@ -import std.dispatch.{*}; import std.{*}; -pragma no-patterson-condition; -pragma no-coverage-condition; -pragma no-bounded-variable-condition; +import std.dispatch.{*}; forall a. class a : Neg { From e26ebdf6cc9d31281270c850be978856cc9f0370 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 16:32:16 +0200 Subject: [PATCH 02/32] Use std.opcodes --- std/dispatch.solc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index 868ca42f6..e59cc56f8 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -1,4 +1,5 @@ import std.{*}; +import std.opcodes.{callvalue}; export { ABIString, @@ -256,10 +257,7 @@ instance Payable:MethodLevelCallvalueCheck { // NonPayable methods revert if passed value instance NonPayable:MethodLevelCallvalueCheck { function checkCallvalue(prx : Proxy(NonPayable)) -> () { - let value: word; - assembly { - value := callvalue() - } + let value = callvalue(); if (value > 0) { let NonPayableReceivedValue = Error(0xb5988ea3); revertWithError(NonPayableReceivedValue); From 7c0e4c541fbdfda2ba5cdb26dc41bea54b9e9628 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 16:33:01 +0200 Subject: [PATCH 03/32] Use std/opcodes in std --- std/std.solc | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/std/std.solc b/std/std.solc index 4686cf2ce..68e3014dc 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,3 +1,5 @@ +import std.opcodes.{add, mstore, mload, mcopy}; + pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; @@ -85,8 +87,8 @@ export { memberAccessBase, memory(*), memory_ref, - mload, - mstore, + // mload, // Re-exporting does not work yet +// mstore, ne, not, or, @@ -419,11 +421,7 @@ function gtWord(x:word, y:word) -> bool { } function addWord(l: word, r: word) -> word { - let rw : word; - assembly { - rw := add(l,r) - } - return rw; + return add(l, r); } function subWord(l: word, r: word) -> word { @@ -805,16 +803,6 @@ data mapping(member, index) = mapping(word) ; // --- Low-level memory ops -function mload(a:word) -> word { - let res: word; - assembly { res := mload(a) } - return res; -} - -function mstore(a:word, v:word) -> () { - assembly { mstore(a,v) } -} - function strlen(s:memory(string)) -> word { match s { | memory(a) => return mload(a); } } @@ -989,7 +977,7 @@ instance MemoryWordReader:WordReader { } function copyToMem(reader:MemoryWordReader, dst:word, cnt: word) -> () { match reader { - | MemoryWordReader(ptr) => assembly { mcopy(dst, ptr, cnt) } + | MemoryWordReader(ptr) => mcopy(dst, ptr, cnt); } } } From 1c7ae5494e43544d967bbbec86299378db8d1db5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 16:54:06 +0200 Subject: [PATCH 04/32] Use sstore/sload --- std/std.solc | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/std/std.solc b/std/std.solc index 68e3014dc..5e83b1f5c 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,4 +1,4 @@ -import std.opcodes.{add, mstore, mload, mcopy}; +import std.opcodes.{add, mstore, mload, mcopy, sstore, sload}; pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; @@ -1529,19 +1529,13 @@ pragma no-bounded-variable-condition LVA, RVA; // -- storage function sload_(x:word) -> word { - let res: word; - assembly { - res := sload(x) - } - return res; - } + return sload(x); +} function sstore_(a:word, v:word) -> () { - assembly { sstore(a,v) } + sstore(a, v); } - - forall self. class self:StorageSize { function size(x:Proxy(self)) -> word; @@ -1620,34 +1614,21 @@ class self:StorageType { instance word:StorageType { function load(ptr:word) -> word { - let r:word; - assembly { - r := sload(ptr) - } - return r; + return sload(ptr); } function store(ptr:word, value:word) -> () { - assembly { - sstore(ptr, value) - } + sstore(ptr, value); } } forall a. a:Typedef(word) => function sloadViaWord(ptr:word) -> a { - let r:word; - assembly { - r := sload(ptr) - } - return Typedef.abs(r); + return Typedef.abs(sload(ptr)); } forall a. a:Typedef(word) => function sstoreViaWord(ptr:word, value:a) -> () { - let w: word = Typedef.rep(value); - assembly { - sstore(ptr, w) - } + sstore(ptr, Typedef.rep(value)); } instance uint256:StorageType { From cc934ae2e0f4b059b36757eb6938125c5223cf41 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 17:38:01 +0200 Subject: [PATCH 05/32] use new helpers --- std/std.solc | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/std/std.solc b/std/std.solc index 5e83b1f5c..abc8a364f 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,4 +1,5 @@ import std.opcodes.{add, mstore, mload, mcopy, sstore, sload}; +//import std.opcodes.{not} as not_; pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; @@ -1245,24 +1246,34 @@ instance bool:ABIEncode { } } -function round_up_to_mul_of_32(value:word) -> word { - return bandWord(value + 31, bnotWord(31)); +// TODO: support import renaming +function and_(a: word, b: word) -> word { + let res; + assembly { + res := and(a, b) + } + return res; } -function encodeIntoFromBytesLike(srcPtr:word, basePtr:word, offset:word, tail:word) -> word { - let tailOffset = tail - basePtr; - +function not_(a: word) -> word { + let res; assembly { - let length := mload(srcPtr) - let total := add(length, 32) - - mstore(add(basePtr, offset), sub(tail, basePtr)) - mcopy(tail, srcPtr, total) - let rounded := and(add(total, 31), not(31)) - tail := add(tail, rounded) + res := not(a) } + return res; +} - return tail; +function round_up_to_mul_of_32(value:word) -> word { + return and_(value + 31, not_(31)); +} + +function encodeIntoFromBytesLike(srcPtr:word, basePtr:word, offset:word, tail:word) -> word { + let tailOffset = tail - basePtr; + let length = mload(srcPtr); + let total = length + 32; + mstore(basePtr + offset, tail - basePtr); + mcopy(tail, srcPtr, total); + return tail + round_up_to_mul_of_32(total); } instance memory(string):ABIEncode { From 8e76b2307dd98aff864a825522b5d769d0f0e38f Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 17:56:17 +0200 Subject: [PATCH 06/32] Rewrite dispatch assembly blocks --- std/dispatch.solc | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index e59cc56f8..a43bd9b02 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -1,5 +1,5 @@ import std.{*}; -import std.opcodes.{callvalue}; +import std.opcodes.{callvalue, calldatasize, calldataload, shr}; export { ABIString, @@ -84,7 +84,7 @@ forall name payability args rets fn function compute(prx : Proxy(Method(name,payability,args,rets,fn))) -> bytes4 { // let hash : word = keccakLit(sigStr(prx)); let hash = keccakLit(sigStr(Proxy:Proxy(name)) + "(" + sigStr(Proxy:Proxy(args)) + ")"); - return bytes4(bshrWord(224, hash)); + return bytes4(shr(224, hash)); } } @@ -157,10 +157,7 @@ forall args rets fn => function do_exec(pargs : Proxy(args), prets : Proxy(rets), fn : fn) -> () { // check we have enough calldata for the head of args let hdsz = ABIAttribs.headSize(pargs); - let cdsz; - assembly { - cdsz := calldatasize() - } + let cdsz = calldatasize(); if ((cdsz - 4) < hdsz) { let ABIInputTruncated = Error(0x08638556); revertWithError(ABIInputTruncated); @@ -234,10 +231,7 @@ forall n m . n:ExecMethod, n:Selector, m:RunDispatch => instance (n,m):RunDispat // Given evidence of a type with a known selector, we can check if it matches the selector in the first four bytes of calldata forall ty . ty:Selector => function selector_matches(prx : Proxy(ty)) -> bool { let candidate = Typedef.rep(Selector.compute(prx)); - let selector: word; - assembly { - selector := shr(224, calldataload(0)) - } + let selector = shr(224, calldataload(0)); return selector == candidate; } @@ -287,11 +281,9 @@ forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(meth // calldata shorter than 4 bytes can't contain a selector — skip // dispatch and invoke the fallback directly (matches Solidity) - let cdsz: word; - assembly { - cdsz := calldatasize() - } + let cdsz = calldatasize(); if (cdsz >= 4) { + // dispatch to method based on selector RunDispatch.go(ms); } // fallthrough to fallback -- this will be reached upon short input From b41898d589bb20a052fd241a9b47e758619608c3 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 17:59:12 +0200 Subject: [PATCH 07/32] Rewrite std assembly blocks --- std/std.solc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/std/std.solc b/std/std.solc index abc8a364f..aa9f29a19 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,4 +1,4 @@ -import std.opcodes.{add, mstore, mload, mcopy, sstore, sload}; +import std.opcodes.{add, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy}; //import std.opcodes.{not} as not_; pragma no-patterson-condition ABIEncode, Num; @@ -997,14 +997,9 @@ instance CalldataWordReader : Typedef(word) { instance CalldataWordReader:WordReader { function read(reader:CalldataWordReader) -> word { - let result : word; match reader { - | CalldataWordReader(ptr) => - // https://github.com/argotorg/solcore/issues/188 - let ptr2 = ptr; - assembly { result := calldataload(ptr2) } + | CalldataWordReader(ptr) => return calldataload(ptr); } - return result; } function advance(reader:CalldataWordReader, offset:word) -> CalldataWordReader { match reader { @@ -1013,7 +1008,7 @@ instance CalldataWordReader:WordReader { } function copyToMem(reader:CalldataWordReader, dst:word, cnt: word) -> () { match reader { - | CalldataWordReader(ptr) => assembly { calldatacopy(dst, ptr, cnt) } + | CalldataWordReader(ptr) => calldatacopy(dst, ptr, cnt); } } } From 1d596d10c298715752c2ebf295c0dbf33b40cf20 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 18:08:51 +0200 Subject: [PATCH 08/32] Rewrite loadBytesFromStorage --- std/std.solc | 61 ++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/std/std.solc b/std/std.solc index aa9f29a19..5db442698 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,4 +1,4 @@ -import std.opcodes.{add, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy}; +import std.opcodes.{add, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256}; //import std.opcodes.{not} as not_; pragma no-patterson-condition ABIEncode, Num; @@ -1906,39 +1906,34 @@ function storeBytesFromMemory(slot: word, src: word) -> () { // shamelessly stolen from abi_encode_t_string_storage_to_t_string_memory_ptr function loadBytesFromStorage(slot:word, memPtr:word) -> word { - let ret : word; - assembly { - let pos := memPtr - let slotValue := sload(slot) - let length := div(slotValue, 2) - let outOfPlaceEncoding := and(slotValue, 1) - if iszero(outOfPlaceEncoding) { - length := and(length, 0x7f) - } - mstore(pos, length) - pos := add(pos, 0x20) - - switch outOfPlaceEncoding - case 0 { - // short byte array - mstore(pos, and(slotValue, not(0xff))) - let empty := iszero(length) - let notzero := iszero(empty) - ret := add(pos, mul(0x20, notzero)) - } - case 1 { - // long byte array - mstore(0, slot) - let dataPos := keccak256(0, 32) - let i := 0 - for { } lt(i, length) { i := add(i, 0x20) } { - mstore(add(pos, i), sload(dataPos)) - dataPos := add(dataPos, 1) - } - ret := add(pos, i) + let pos = memPtr; + let slotValue = sload(slot); + let length = slotValue / 2; + let outOfPlaceEncoding = and_(slotValue, 1); + if (iszero(outOfPlaceEncoding) == 1) { + length = and_(length, 0x7f); + } + mstore(pos, length); + pos = pos + 32; + match outOfPlaceEncoding { + | 0 => + // Short byte array + mstore(pos, and_(slotValue, not_(0xff))); + let empty = iszero(length); + let notzero = iszero(empty); + return pos + (notzero * 32); + | 1 => + // Long byte array + mstore(0, slot); + let dataPos = keccak256(0, 32); + let i = 0; + for (let x_; i < length; i = i + 32) { + mstore(pos + i, sload(dataPos)); + dataPos = dataPos + 1; + } + return pos + i; + | _ => return 0; // unreachable } - } - return ret; } From 0b0fb794f0f739977b77c0a25639bf116aff0d37 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 22 May 2026 18:10:52 +0200 Subject: [PATCH 09/32] Simplify loadBytesFromStorage --- std/std.solc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/std/std.solc b/std/std.solc index 5db442698..e368fd772 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1909,30 +1909,28 @@ function loadBytesFromStorage(slot:word, memPtr:word) -> word { let pos = memPtr; let slotValue = sload(slot); let length = slotValue / 2; - let outOfPlaceEncoding = and_(slotValue, 1); - if (iszero(outOfPlaceEncoding) == 1) { + let outOfPlaceEncoding = tobool(and_(slotValue, 1)); + if (!outOfPlaceEncoding) { length = and_(length, 0x7f); } mstore(pos, length); pos = pos + 32; match outOfPlaceEncoding { - | 0 => + | false => // Short byte array mstore(pos, and_(slotValue, not_(0xff))); let empty = iszero(length); let notzero = iszero(empty); return pos + (notzero * 32); - | 1 => + | true => // Long byte array - mstore(0, slot); - let dataPos = keccak256(0, 32); + let dataPos = hash1(slot); let i = 0; - for (let x_; i < length; i = i + 32) { + for (let x; i < length; i = i + 32) { mstore(pos + i, sload(dataPos)); dataPos = dataPos + 1; } return pos + i; - | _ => return 0; // unreachable } } From 6e225ec09758fd85eb5a0e34d4d7b12e5129316a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 May 2026 17:39:28 +0200 Subject: [PATCH 10/32] Simplify dispatch --- std/dispatch.solc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index a43bd9b02..849bd63b6 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -156,9 +156,7 @@ forall args rets fn , rets:ABIEncode => function do_exec(pargs : Proxy(args), prets : Proxy(rets), fn : fn) -> () { // check we have enough calldata for the head of args - let hdsz = ABIAttribs.headSize(pargs); - let cdsz = calldatasize(); - if ((cdsz - 4) < hdsz) { + if ((calldatasize() - 4) < ABIAttribs.headSize(pargs)) { let ABIInputTruncated = Error(0x08638556); revertWithError(ABIInputTruncated); } @@ -251,8 +249,7 @@ instance Payable:MethodLevelCallvalueCheck { // NonPayable methods revert if passed value instance NonPayable:MethodLevelCallvalueCheck { function checkCallvalue(prx : Proxy(NonPayable)) -> () { - let value = callvalue(); - if (value > 0) { + if (callvalue() > 0) { let NonPayableReceivedValue = Error(0xb5988ea3); revertWithError(NonPayableReceivedValue); } From ba6baec1fd126c2656f878a72668cfb3a56ed427 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 May 2026 17:41:57 +0200 Subject: [PATCH 11/32] Use require in dispatch --- std/dispatch.solc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index 849bd63b6..88765b34e 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -248,11 +248,9 @@ instance Payable:MethodLevelCallvalueCheck { } // NonPayable methods revert if passed value instance NonPayable:MethodLevelCallvalueCheck { - function checkCallvalue(prx : Proxy(NonPayable)) -> () { - if (callvalue() > 0) { - let NonPayableReceivedValue = Error(0xb5988ea3); - revertWithError(NonPayableReceivedValue); - } + function checkCallvalue(prx : Proxy(NonPayable)) -> () { + let NonPayableReceivedValue = Error(0xb5988ea3); + require(callvalue() == 0, NonPayableReceivedValue); } } From 622b0a31fbd68fe7f25a632bce1f4398d106e32a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 May 2026 21:37:45 +0200 Subject: [PATCH 12/32] Avoid reexporting --- std/std.solc | 2 -- test/examples/dispatch/stringid.solc | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/std/std.solc b/std/std.solc index e368fd772..4548dce43 100644 --- a/std/std.solc +++ b/std/std.solc @@ -88,8 +88,6 @@ export { memberAccessBase, memory(*), memory_ref, - // mload, // Re-exporting does not work yet -// mstore, ne, not, or, diff --git a/test/examples/dispatch/stringid.solc b/test/examples/dispatch/stringid.solc index a75b4cae5..9babf4562 100644 --- a/test/examples/dispatch/stringid.solc +++ b/test/examples/dispatch/stringid.solc @@ -1,5 +1,6 @@ import std.{*}; -import std.{memory, string, Typedef, log1, allocate_memory, mstore, uint256}; +import std.{memory, string, Typedef, log1, allocate_memory, uint256}; +import std.opcodes.{mstore}; import std.dispatch.{*}; pragma no-patterson-condition ; pragma no-coverage-condition ; From 5013d60009134f7992164ec808f968663191aadc Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 27 May 2026 22:09:46 +0200 Subject: [PATCH 13/32] Use more opcodes helpers in std --- std/std.solc | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/std/std.solc b/std/std.solc index 4548dce43..7816d33db 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,4 +1,4 @@ -import std.opcodes.{add, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256}; +import std.opcodes.{add, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, log1 as log1_, invalid}; //import std.opcodes.{not} as not_; pragma no-patterson-condition ABIEncode, Num; @@ -163,10 +163,8 @@ export { forall t.t:Typedef(word) => function log1(v:t, topic:word) -> () { let w : word = Typedef.rep(v); - assembly { - mstore(0,w) - log1(0,32,topic) - } + mstore(0, w); + log1_(0, 32, topic); } function unimplemented() -> () { @@ -220,9 +218,7 @@ function revertWithError(e:Error) -> () { function assert(cond: bool) -> () { if (!cond) { - assembly { - invalid() - } + invalid(); } } @@ -583,22 +579,14 @@ instance word:Bounded { } function hash1(x: word) -> word { - let result: word = 0; - assembly { - mstore(0, x) - result := keccak256(0,32) - } - return result; + mstore(0, x); + return keccak256(0, 32); } function hash2(x: word, y: word) -> word { - let result: word = 0; - assembly { - mstore(0, x) - mstore(32, y) - result := keccak256(0,64) - } - return result; + mstore(0, x); + mstore(32, y); + return keccak256(0, 64); } // --- Value Types --- From 107920ef94897640fb6b69a8028f7d3fc73c7989 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 30 May 2026 13:15:04 +0200 Subject: [PATCH 14/32] import not_ --- std/std.solc | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/std/std.solc b/std/std.solc index 7816d33db..cc4ebe84f 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,5 +1,5 @@ -import std.opcodes.{add, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, log1 as log1_, invalid}; -//import std.opcodes.{not} as not_; + +import std.opcodes.{add, not as not_, and as and_, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, log1 as log1_, invalid}; pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; @@ -1227,23 +1227,6 @@ instance bool:ABIEncode { } } -// TODO: support import renaming -function and_(a: word, b: word) -> word { - let res; - assembly { - res := and(a, b) - } - return res; -} - -function not_(a: word) -> word { - let res; - assembly { - res := not(a) - } - return res; -} - function round_up_to_mul_of_32(value:word) -> word { return and_(value + 31, not_(31)); } From f80b5f474daaf89e4a3b321a5c279fa018c67f8b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 1 Jun 2026 20:09:53 +0200 Subject: [PATCH 15/32] Fix imports in tests --- test/examples/dispatch/stringid.solc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/examples/dispatch/stringid.solc b/test/examples/dispatch/stringid.solc index 9babf4562..2bdfe63cf 100644 --- a/test/examples/dispatch/stringid.solc +++ b/test/examples/dispatch/stringid.solc @@ -1,6 +1,6 @@ import std.{*}; import std.{memory, string, Typedef, log1, allocate_memory, uint256}; -import std.opcodes.{mstore}; +import std.opcodes.{mstore, not as not_}; import std.dispatch.{*}; pragma no-patterson-condition ; pragma no-coverage-condition ; From f1591412db4d6a300aeae92f00e3035215d3b910 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 8 Jun 2026 18:29:01 +0200 Subject: [PATCH 16/32] Fix hashes.solc --- test/examples/dispatch/hashes.solc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/examples/dispatch/hashes.solc b/test/examples/dispatch/hashes.solc index 453ae2279..b6b149027 100644 --- a/test/examples/dispatch/hashes.solc +++ b/test/examples/dispatch/hashes.solc @@ -1,5 +1,6 @@ import std.{*}; import std.dispatch.{*}; +import std.opcodes.{mstore}; // Build a memory(bytes) holding the three-byte string "abc". function abcBytes() -> memory(bytes) { From e28ba1ca11e286415aaf42a74a6357706b465e3f Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 9 Jun 2026 22:09:54 +0200 Subject: [PATCH 17/32] Rewrite more --- std/std.solc | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/std/std.solc b/std/std.solc index cc4ebe84f..2cd3755a6 100644 --- a/std/std.solc +++ b/std/std.solc @@ -400,11 +400,7 @@ default instance a:Num { // These are intended to be folded by MastEval when their arguments are // statically known word values. function eqWord(x:word, y:word) -> bool { - let res : word; - assembly { - res := eq(x, y) - } - return tobool(res); + return tobool(eq(x, y)); } function gtWord(x:word, y:word) -> bool { @@ -2027,10 +2023,7 @@ instance memory(bytes):MemoryPointer { instance memory(bytes):MemoryEncode { function encodeInto(v: memory(bytes), target: word) -> () { let v_ = Typedef.rep(v); - assembly { - mcopy(target, add(v_, 32), mload(v_)) - } - } + mcopy(target, v_ + 32, mload(v_)); } // Placeholder for an empty memory area. @@ -2109,11 +2102,7 @@ function truncate(input: a, end: word) -> memory_ref { forall a . a:MemorySize, a:MemoryPointer => function keccak256_(input: a) -> bytes32 { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); - let res : word; - assembly { - res := keccak256(ptr, len) - } - return bytes32(res); + return bytes32(keccak256(ptr, len)); } forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 { From af0a11aec49b061943fafcf801de8bc13bfb0f42 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 9 Jun 2026 22:11:08 +0200 Subject: [PATCH 18/32] Rwrite revert --- std/std.solc | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/std/std.solc b/std/std.solc index 2cd3755a6..9fcbfda3c 100644 --- a/std/std.solc +++ b/std/std.solc @@ -188,9 +188,7 @@ function revertLit(s:string) -> () { // Empty revert. function revertEmpty() -> () { - assembly { - revert(0, 0) - } + revert(0, 0); } // TODO: use bytes4 @@ -200,19 +198,15 @@ data Error = Error(word) | Empty | Msg(memory(string)); // Revert with Error selector. function revertWithError(e:Error) -> () { match e { - | .Error(selector) => assembly { - mstore(0, selector) + | .Error(selector) => + mstore(0, selector); // We only care about the BE MSB. - revert(28, 4) - } - | .Empty => assembly { - revert(0, 0) - } + revert(28, 4); + | .Empty => + revert(0, 0); | .Msg(msg) => let msg_ = Typedef.rep(msg); - assembly { - revert(add(msg_, 32), mload(msg_)) - } + revert(msg_ + 32, mload(msg_)); } } From 0dac70da71211678ec068b99cb1159293330d61b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 9 Jun 2026 22:13:52 +0200 Subject: [PATCH 19/32] Rewrite sha256 --- std/std.solc | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/std/std.solc b/std/std.solc index 9fcbfda3c..bd7b6c610 100644 --- a/std/std.solc +++ b/std/std.solc @@ -2104,15 +2104,9 @@ forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 let ptr : word = MemoryPointer.ptr(input); let res : word; // We assume the [0, 32] scratch space is reserved. - // TODO: add specific error code - assembly { - let ret := staticcall(gas(), 2, ptr, len, 0, 32) - if iszero(ret) { - revert(0, 0) - } - res := mload(0) - } - return bytes32(res); + let ret = staticcall(gas(), 2, ptr, len, 0, 32); + require(ret != 0, Error(0x12345678)); // SHA256CallFailed() + return bytes32(mload(0)); } forall a . a:MemorySize, a:MemoryPointer => function ripemd160(input: a) -> bytes32 { From 14e952c8d7f0768de2abfd1b0c8e0d219e49dd77 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 9 Jun 2026 22:16:59 +0200 Subject: [PATCH 20/32] Use require in deposit --- std/dispatch.solc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index 88765b34e..23d6d0a2b 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -156,10 +156,7 @@ forall args rets fn , rets:ABIEncode => function do_exec(pargs : Proxy(args), prets : Proxy(rets), fn : fn) -> () { // check we have enough calldata for the head of args - if ((calldatasize() - 4) < ABIAttribs.headSize(pargs)) { - let ABIInputTruncated = Error(0x08638556); - revertWithError(ABIInputTruncated); - } + require(calldatasize() >= (ABIAttribs.headSize(pargs) + 4), Error(0x08638556)); // ABIInputTruncated() // TODO: calldatasize checks for dynamic types From 5bd3577c4bff48bd3181e4488c832f062602cd9b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 13:59:32 +0200 Subject: [PATCH 21/32] f --- test/examples/dispatch/hashes.solc | 1 - test/examples/dispatch/stringid.solc | 1 - 2 files changed, 2 deletions(-) diff --git a/test/examples/dispatch/hashes.solc b/test/examples/dispatch/hashes.solc index b6b149027..453ae2279 100644 --- a/test/examples/dispatch/hashes.solc +++ b/test/examples/dispatch/hashes.solc @@ -1,6 +1,5 @@ import std.{*}; import std.dispatch.{*}; -import std.opcodes.{mstore}; // Build a memory(bytes) holding the three-byte string "abc". function abcBytes() -> memory(bytes) { diff --git a/test/examples/dispatch/stringid.solc b/test/examples/dispatch/stringid.solc index 2bdfe63cf..da46d9ff3 100644 --- a/test/examples/dispatch/stringid.solc +++ b/test/examples/dispatch/stringid.solc @@ -1,6 +1,5 @@ import std.{*}; import std.{memory, string, Typedef, log1, allocate_memory, uint256}; -import std.opcodes.{mstore, not as not_}; import std.dispatch.{*}; pragma no-patterson-condition ; pragma no-coverage-condition ; From 7fbedf33a9de1cbe8bd4bcfccebb01b0247c3417 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 14:03:29 +0200 Subject: [PATCH 22/32] f --- std/std.solc | 1 + 1 file changed, 1 insertion(+) diff --git a/std/std.solc b/std/std.solc index bd7b6c610..081be622a 100644 --- a/std/std.solc +++ b/std/std.solc @@ -2018,6 +2018,7 @@ instance memory(bytes):MemoryEncode { function encodeInto(v: memory(bytes), target: word) -> () { let v_ = Typedef.rep(v); mcopy(target, v_ + 32, mload(v_)); + } } // Placeholder for an empty memory area. From 3b8dc3556825bf5c8c760ce42992684b7dfdb741 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 14:04:59 +0200 Subject: [PATCH 23/32] Revert import --- std/std.solc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/std/std.solc b/std/std.solc index 081be622a..0609cff5f 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,5 +1,5 @@ -import std.opcodes.{add, not as not_, and as and_, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, log1 as log1_, invalid}; +import std.opcodes.{add, not as not_, and as and_, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, log1 as log1_, revert as revert_, invalid}; pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; @@ -188,7 +188,7 @@ function revertLit(s:string) -> () { // Empty revert. function revertEmpty() -> () { - revert(0, 0); + revert_(0, 0); } // TODO: use bytes4 @@ -201,12 +201,12 @@ function revertWithError(e:Error) -> () { | .Error(selector) => mstore(0, selector); // We only care about the BE MSB. - revert(28, 4); + revert_(28, 4); | .Empty => - revert(0, 0); + revert_(0, 0); | .Msg(msg) => let msg_ = Typedef.rep(msg); - revert(msg_ + 32, mload(msg_)); + revert_(msg_ + 32, mload(msg_)); } } From 8c96fd12ec5155f2d5df693d19759da8fa65df2b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 14:05:09 +0200 Subject: [PATCH 24/32] Import opcodes --- std/std.solc | 2 +- test/examples/dispatch/hashes.solc | 1 + test/examples/dispatch/memory.solc | 1 + test/examples/dispatch/stringid.solc | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/std/std.solc b/std/std.solc index 0609cff5f..d46b39fd4 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,5 +1,5 @@ -import std.opcodes.{add, not as not_, and as and_, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, log1 as log1_, revert as revert_, invalid}; +import std.opcodes.{add, not as not_, and as and_, eq, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, gas, log1 as log1_, staticcall, revert as revert_, invalid}; pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; diff --git a/test/examples/dispatch/hashes.solc b/test/examples/dispatch/hashes.solc index 453ae2279..b6b149027 100644 --- a/test/examples/dispatch/hashes.solc +++ b/test/examples/dispatch/hashes.solc @@ -1,5 +1,6 @@ import std.{*}; import std.dispatch.{*}; +import std.opcodes.{mstore}; // Build a memory(bytes) holding the three-byte string "abc". function abcBytes() -> memory(bytes) { diff --git a/test/examples/dispatch/memory.solc b/test/examples/dispatch/memory.solc index 7c17bccb7..eec43817b 100644 --- a/test/examples/dispatch/memory.solc +++ b/test/examples/dispatch/memory.solc @@ -1,5 +1,6 @@ import std.{*}; import std.dispatch.{*}; +import std.opcodes.{mstore}; contract C { public function dirty_allocate() -> memory(bytes) { diff --git a/test/examples/dispatch/stringid.solc b/test/examples/dispatch/stringid.solc index da46d9ff3..ac7423530 100644 --- a/test/examples/dispatch/stringid.solc +++ b/test/examples/dispatch/stringid.solc @@ -1,6 +1,7 @@ import std.{*}; import std.{memory, string, Typedef, log1, allocate_memory, uint256}; import std.dispatch.{*}; +import std.opcodes.{mstore}; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; From e038981c12372d76a5787db0160e7231df6bc801 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 14:33:05 +0200 Subject: [PATCH 25/32] update expectation --- std/std.solc | 3 +-- test/examples/dispatch/basic.json | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/std/std.solc b/std/std.solc index d46b39fd4..a4809e8e5 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1885,7 +1885,7 @@ function loadBytesFromStorage(slot:word, memPtr:word) -> word { // Long byte array let dataPos = hash1(slot); let i = 0; - for (let x; i < length; i = i + 32) { + for (; i < length; i = i + 32) { mstore(pos + i, sload(dataPos)); dataPos = dataPos + 1; } @@ -2103,7 +2103,6 @@ forall a . a:MemorySize, a:MemoryPointer => function keccak256_(input: a) -> byt forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); - let res : word; // We assume the [0, 32] scratch space is reserved. let ret = staticcall(gas(), 2, ptr, len, 0, 32); require(ret != 0, Error(0x12345678)); // SHA256CallFailed() diff --git a/test/examples/dispatch/basic.json b/test/examples/dispatch/basic.json index 3e60ff041..f01db96ef 100644 --- a/test/examples/dispatch/basic.json +++ b/test/examples/dispatch/basic.json @@ -138,7 +138,7 @@ }, "kind": "call", "output": { - "returndata":"4924aef0", + "returndata":"08638556", "status": "failure" } }, @@ -150,7 +150,7 @@ }, "kind": "call", "output": { - "returndata":"4924aef0", + "returndata":"08638556", "status": "failure" } }, From 2141d157dd76e2fb76e17298c704dd29f0fcca8c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:08:35 +0200 Subject: [PATCH 26/32] more assembly --- std/std.solc | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/std/std.solc b/std/std.solc index a4809e8e5..3dd98efca 100644 --- a/std/std.solc +++ b/std/std.solc @@ -398,11 +398,7 @@ function eqWord(x:word, y:word) -> bool { } function gtWord(x:word, y:word) -> bool { - let res : word; - assembly { - res := gt(x, y) - } - return tobool(res); + return tobool(gt(x, y)); } function addWord(l: word, r: word) -> word { @@ -410,29 +406,17 @@ function addWord(l: word, r: word) -> word { } function subWord(l: word, r: word) -> word { - let rw : word; - assembly { - rw := sub(l,r) - } - return rw; + return sub(l, r); } // Bitwise AND function bandWord(x: word, y: word) -> word { - let res: word; - assembly { - res := and(x, y) - } - return res; + return and_(x, y); } // Bitwise OR function borWord(x: word, y: word) -> word { - let res: word; - assembly { - res := or(x, y) - } - return res; + return or_(x, y); } // Bitwise XOR @@ -2069,7 +2053,7 @@ instance memory_ref:MemoryPointer { instance memory_ref:MemoryEncode { function encodeInto(v: memory_ref, target: word) -> () { match v { - | memory_ref(ptr, len) => assembly { mcopy(target, ptr, len) } + | memory_ref(ptr, len) => mcopy(target, ptr, len); } } } From 40aef43d5cfd829a2562aa1494781618fd97fb31 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:12:01 +0200 Subject: [PATCH 27/32] f --- std/std.solc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/std/std.solc b/std/std.solc index 3dd98efca..54f4cea3a 100644 --- a/std/std.solc +++ b/std/std.solc @@ -421,11 +421,7 @@ function borWord(x: word, y: word) -> word { // Bitwise XOR function bxorWord(x: word, y: word) -> word { - let res: word; - assembly { - res := xor(x, y) - } - return res; + return xor_(x, y); } // Bitwise NOT From afe879795466f5a6027f2595e07707abee209baf Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:21:10 +0200 Subject: [PATCH 28/32] Repalcem ore assembly --- std/std.solc | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/std/std.solc b/std/std.solc index 54f4cea3a..a7e37d160 100644 --- a/std/std.solc +++ b/std/std.solc @@ -426,29 +426,17 @@ function bxorWord(x: word, y: word) -> word { // Bitwise NOT function bnotWord(x: word) -> word { - let res: word; - assembly { - res := not(x) - } - return res; + return not_(x); } // Bitwise SHL function bshlWord(x: word, y: word) -> word { - let res: word; - assembly { - res := shl(x, y) - } - return res; + return shl(x, y); } // Bitwise SHR function bshrWord(x: word, y: word) -> word { - let res: word; - assembly { - res := shr(x, y) - } - return res; + return shr(x, y); } instance word:Eq { @@ -476,11 +464,7 @@ instance word:Sub { } function mulWord(l: word, r: word) -> word { - let rw : word; - assembly { - rw := mul(l,r) - } - return rw; + return mul(l, r); } instance word:Mul { @@ -491,21 +475,13 @@ instance word:Mul { instance word:Div { function div(l: word, r: word) -> word { - let rw : word; - assembly { - rw := div(l,r) - } - return rw; + return div(l, r); } } instance word : Mod { function mod (l : word, r : word) -> word { - let res : word; - assembly { - res := mod(l,r) - } - return res; + return mod(l, r); } } From 557af7a894f40b58689916d68b5dff56c56af735 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:21:51 +0200 Subject: [PATCH 29/32] Replace ripem160 --- std/std.solc | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/std/std.solc b/std/std.solc index a7e37d160..f625eb103 100644 --- a/std/std.solc +++ b/std/std.solc @@ -2070,15 +2070,9 @@ forall a . a:MemorySize, a:MemoryPointer => function ripemd160(input: a) -> byte let ptr : word = MemoryPointer.ptr(input); let res : word; // We assume the [0, 32] scratch space is reserved. - // TODO: add specific error code - assembly { - let ret := staticcall(gas(), 3, ptr, len, 0, 32) - if iszero(ret) { - revert(0, 0) - } - res := mload(0) - } - return bytes32(res); + let ret = staticcall(gas(), 3, ptr, len, 0, 32); + require(ret != 0, Error(0x12345678)); // RIPEMD160CallFailed() + return bytes32(mload(0)); } // --- Precompiles --- From 819b75a4124483ee5efe4540c72758a171147c4a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:24:08 +0200 Subject: [PATCH 30/32] Rewrite ECRecover without assembly (and add Errors) --- std/std.solc | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/std/std.solc b/std/std.solc index f625eb103..e32b8001d 100644 --- a/std/std.solc +++ b/std/std.solc @@ -2094,23 +2094,14 @@ function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) -> address let r_ = Typedef.rep(r); let s_ = Typedef.rep(s); let ptr = get_free_memory(); - let res: word; // We assume the [0, 32] scratch space is reserved. - // TODO: add specific error code - assembly { - mstore(ptr, hash_) - mstore(add(ptr, 32), v_) - mstore(add(ptr, 64), r_) - mstore(add(ptr, 96), s_) - - let ret := staticcall(gas(), 1, ptr, 128, 0, 32) - if iszero(ret) { - revert(0, 0) - } - res := mload(0) - if iszero(res) { - revert(0, 0) - } - } + mstore(ptr, hash_); + mstore(add(ptr, 32), v_); + mstore(add(ptr, 64), r_); + mstore(add(ptr, 96), s_); + let ret = staticcall(gas(), 1, ptr, 128, 0, 32); + require(ret != 0, Error(0x12345678)); // ECRecoverCallFailed() + let res = mload(0); + require(res != 0, Error(0x12345678)); // ECRecoverFailed() return address(res); } From e8049d6244abe0840f80e15c1d77c7c0922c80b5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:25:44 +0200 Subject: [PATCH 31/32] Rewrite zeroize_memory without assembly --- std/std.solc | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/std/std.solc b/std/std.solc index e32b8001d..25c6f4b60 100644 --- a/std/std.solc +++ b/std/std.solc @@ -771,19 +771,16 @@ function allocate_zeroed_memory(size: word) -> word { // Clears a memory area. function zeroize_memory(ptr: word, len: word) -> () { - assembly { - let end_ptr := add(ptr, len) - - // Zero out 32-byte words. - let words := div(len, 32) - for { let i := 0 } lt(i, words) { i := add(i, 1) } { - mstore(ptr, 0) - ptr := add(ptr, 32) - } + let end_ptr = ptr + len; - // Zero out trailing bytes. We rely on the zero-slot (0x60-0x7f). - mcopy(ptr, 0x60, sub(end_ptr, ptr)) + // Zero out 32-byte words. + for (let i = 0; i < len / 32; i += 1) { + mstore(ptr, 0) + ptr += 32; } + + // Zero out trailing bytes. We rely on the zero-slot (0x60-0x7f). + mcopy(ptr, 0x60, end_ptr - ptr); } // --- Indexable Types --- From 2bfcf80889d48bc41c70ffeb99f4f25ca142e603 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 16 Jun 2026 15:30:50 +0200 Subject: [PATCH 32/32] f --- std/std.solc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/std.solc b/std/std.solc index 25c6f4b60..ebb209fa1 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1,5 +1,5 @@ -import std.opcodes.{add, not as not_, and as and_, eq, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, gas, log1 as log1_, staticcall, revert as revert_, invalid}; +import std.opcodes.{add, div, mul, sub, mod, or as or_, xor as xor_, not as not_, and as and_, eq, gt as gt_, shl, shr, mstore, mload, mcopy, sstore, sload, calldataload, calldatacopy, iszero, keccak256, gas, log1 as log1_, staticcall, revert as revert_, invalid}; pragma no-patterson-condition ABIEncode, Num; pragma no-coverage-condition ABIDecode, MemoryType; @@ -398,7 +398,7 @@ function eqWord(x:word, y:word) -> bool { } function gtWord(x:word, y:word) -> bool { - return tobool(gt(x, y)); + return tobool(gt_(x, y)); } function addWord(l: word, r: word) -> word {