From ee022db90fa5234f9c94bf314e8c5477fba11c56 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Tue, 21 Oct 2025 08:15:11 +0200 Subject: [PATCH 01/11] Fix parsing and pretty-printing of Yul for statements --- src/Language/Yul.hs | 7 +++---- src/Language/Yul/Parser.hs | 1 + test/Cases.hs | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Language/Yul.hs b/src/Language/Yul.hs index 42e186cb..dca82d61 100644 --- a/src/Language/Yul.hs +++ b/src/Language/Yul.hs @@ -89,7 +89,7 @@ hlist, vlist, nvlist, pprBlock :: Pretty a => [a] -> Doc hlist = hsep . map ppr vlist = vcat . map ppr nvlist = nest 2 . vlist -pprBlock stmts = lbrace $$ nvlist stmts $$ rbrace +pprBlock stmts = braces(nvlist stmts) instance Pretty YulObject where @@ -133,9 +133,8 @@ instance Pretty YulStmt where $$ maybe empty (\stmts -> text "default" <+> pprBlock stmts) def where pprCase (lit, stmts) = text "case" <+> ppr lit <+> pprBlock stmts ppr (YFor pre cond post stmts) = - text "for" <+> braces (hlist pre) - <+> ppr cond - <+> hlist post <+> pprBlock stmts + text "for" <+> braces (hlist pre) <+> ppr cond <+> braces (hlist post) + $$ pprBlock stmts ppr YBreak = text "break" ppr YContinue = text "continue" ppr YLeave = text "leave" diff --git a/src/Language/Yul/Parser.hs b/src/Language/Yul/Parser.hs index 66b1c4d9..dfa268a6 100644 --- a/src/Language/Yul/Parser.hs +++ b/src/Language/Yul/Parser.hs @@ -71,6 +71,7 @@ yulStmt = choice , yulFun , YLet <$> (pKeyword "let" *> commaSep pName) <*> optional (symbol ":=" *> yulExpression) , YIf <$> (pKeyword "if" *> yulExpression) <*> yulBlock + , YFor <$> (pKeyword "for" *> yulBlock) <*> yulExpression <*> yulBlock <*> yulBlock , YSwitch <$> (pKeyword "switch" *> yulExpression) <*> many yulCase <*> diff --git a/test/Cases.hs b/test/Cases.hs index 775f0a2a..9d1067d2 100644 --- a/test/Cases.hs +++ b/test/Cases.hs @@ -187,6 +187,7 @@ cases = , runTestExpectingFailure "overlapping-heads.solc" caseFolder , runTestExpectingFailure "instance-wrong-sig.solc" caseFolder , runTestForFile "match-yul.solc" caseFolder + , runTestForFile "yul-for.solc" caseFolder ] where caseFolder = "./test/examples/cases" From 7c3be1f1e1c01e2a152c858f0453b47d904ecbe2 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 24 Oct 2025 08:07:40 +0200 Subject: [PATCH 02/11] add missing yul-for testcase --- test/examples/cases/yul-for.solc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/examples/cases/yul-for.solc diff --git a/test/examples/cases/yul-for.solc b/test/examples/cases/yul-for.solc new file mode 100644 index 00000000..f978b196 --- /dev/null +++ b/test/examples/cases/yul-for.solc @@ -0,0 +1,14 @@ +contract YulFor { + function main() { + let loopStart = 128; + let loopEnd = 256; + let res : word; + assembly { + let i := loopStart + for {} lt(i, loopEnd) { i := add(i, 32) } + { mstore(i, 42) } + res := mload(192) + } + return res; + } +} From a3abbdee887343ef9c0d505ef926c3679fbe631d Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 31 Oct 2025 13:30:21 +0100 Subject: [PATCH 03/11] Primitives: fix type of calldatacopy --- src/Solcore/Primitives/Primitives.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Solcore/Primitives/Primitives.hs b/src/Solcore/Primitives/Primitives.hs index a00f5229..cef706da 100644 --- a/src/Solcore/Primitives/Primitives.hs +++ b/src/Solcore/Primitives/Primitives.hs @@ -213,7 +213,7 @@ yulPrimOps = [ (Name "stop", monotype unit) , (Name "callvalue", monotype word) , (Name "calldataload", monotype (word :-> word)) , (Name "calldatasize", monotype word) - , (Name "calldatacopy", monotype (word :-> word :-> word :-> word)) + , (Name "calldatacopy", monotype (word :-> word :-> word :-> unit)) , (Name "codesize", monotype word) , (Name "codecopy", monotype (word :-> word :-> word :-> unit)) , (Name "datasize", monotype (string :-> word)) From a91f963c1a022f28a491298cf4a597047e7395c7 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 31 Oct 2025 13:53:34 +0100 Subject: [PATCH 04/11] std: ABI en/decoding for strings --- std/dispatch.solc | 21 ++++++-- std/std.solc | 127 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 133 insertions(+), 15 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index b1454fec..78eac881 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -38,6 +38,17 @@ instance ():ABIString { } } +instance memory(string):ABIString { + function append(head : word, tail : word, prx : Proxy(memory(string))) -> word { + let size : word = 6; + assembly { + mstore(head, add(mload(head), size)) + mstore(tail, 0x737472696e670000000000000000000000000000000000000000000000000000) + } + return Add.add(tail, size); + } +} + function append_left_bracket(head : word, tail : word) -> word { let size = 1; assembly { @@ -183,12 +194,14 @@ forall payability args rets fn // abi encode rets to memory let ptr = abi_encode(rets); - // TODO: this is broken for dynamically sized types... - let retSz : word = ABIAttribs.headSize(prets); + // let retSz : word = ABIAttribs.headSize(prets); + // the approach above does not work for dynamically sized types... + // ...instead we take the size of memory allocated by the encoding let start : word = Typedef.rep(ptr); - + let end : word = get_free_memory(); + let retSz : word = Sub.sub(end, start); assembly { - return(start,retSz) + return(start, retSz) } } diff --git a/std/std.solc b/std/std.solc index 1640fad4..f9bc1e53 100644 --- a/std/std.solc +++ b/std/std.solc @@ -36,6 +36,16 @@ pragma no-coverage-condition ABIDecode, MemoryType; - memory vectors */ +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) + } +} + + // --- booleans --- // TODO: this should short circuit. probably needs some compiler magic to do so. @@ -101,6 +111,12 @@ forall abs rep . class abs:Typedef(rep) { function rep(x:abs) -> rep; } +forall t. +default instance t:Typedef(t) { + function abs(x:t) -> t { return x; } + function rep(x:t) -> t { return x; } +} + // --- Equality --- forall a. class a:Eq { @@ -149,6 +165,7 @@ function lt(x:a, y:a) -> bool { return gt(y,x); } + // --- Arithmetic --- forall t . class t:Add { @@ -423,6 +440,23 @@ forall t . instance returndata(t) : Typedef(word) { 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); } +} + + // --- Free Memory Pointer --- // Memory in solidity is bump allocated in a single arena @@ -534,6 +568,8 @@ forall ty . class ty:WordReader { function read(reader:ty) -> word; // returns a new WordReader that points to a location `offset` bytes further into the array function advance(reader:ty, offset:word) -> ty; + // copies a block from the underlying source to memory + function copyToMem(reader:ty, dst: word, cnt: word) -> (); } // WordReader for memory @@ -551,6 +587,11 @@ instance MemoryWordReader:WordReader { | MemoryWordReader(ptr) => return MemoryWordReader(Add.add(ptr, offset)); } } + function copyToMem(reader:MemoryWordReader, dst:word, cnt: word) -> () { + match reader { + | MemoryWordReader(ptr) => assembly { mcopy(dst, ptr, cnt) } + } + } } // WordReader for calldata @@ -581,6 +622,11 @@ instance CalldataWordReader:WordReader { | CalldataWordReader(ptr) => return CalldataWordReader(Add.add(ptr, offset)); } } + function copyToMem(reader:CalldataWordReader, dst:word, cnt: word) -> () { + match reader { + | CalldataWordReader(ptr) => assembly { calldatacopy(dst, ptr, cnt) } + } + } } // --- HasWordReader --- @@ -623,6 +669,7 @@ instance uint256:MemoryType(uint256) { } // We load a DynArray into a sized pointer to the first element +/* forall ty ret . ty:MemoryType(ret) => instance DynArray(ty):MemoryType(slice(memory(ret))) { function loadFromMemory(p : Proxy (DynArray(ty)), loc:word) -> slice(memory(ret)) { let length; @@ -633,19 +680,20 @@ forall ty ret . ty:MemoryType(ret) => instance DynArray(ty):MemoryType(slice(mem return slice(Typedef.abs(loc) : memory(ret), length); } } - +*/ // FAIL: patterson // FAIL: bound variable // if we ty is a MemoryType that returns deref and deref is ABIEncode, then we can encode a memory(ty) // by loading it and then running the ABI encoding for the loaded value +/* forall ty deref . ty:MemoryType(deref), deref:ABIEncode => instance memory(ty):ABIEncode { function encodeInto(x:memory(ty), basePtr:word, offset:word, tail:word) -> word { let prx : Proxy(ty); // FIXED: before was Proxy(deref) return ABIEncode.encodeInto(MemoryType.loadFromMemory(prx, Typedef.rep(x)) : deref, basePtr, offset, tail); } } - +*/ // --- ABI Tuples --- // Tuples in Solidity are always desugared to nested pairs (to allow for @@ -691,6 +739,10 @@ forall t . instance DynArray(t):ABIAttribs { function headSize(ty : Proxy(DynArray(t))) -> word { return 32; } function isStatic(ty : Proxy(DynArray(t))) -> bool { return false; } } +instance string:ABIAttribs { + function headSize(ty: Proxy(string)) -> word { return 32; } + function isStatic(ty : Proxy(string)) -> bool { return false; } +} // computes the attribs for a pair of two types that implement attribs forall a b . a:ABIAttribs, b:ABIAttribs => instance (a,b):ABIAttribs { @@ -711,14 +763,14 @@ forall a b . a:ABIAttribs, b:ABIAttribs => instance (a,b):ABIAttribs { // if an abi tuple contains dynamic elems we store it in the tail, otherwise we // treat it the same as a series of nested pairs forall tuple . tuple:ABIAttribs => instance ABITuple(tuple):ABIAttribs { - function headSize(ty : Proxy(tuple)) -> word { + function headSize(ty : Proxy(ABITuple(tuple))) -> word { let px : Proxy(tuple); match ABIAttribs.isStatic(px) { | true => return ABIAttribs.headSize(px); | false => return 32; } } - function isStatic(ty : Proxy(tuple)) -> bool { + function isStatic(ty : Proxy(ABITuple(tuple))) -> bool { let px : Proxy(tuple); return ABIAttribs.isStatic(px); } @@ -726,21 +778,21 @@ forall tuple . tuple:ABIAttribs => instance ABITuple(tuple):ABIAttribs { // for pointer types we fetch the attribs of the pointed to type, not the pointer itself forall ty . ty:ABIAttribs => instance memory(ty):ABIAttribs { - function headSize(ty : Proxy(ty)) -> word { + function headSize(p : Proxy(memory(ty))) -> word { let px : Proxy(ty); return ABIAttribs.headSize(px); } - function isStatic(ty : Proxy(ty)) -> bool { + function isStatic(p : Proxy(memory(ty))) -> bool { let px : Proxy(ty); return ABIAttribs.isStatic(px); } } forall ty . ty:ABIAttribs => instance calldata(ty):ABIAttribs { - function headSize(ty : Proxy(ty)) -> word { + function headSize(p : Proxy(calldata(ty))) -> word { let px : Proxy(ty); return ABIAttribs.headSize(px); } - function isStatic(ty : Proxy(ty)) -> bool { + function isStatic(ty : Proxy(calldata(ty))) -> bool { let px : Proxy(ty); return ABIAttribs.isStatic(px); } @@ -775,6 +827,31 @@ instance uint256:ABIEncode { } } +function round_up_to_mul_of_32(value:word) -> word { + let result : word; + assembly { result := and(add(value, 31), not(31)) } + return result; +} + +instance memory(string):ABIEncode { + function encodeInto(x:memory(string), basePtr:word, offset:word, tail:word) -> word { + let tailOffset = Sub.sub(tail,basePtr); + let srcPtr = Typedef.rep(x); + + 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) + } + + return tail; + } +} + instance ():ABIEncode { // a unit256 is written directly into the head function encodeInto(x:(), basePtr:word, offset:word, tail:word) -> word { @@ -850,6 +927,11 @@ forall ty reader . reader:WordReader => instance ABIDecoder(ty, reader):WordRead | ABIDecoder(ptr) => return ABIDecoder(WordReader.advance(ptr, offset)); } } + function copyToMem(decoder:ABIDecoder(ty, reader), dst:word, cnt: word) -> () { + match decoder { + | ABIDecoder(ptr) => WordReader.copyToMem(ptr, dst, cnt); + } + } } // ABI Decoding for uint @@ -865,7 +947,28 @@ forall reader . reader:WordReader => instance ABIDecoder((), reader):ABIDecode(( } } -// ABI decoding for a pait of decodable values +// ABI decoding for strings (only in memory) +forall reader. reader : WordReader => +instance ABIDecoder(memory(string), reader):ABIDecode(memory(string)) +{ + function decode(ptr:ABIDecoder(memory(string), reader), currentHeadOffset:word) -> memory(string) { + let tmp:word; + let headRdr = WordReader.advance(ptr, currentHeadOffset); + let tailPtr : word = WordReader.read(headRdr); + + let src = WordReader.advance(ptr, tailPtr); + let srcRdr = getReader(src); + let length = WordReader.read(src); + let total = Add.add(length, 32); + let rounded = round_up_to_mul_of_32(total); + let resultPtr : word = allocate_memory(rounded) ; + WordReader.copyToMem(srcRdr, resultPtr, total); + return memory(resultPtr); + } // decode ends +} + + +// ABI decoding for a pair of decodable values // FAIL: Coverage forall a b a_decoded b_decoded reader . reader:WordReader, ABIDecoder(b,reader):ABIDecode(b_decoded), ABIDecoder(a,reader):ABIDecode(a_decoded), a:ABIAttribs => instance ABIDecoder((a,b), reader):ABIDecode((a_decoded,b_decoded)) { @@ -896,6 +999,7 @@ forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_dec } } +/* forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_decoded), tuple:ABIAttribs => instance ABIDecoder(memory(ABITuple(tuple)), reader):ABIDecode(memory(tuple_decoded)) { @@ -909,7 +1013,8 @@ forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_dec } } } - +*/ +/* forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReader, ABIDecoder(baseType, reader):ABIDecode(baseType_decoded) => instance ABIDecoder(memory(DynArray(baseType)), reader):ABIDecode(memory(DynArray(baseType_decoded))) { @@ -935,7 +1040,7 @@ forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReade return result; } } - +*/ forall ty reader. function getReader(d:ABIDecoder(ty, reader)) -> reader { match d { From b5d4f90794d9876b17ff9f3028e43a4e0052aa42 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 31 Oct 2025 14:18:09 +0100 Subject: [PATCH 05/11] dispatch: workaround for Issue #252 --- std/dispatch.solc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/std/dispatch.solc b/std/dispatch.solc index 78eac881..2d9e480e 100644 --- a/std/dispatch.solc +++ b/std/dispatch.solc @@ -198,10 +198,11 @@ forall payability args rets fn // the approach above does not work for dynamically sized types... // ...instead we take the size of memory allocated by the encoding let start : word = Typedef.rep(ptr); + let encStart : word = Typedef.rep(ptr); // cannot be called start - see #252 let end : word = get_free_memory(); - let retSz : word = Sub.sub(end, start); + let retSz : word = Sub.sub(end, encStart); assembly { - return(start, retSz) + return(encStart, retSz) } } From 3452f51b54e9308577e236fa6d95f9ed9f37691b Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 31 Oct 2025 15:25:50 +0100 Subject: [PATCH 06/11] std: uncomment some instances that do not overlap after all --- std/std.solc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/std/std.solc b/std/std.solc index 23b1bde3..b28da4fb 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1009,7 +1009,7 @@ forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_dec } } -/* + forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_decoded), tuple:ABIAttribs => instance ABIDecoder(memory(ABITuple(tuple)), reader):ABIDecode(memory(tuple_decoded)) { @@ -1023,8 +1023,7 @@ forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_dec } } } -*/ -/* + forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReader, ABIDecoder(baseType, reader):ABIDecode(baseType_decoded) => instance ABIDecoder(memory(DynArray(baseType)), reader):ABIDecode(memory(DynArray(baseType_decoded))) { @@ -1050,7 +1049,7 @@ forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReade return result; } } -*/ + forall ty reader. function getReader(d:ABIDecoder(ty, reader)) -> reader { match d { From 34585a06d139e98efbb26f88de0aeda01c665686 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 31 Oct 2025 15:26:40 +0100 Subject: [PATCH 07/11] std: remove commented-out code --- std/std.solc | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/std/std.solc b/std/std.solc index b28da4fb..409805db 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1069,46 +1069,6 @@ forall baseType baseType_decoded reader . ABIDecoder(baseType, CalldataWordReade } } -// forall nm args rets f g . nm:Selector, args:ABIDecode, rets:ABIEncode, f:invokable(args, rets) => instance Dispatch(nm,args,rets,f):GenerateDispatch { -// function dispatch_if_selector_match(d:Dispatch(nm,args,rets,f)) -> g { -// return lam() { -// match d { -// | Dispatch(name, args, rets, fn) => match selector_matches(name) { -// | false => return (); -// | true => return (); -// }} -// }; -// } -// } - -//// /// Translation of the above contract -//// struct StorageContext { -//// x:uint; -//// y:bool; -//// } -//// -//// function C_f(ctxt:StorageContext) public { -//// ctxt.x = 42; -//// } -//// -//// -//// function entry_C() { -//// GenerateDispatch.dispatch_if_selector_match(DispatchFunction("f()", C_f)); // could also be (nested) pairs of dispatch functions, if the contract had more functions -//// revert("unknown selector"); -//// } -//// -//// // init code for contract creation -//// function init_C() { -//// // constructor code -//// let code_start := allocate_unbounded() // fetch some free memory -//// let code_length := __builtin_fetch_code(entry_C, code_start) // sounds weirder than it is - this will just add the code for entry_C to a Yul subobject and use some Yul builtins for fetching the code to be deployed -//// assembly { -//// return(code_start, code_length) -//// } -//// } -//// -//// - // --- Assignment --- From 1138f87ee3b21bb34e66fcb0e5aa174c8c268935 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Fri, 31 Oct 2025 15:28:07 +0100 Subject: [PATCH 08/11] tests: add dispatch/stringid --- test/Cases.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Cases.hs b/test/Cases.hs index 775f0a2a..14346aa1 100644 --- a/test/Cases.hs +++ b/test/Cases.hs @@ -61,6 +61,7 @@ dispatches = testGroup "Files for dispatch cases" [ runDispatchTest "basic.solc" + , runDispatchTest "stringid.solc" ] where runDispatchTest file = runTestForFileWith (emptyOption mempty) file "./test/examples/dispatch" From 5af6bcd92dbd095c13fa52d9a1296846e93df7ea Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Sat, 1 Nov 2025 17:17:33 +0100 Subject: [PATCH 09/11] std: fix bug in loadBytesFromStorage --- std/std.solc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/std.solc b/std/std.solc index 409805db..704f8cfb 100644 --- a/std/std.solc +++ b/std/std.solc @@ -1356,7 +1356,7 @@ instance memory(string):Storable(string) { function sload(src:storage(string)) -> memory(string) { let srcPtr : word = Typedef.rep(src); let dstPtr : word = get_free_memory(); - let endPtr = loadBytesFromStorage(srcPtr, srcPtr); + let endPtr = loadBytesFromStorage(srcPtr, dstPtr); set_free_memory(endPtr); return memory(dstPtr); } From 57032fc0ece93c8b616bb5543523874dc73b8e64 Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Tue, 4 Nov 2025 11:01:00 +0100 Subject: [PATCH 10/11] add missing stringid test --- test/examples/dispatch/stringid.solc | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/examples/dispatch/stringid.solc diff --git a/test/examples/dispatch/stringid.solc b/test/examples/dispatch/stringid.solc new file mode 100644 index 00000000..972bcc30 --- /dev/null +++ b/test/examples/dispatch/stringid.solc @@ -0,0 +1,41 @@ +import dispatch; + +contract C { + constructor() {} + function id(x:memory(string)) -> (memory(string)) { + let ptr : word = Typedef.rep(x); + let len : word; + let n1 : word; + assembly { + len := mload(ptr) + n1 := mload(add(ptr,32)) + } + log1(len, 0xc001); + log1(n1, 0xc002); + + return x; + } + + function const_a() -> (memory(string)) { + let resPtr = allocate_memory(64); + let payload = 0x7777777777777777777777777777777777777777777777777777777777777777; + mstore(resPtr, 3); + mstore(resPtr+32, payload); + return memory(resPtr); + } + function mylen(x:memory(string)) -> uint256 { + let ptr : word = Typedef.rep(x); + let l : word; + let n1 : word; + assembly { + l := mload(ptr) + n1 := mload(add(ptr,32)) + } + // log1(l, 0xc001); + // log1(n1, 0xc002); + + return uint256(l); + } + + // function answer() -> uint256 { return uint256(17); } +} From 8e78208f10c41f3de956d151dc23a0c88549873b Mon Sep 17 00:00:00 2001 From: Marcin Benke Date: Tue, 13 Jan 2026 15:45:08 +0100 Subject: [PATCH 11/11] runsol.sh: fix unbound hull variable --- runsol.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runsol.sh b/runsol.sh index 2e710858..d32181c5 100755 --- a/runsol.sh +++ b/runsol.sh @@ -31,7 +31,7 @@ echo "Processing: $file" root_dir="$(cd "$(dirname "$(readlink --canonicalize "${BASH_SOURCE[0]}")")" && pwd)" build_dir="$root_dir/build" base=$(basename "$file" .solc) -core="$build_dir/output1.core" +hull="$build_dir/output1.hull" hexfile="$build_dir/$base.hex" yulfile="$build_dir/$base.yul" runtime_tracefile="$build_dir/trace.runtime.jsonl"