diff --git a/docs/bytecode_analysis/calldata_slice_to_memory.md b/docs/bytecode_analysis/calldata_slice_to_memory.md new file mode 100644 index 0000000..0b83b54 --- /dev/null +++ b/docs/bytecode_analysis/calldata_slice_to_memory.md @@ -0,0 +1,280 @@ +code: +``` +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.23; + +contract ByteCode { + function foo( + bytes calldata encoded, + uint offset, + uint length + ) public payable returns (bytes memory) { unchecked { + return encoded[offset:offset + length]; + }} +} +``` + +compiler: +``` +solc_version = "0.8.23" +optimizer = true +optimizer_runs = 20000 +via_ir = true +``` + +run with eg: +`forge debug --debug src/ByteCode.sol --sig "foo(bytes,uint256,uint256)" "00010203040506" 2 3` + +deployed bytecode assembly + stack trace: +``` +/* \"src/ByteCode.sol\":65:268 contract ByteCode {... */ + 0x80 + 0x04 + calldatasize [0x80, 4, calldatasize] + lt + iszero [0x80, calldataTooShortForSelector] + tag_1 [0x80, calldataTooShortForSelector, tag_1] + jumpi /*revert if calldata too short*/ + 0x00 + dup1 + revert +tag_1: + 0x00 [0x80, 0] + dup1 [0x80, 0, 0] + calldataload [0x80, 0, cd[0:32]] + 0xe0 [0x80, 0, cd[0:32], 0xe0 (=224=256-32)] + shr [0x80, 0, cd[0:4]] + 0xb422824d [0x80, 0, cd[0:4], foo.selector] + eq + tag_3 [0x80, 0, isFooSelector, tag_3] + jumpi /*revert if function selector is not foo*/ + 0x00 + dup1 + revert +tag_3: + calldatasize + 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc /*-4*/ + add /*why not sub 4 instead of add -4?!? we even already know that calldatasize >= 4 (not that it matters)!*/ + 0x60 /* 3*32: encoded, offset, size */ + slt /*signed less than */ + tag_9 + jumpi /*revert if calldata too short for foo (must be at least 3 words)*/ + calldataload(0x04) [0x80, 0, cd[4:36] (=encodedPO)] + swap1 [0x80, encodedPO, 0] + 0xffffffffffffffff [0x80, encodedPO, 0, 0xffffffffffffffff (=2^64-1)] + swap1 [0x80, encodedPO, 2^64-1, 0] + dup2 [0x80, encodedPO, 2^64-1, 0, 2^64-1] + dup4 [0x80, encodedPO, 2^64-1, 0, 2^64-1, encodedPO] + gt + tag_9 + jumpi /*revert if encodedPO points to something beyond 2^64-1 in calldata*/ + calldatasize [0x80, encodedPO, 2^64-1, 0, calldatasize] + 0x23 [0x80, encodedPO, 2^64-1, 0, calldatasize, 0x23 (=35)] + dup5 [0x80, encodedPO, 2^64-1, 0, calldatasize, 35, encodedPO] + add [0x80, encodedPO, 2^64-1, 0, calldatasize, encodedPO+35] + slt + iszero + tag_9 /*revert if encodedPO points outside of calldata (I think? not sure why 35 and not 36=32+4)*/ + jumpi + dup3 [0x80, encodedPO, 2^64-1, 0, encodedPO] + 0x04 [0x80, encodedPO, 2^64-1, 0, encodedPO, 4] + add [0x80, encodedPO, 2^64-1, 0, encodedPO+4] + calldataload [0x80, encodedPO, 2^64-1, 0, encode.length] + dup3 [0x80, encodedPO, 2^64-1, 0, encode.length, 2^64-1] + dup2 [0x80, encodedPO, 2^64-1, 0, encode.length, 2^64-1, encode.length] + gt + tag_11 + jumpi /*revert if encode.length is larger than 2^64-1*/ + 0x24 [0x80, encodedPO, 2^64-1, 0, encode.length, 0x24 (=36)] + swap4 [0x80, 36, 2^64-1, 0, encode.length, encodedPO] + calldatasize [0x80, 36, 2^64-1, 0, encode.length, encodedPO, calldatasize] + dup6 [0x80, 36, 2^64-1, 0, encode.length, encodedPO, calldatasize, 36] + dup4 [0x80, 36, 2^64-1, 0, encode.length, encodedPO, calldatasize, 36, encode.length] + dup4 [0x80, 36, 2^64-1, 0, encode.length, encodedPO, calldatasize, 36, encode.length, encodedPO] + add + add [0x80, 36, 2^64-1, 0, encode.length, encodedPO, calldatasize, 36+encode.length+encodedPO] + gt [0x80, 36, 2^64-1, 0, encode.length, encodedPO, encodedExceedsCalldata] + tag_13 + jumpi /*revert if encodedPO+encode.length exceeds calldata*/ + dup5 [0x80, 36, 2^64-1, 0, encode.length, encodedPO, 36] + calldataload [0x80, 36, 2^64-1, 0, encode.length, encodedPO, offset] + swap1 [0x80, 36, 2^64-1, 0, encode.length, offset, encodedPO] + 0x44 + calldataload [0x80, 36, 2^64-1, 0, encode.length, offset, encodedPO, length] + dup3 [0x80, 36, 2^64-1, 0, encode.length, offset, encodedPO, length, offset] + add [0x80, 36, 2^64-1, 0, encode.length, offset, encodedPO, length+offset] + swap3 [0x80, 36, 2^64-1, 0, length+offset, offset, encodedPO, encode.length] + dup4 [0x80, 36, 2^64-1, 0, length+offset, offset, encodedPO, encode.length, length+offset] + dup4 [0x80, 36, 2^64-1, 0, length+offset, offset, encodedPO, encode.length, length+offset, offset] + gt + tag_23 + jumpi /*pointless check that reverts if offset > length+offset */ + dup4 [0x80, 36, 2^64-1, 0, length+offset, offset, encodedPO, encode.length, length+offset] + gt + tag_17 + jumpi /*revert if length+offset > encode.length*/ + dup2 [0x80, 36, 2^64-1, 0, length+offset, offset, encodedPO, offset] + add [0x80, 36, 2^64-1, 0, length+offset, offset, encodedPO+offset] + swap2 [0x80, 36, 2^64-1, 0, encodedPO+offset, offset, length+offset] + sub [0x80, 36, 2^64-1, 0, encodedPO+offset, length] + dup4 [0x80, 36, 2^64-1, 0, encodedPO+offset, length, 2^64-1] + dup2 [0x80, 36, 2^64-1, 0, encodedPO+offset, length, 2^64-1, length] + gt + tag_19 + jumpi /*revert if length > 2^64-1*/ + 2^256-31 [0x80, 36, 2^64-1, 0, encodedPO+offset, length, 2^256-31] + swap5 [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36] + 0x1f [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, 31] + dup3 [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, 31, length] + add [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, 31+length] + dup7 [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, 31+length, 2^256-31] + and [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, (31+length)lower5bits=0] + 0x3f [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, (31+length)lower5bits=0, 63] + add [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, ((31+length)lower5bits=0)+63] + dup7 [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, ((31+length)lower5bits=0)+63, 2^256-31] + and [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, (((31+length)lower5bits=0)+63)lower5bits=0] + dup8 [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, (((31+length)lower5bits=0)+63)lower5bits=0, 0x80] + add [0x80, 2^256-31, 2^64-1, 0, encodedPO+offset, length, 36, (((31+length)lower5bits=0)+63)lower5bits=0+0x80] + swap5 [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 2^64-1] + dup6 [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 2^64-1, (((31+length)lower5bits=0)+63)lower5bits=0+0x80] + gt /*idiotic gt*/[0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 0] + dup8 [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 0, 0x80] + dup7 [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 0, 0x80, (((31+length)lower5bits=0)+63)lower5bits=0+0x80] + lt /*idiotic lt - known at compile time*/ [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 0, 0] + or [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 1] + tag_21 + jumpi /*revert if applicable with Panic(0x41) = oversized allocation*/ + 0x40 [0x80, 2^256-31, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 0, encodedPO+offset, length, 36, 64] + swap5 [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36, (((31+length)lower5bits=0)+63)lower5bits=0+0x80] + 0x40 [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 64] + mstore /*write to free memory ptr*/ [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36, (((31+length)lower5bits=0)+63)lower5bits=0+0x80, 64] + dup2 [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36, length] + dup8 [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36, length, 0x80] + mstore /*store length at 0x80*/ [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36] + 0x20 [0x80, 2^256-31, 64, 0, encodedPO+offset, length, 36, 32] + swap3 [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset] + calldatasize [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset, calldatasize] + dup3 [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset, calldatasize, 36] + dup5 [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset, calldatasize, 36, length] + dup4 [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset, calldatasize, 36, length, encodedPO+offset] + add [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset, calldatasize, 36, length+encodedPO+offset] + add [0x80, 2^256-31, 64, 0, 32, length, 36, encodedPO+offset, calldatasize, 36+length+encodedPO+offset] + gt + tag_23 + jumpi /*revert if we read past calldata*/ + swap2 [0x80, 2^256-31, 64, 0, 32, encodedPO+offset, 36, length] + dup1 [0x80, 2^256-31, 64, 0, 32, encodedPO+offset, 36, length, length] + dup5 [0x80, 2^256-31, 64, 0, 32, encodedPO+offset, 36, length, length, 32] + swap9 [32, 2^256-31, 64, 0, 32, encodedPO+offset, 36, length, length, 0x80] + swap7 [32, 2^256-31, 0x80, 0, 32, encodedPO+offset, 36, length, length, 64] + swap6 [32, 2^256-31, 0x80, 64, 32, encodedPO+offset, 36, length, length, 0] + swap5 [32, 2^256-31, 0x80, 64, 0, encodedPO+offset, 36, length, length, 32] + swap3 [32, 2^256-31, 0x80, 64, 0, encodedPO+offset, 32, length, length, 36] + dup6 [32, 2^256-31, 0x80, 64, 0, encodedPO+offset, 32, length, length, 36, 0] + swap5 [32, 2^256-31, 0x80, 64, 0, 0, 32, length, length, 36, encodedPO+offset] + add [32, 2^256-31, 0x80, 64, 0, 0, 32, length, length, 36+encodedPO+offset] + dup4 [32, 2^256-31, 0x80, 64, 0, 0, 32, length, length, 36+encodedPO+offset, 32] + dup9 [32, 2^256-31, 0x80, 64, 0, 0, 32, length, length, 36+encodedPO+offset, 32, 0x80] + add [32, 2^256-31, 0x80, 64, 0, 0, 32, length, length, 36+encodedPO+offset, 0xA0] + calldatacopy /*actually copy slice*/ [32, 2^256-31, 0x80, 64, 0, 0, 32, length] + dup6 [32, 2^256-31, 0x80, 64, 0, 0, 32, length, 0x80] + add [32, 2^256-31, 0x80, 64, 0, 0, 32, length+0x80] + add [32, 2^256-31, 0x80, 64, 0, 0, length+0xA0] + mstore /*rather pointless write of zeros after slice*/ [32, 2^256-31, 0x80, 64, 0] + mload(0x40) /*load free memory ptr*/ [32, 2^256-31, 0x80, 64, 0, freeMemPtr(the ugly expression from before)] + swap5 [freeMemPtr, 2^256-31, 0x80, 64, 0, 32] + dup6 [freeMemPtr, 2^256-31, 0x80, 64, 0, 32, freeMemPtr] + swap4 [freeMemPtr, 2^256-31, freeMemPtr, 64, 0, 32, 0x80] + dup2 [freeMemPtr, 2^256-31, freeMemPtr, 64, 0, 32, 0x80, 32] + dup6 [freeMemPtr, 2^256-31, freeMemPtr, 64, 0, 32, 0x80, 32, freeMemPtr] + mstore [freeMemPtr, 2^256-31, freeMemPtr, 64, 0, 32, 0x80] + dup1 [freeMemPtr, 2^256-31, freeMemPtr, 64, 0, 32, 0x80, 0x80] + mload [freeMemPtr, 2^256-31, freeMemPtr, 64, 0, 32, 0x80, length] + swap4 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64] + dup5 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, length] + dup4 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, length, 32] + dup8 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, length, 32, freeMemPtr] + add [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, length, 32+freeMemPtr] + mstore /*store length in next free memory word*/ [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64] + dup4 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, 0] +tag_25: + dup6 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, 0, length] + dup2 [freeMemPtr, 2^256-31, freeMemPtr, length, 0, 32, 0x80, 64, 0, length, 0] + lt /*insanely pointless 0 store 4 at 0x80 + 0x20 [0x40, 0x80, calldatasize-4, 0x20] + dup3 [0x40, 0x80, calldatasize-4, 0x20, 0x80] + add [0x40, 0x80, calldatasize-4, 0xA0] + mstore [0x40, 0x80] -> store calldatasize-4 at 0xA0 + return -> return 64 bytes at 0x80 +tag_7: + dup3 + dup1 + revert +``` + diff --git a/src/libraries/BytesParsing.sol b/src/libraries/BytesParsing.sol index 06238a1..84643d6 100644 --- a/src/libraries/BytesParsing.sol +++ b/src/libraries/BytesParsing.sol @@ -19,6 +19,11 @@ library BytesParsing { revert OutOfBounds(pastTheEndOffset, length); } + function checkLength(uint encodedLength, uint expectedLength) internal pure { + if (encodedLength != expectedLength) + revert LengthMismatch(encodedLength, expectedLength); + } + //Summary of all remaining functions: // //Each function has 2*2=4 versions: @@ -42,7 +47,6 @@ library BytesParsing { // as input and return the parsed value and the next offset (i.e. the offset pointing to the // next, unparsed byte). // - // * checkLength(encoded, expected) - no return, reverts if encoded.length != expected // * slice(encoded, offset, length) // * sliceUintPrefixed - n in {8, 16, 32} - parses n bytes of length prefix followed by data // * asAddress @@ -54,22 +58,12 @@ library BytesParsing { bytes calldata encoded, uint offset, uint length - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { /// @solidity memory-safe-assembly assembly { + ret.offset := add(encoded.offset, offset) + ret.length := length nextOffset := add(offset, length) - ret := mload(FREE_MEMORY_PTR) - - mstore(ret, length) - let retStart := add(ret, WORD_SIZE) - let sliceStart := add(encoded.offset, offset) - calldatacopy(retStart, sliceStart, length) - //When compiling with --via-ir then normally allocated memory (i.e. via new) will have 32 byte - // memory alignment and so we enforce the same memory alignment here. - mstore( - FREE_MEMORY_PTR, - and(add(add(retStart, length), WORD_SIZE_MINUS_ONE), not(WORD_SIZE_MINUS_ONE)) - ) } } @@ -126,21 +120,11 @@ library BytesParsing { /* ------------------------------------------------------------------------------------------------- Remaining library code below was auto-generated via the following js/node code: -for (const cd of ["Cd", ""]) - console.log( -`function checkLength${cd}( - bytes ${cd ? "calldata" : "memory"} encoded, - uint256 expected -) internal pure { - if (encoded.length != expected) - revert LengthMismatch(encoded.length, expected); -} - function slice${cd}( bytes ${cd ? "calldata" : "memory"} encoded, uint offset, uint length -) internal pure returns (bytes memory ret, uint nextOffset) { +) internal pure returns (bytes ${cd ? "calldata" : "memory"} ret, uint nextOffset) { (ret, nextOffset) = slice${cd}Unchecked(encoded, offset, length); checkBound(nextOffset, encoded.length); } @@ -154,7 +138,7 @@ const funcs = [ `(len, nextOffset) = asUint${n}${cd}Unchecked(encoded, offset);`, `(ret, nextOffset) = slice${cd}Unchecked(encoded, nextOffset, uint(len));` ], - `bytes memory`, + cd => `bytes ${cd ? "calldata" : "memory"}`, ]), [ `asAddress`, cd => [ @@ -162,7 +146,7 @@ const funcs = [ `(tmp, nextOffset) = asUint160${cd}Unchecked(encoded, offset);`, `ret = address(tmp);` ], - `address` + _ => `address` ], [ `asBool`, cd => [ @@ -175,7 +159,7 @@ const funcs = [ `/// @solidity memory-safe-assembly`, `assembly { ret := cleanedVal }` ], - `bool` + _ => `bool` ], ...Array.from({length: 32}, (_, i) => [ `asUint${(i+1)*8}`, @@ -187,7 +171,7 @@ const funcs = [ : ` ret := mload(add(encoded, nextOffset))`, `}` ], - `uint${(i+1)*8}` + _ => `uint${(i+1)*8}` ]), ...Array.from({length: 32}, (_, i) => [ `asBytes${i+1}`, @@ -198,7 +182,7 @@ const funcs = [ ` nextOffset := add(offset, ${i+1})`, `}` ], - `bytes${i+1}` + _ => `bytes${i+1}` ]), ]; @@ -208,14 +192,14 @@ for (const [name, code, ret] of funcs) { `function ${name}${cd}Unchecked( bytes ${cd ? "calldata" : "memory"} encoded, uint offset -) internal pure returns (${ret} ret, uint nextOffset) { +) internal pure returns (${ret(cd)} ret, uint nextOffset) { ${code(cd).join("\n ")} } function ${name}${cd}( bytes ${cd ? "calldata" : "memory"} encoded, uint offset -) internal pure returns (${ret} ret, uint nextOffset) { +) internal pure returns (${ret(cd)} ret, uint nextOffset) { (ret, nextOffset) = ${name}${cd}Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } @@ -223,31 +207,15 @@ function ${name}${cd}( } ------------------------------------------------------------------------------------------------- */ - function checkLengthCd( - bytes calldata encoded, - uint256 expected - ) internal pure { - if (encoded.length != expected) - revert LengthMismatch(encoded.length, expected); - } - function sliceCd( bytes calldata encoded, uint offset, uint length - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { (ret, nextOffset) = sliceCdUnchecked(encoded, offset, length); checkBound(nextOffset, encoded.length); } - function checkLength( - bytes memory encoded, - uint256 expected - ) internal pure { - if (encoded.length != expected) - revert LengthMismatch(encoded.length, expected); - } - function slice( bytes memory encoded, uint offset, @@ -260,7 +228,7 @@ function ${name}${cd}( function sliceUint8PrefixedCdUnchecked( bytes calldata encoded, uint offset - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { uint8 len; (len, nextOffset) = asUint8CdUnchecked(encoded, offset); (ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len)); @@ -269,7 +237,7 @@ function ${name}${cd}( function sliceUint8PrefixedCd( bytes calldata encoded, uint offset - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { (ret, nextOffset) = sliceUint8PrefixedCdUnchecked(encoded, offset); checkBound(nextOffset, encoded.length); } @@ -294,7 +262,7 @@ function ${name}${cd}( function sliceUint16PrefixedCdUnchecked( bytes calldata encoded, uint offset - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { uint16 len; (len, nextOffset) = asUint16CdUnchecked(encoded, offset); (ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len)); @@ -303,7 +271,7 @@ function ${name}${cd}( function sliceUint16PrefixedCd( bytes calldata encoded, uint offset - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { (ret, nextOffset) = sliceUint16PrefixedCdUnchecked(encoded, offset); checkBound(nextOffset, encoded.length); } @@ -328,7 +296,7 @@ function ${name}${cd}( function sliceUint32PrefixedCdUnchecked( bytes calldata encoded, uint offset - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { uint32 len; (len, nextOffset) = asUint32CdUnchecked(encoded, offset); (ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len)); @@ -337,7 +305,7 @@ function ${name}${cd}( function sliceUint32PrefixedCd( bytes calldata encoded, uint offset - ) internal pure returns (bytes memory ret, uint nextOffset) { + ) internal pure returns (bytes calldata ret, uint nextOffset) { (ret, nextOffset) = sliceUint32PrefixedCdUnchecked(encoded, offset); checkBound(nextOffset, encoded.length); } diff --git a/src/libraries/WormholeCctpMessages.sol b/src/libraries/WormholeCctpMessages.sol index 1445b9c..57e67fb 100644 --- a/src/libraries/WormholeCctpMessages.sol +++ b/src/libraries/WormholeCctpMessages.sol @@ -11,6 +11,7 @@ import {toUniversalAddress} from "wormhole-sdk/Utils.sol"; library WormholeCctpMessages { using { toUniversalAddress } for address; using BytesParsing for bytes; + using {BytesParsing.checkLength} for uint; // Payload IDs. // @@ -141,6 +142,6 @@ library WormholeCctpMessages { offset ) = asDepositUnchecked(encoded, offset); - encoded.checkLength(offset); + encoded.length.checkLength(offset); } } diff --git a/src/testing/CctpMessages.sol b/src/testing/CctpMessages.sol index 8a99ea7..0b138f4 100644 --- a/src/testing/CctpMessages.sol +++ b/src/testing/CctpMessages.sol @@ -50,6 +50,7 @@ struct CctpTokenBurnMessage { library CctpMessages { using BytesParsing for bytes; + using {BytesParsing.checkLength} for uint; uint private constant _CCTP_HEADER_SIZE = 3*4 + 8 + 3*32; uint private constant _CCTP_TOKEN_BURN_MESSAGE_SIZE = _CCTP_HEADER_SIZE + 4 + 4*32; @@ -115,7 +116,7 @@ library CctpMessages { (ret.sender, offset) = encoded.asBytes32Unchecked(offset); (ret.recipient, offset) = encoded.asBytes32Unchecked(offset); (ret.destinationCaller, offset) = encoded.asBytes32Unchecked(offset); - encoded.checkLength(offset); + encoded.length.checkLength(offset); } function decodeCctpMessage( @@ -139,7 +140,7 @@ library CctpMessages { (ret.mintRecipient, offset) = encoded.asBytes32Unchecked(offset); (ret.amount, offset) = encoded.asUint256Unchecked(offset); (ret.messageSender, offset) = encoded.asBytes32Unchecked(offset); - encoded.checkLength(offset); + encoded.length.checkLength(offset); return ret; } } \ No newline at end of file diff --git a/src/testing/WormholeRelayer/DeliveryInstructionSerde.sol b/src/testing/WormholeRelayer/DeliveryInstructionSerde.sol index f9dd02c..f41563a 100644 --- a/src/testing/WormholeRelayer/DeliveryInstructionSerde.sol +++ b/src/testing/WormholeRelayer/DeliveryInstructionSerde.sol @@ -11,6 +11,7 @@ uint8 constant PAYLOAD_ID_DELIVERY_INSTRUCTION = 1; uint8 constant PAYLOAD_ID_REDELIVERY_INSTRUCTION = 2; using BytesParsing for bytes; +using {BytesParsing.checkLength} for uint; struct DeliveryInstruction { uint16 targetChain; @@ -84,7 +85,7 @@ function decodeDeliveryInstruction( (strct.senderAddress, offset) = encoded.asBytes32Unchecked(offset); (strct.messageKeys, offset) = decodeMessageKeyArray(encoded, offset); - encoded.checkLength(offset); + encoded.length.checkLength(offset); } function encode(RedeliveryInstruction memory strct) @@ -116,7 +117,7 @@ function decodeRedeliveryInstruction( (strct.newSourceDeliveryProvider, offset) = encoded.asBytes32Unchecked(offset); (strct.newSenderAddress, offset) = encoded.asBytes32Unchecked(offset); - encoded.checkLength(offset); + encoded.length.checkLength(offset); } function vaaKeyArrayToMessageKeyArray( @@ -250,5 +251,5 @@ function decodeDeliveryOverride( (strct.newExecutionInfo, offset) = decodeBytes(encoded, offset); (strct.redeliveryHash, offset) = encoded.asBytes32Unchecked(offset); - encoded.checkLength(offset); + encoded.length.checkLength(offset); } diff --git a/test/generated/BytesParsingTestWrapper.sol b/test/generated/BytesParsingTestWrapper.sol index 352f45b..c4586d7 100644 --- a/test/generated/BytesParsingTestWrapper.sol +++ b/test/generated/BytesParsingTestWrapper.sol @@ -10,11 +10,15 @@ contract BytesParsingTestWrapper { BytesParsing.checkBound(pastTheEndOffset, length); } + function checkLength(uint encodedLength, uint expectedLength) external pure { + BytesParsing.checkLength(encodedLength, expectedLength); + } + function sliceCdUnchecked( bytes calldata encoded, uint offset, uint length - ) external pure returns (bytes memory ret, uint nextOffset) { + ) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceCdUnchecked(encoded, offset, length); } @@ -26,22 +30,14 @@ contract BytesParsingTestWrapper { return BytesParsing.sliceUnchecked(encoded, offset, length); } - function checkLengthCd(bytes calldata encoded, uint256 expected) external pure { - BytesParsing.checkLengthCd(encoded, expected); - } - function sliceCd( bytes calldata encoded, uint offset, uint length - ) external pure returns (bytes memory ret, uint nextOffset) { + ) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceCd(encoded, offset, length); } - function checkLength(bytes calldata encoded, uint256 expected) external pure { - BytesParsing.checkLength(encoded, expected); - } - function slice( bytes calldata encoded, uint offset, @@ -50,11 +46,11 @@ contract BytesParsingTestWrapper { return BytesParsing.slice(encoded, offset, length); } - function sliceUint8PrefixedCdUnchecked(bytes calldata encoded, uint offset) external pure returns (bytes memory ret, uint nextOffset) { + function sliceUint8PrefixedCdUnchecked(bytes calldata encoded, uint offset) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceUint8PrefixedCdUnchecked(encoded, offset); } - function sliceUint8PrefixedCd(bytes calldata encoded, uint offset) external pure returns (bytes memory ret, uint nextOffset) { + function sliceUint8PrefixedCd(bytes calldata encoded, uint offset) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceUint8PrefixedCd(encoded, offset); } @@ -66,11 +62,11 @@ contract BytesParsingTestWrapper { return BytesParsing.sliceUint8Prefixed(encoded, offset); } - function sliceUint16PrefixedCdUnchecked(bytes calldata encoded, uint offset) external pure returns (bytes memory ret, uint nextOffset) { + function sliceUint16PrefixedCdUnchecked(bytes calldata encoded, uint offset) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceUint16PrefixedCdUnchecked(encoded, offset); } - function sliceUint16PrefixedCd(bytes calldata encoded, uint offset) external pure returns (bytes memory ret, uint nextOffset) { + function sliceUint16PrefixedCd(bytes calldata encoded, uint offset) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceUint16PrefixedCd(encoded, offset); } @@ -82,11 +78,11 @@ contract BytesParsingTestWrapper { return BytesParsing.sliceUint16Prefixed(encoded, offset); } - function sliceUint32PrefixedCdUnchecked(bytes calldata encoded, uint offset) external pure returns (bytes memory ret, uint nextOffset) { + function sliceUint32PrefixedCdUnchecked(bytes calldata encoded, uint offset) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceUint32PrefixedCdUnchecked(encoded, offset); } - function sliceUint32PrefixedCd(bytes calldata encoded, uint offset) external pure returns (bytes memory ret, uint nextOffset) { + function sliceUint32PrefixedCd(bytes calldata encoded, uint offset) external pure returns (bytes calldata ret, uint nextOffset) { return BytesParsing.sliceUint32PrefixedCd(encoded, offset); }