Skip to content

Commit

Permalink
Fix read abi methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Agusx1211 committed Jan 22, 2024
1 parent 08ddb5b commit 9c791a7
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 72 deletions.
2 changes: 0 additions & 2 deletions contracts/modules/utils/L2Compressor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import "../commons/submodules/auth/SequenceBaseSig.sol";
import "../../utils/LibBytesPointer.sol";
import "../../utils/LibBytes.sol";

import "forge-std/console.sol";

function bytesToUint256(
bytes memory _b
) pure returns (uint256 result) {
Expand Down
32 changes: 32 additions & 0 deletions foundry_test/modules/utils/L2CompressorEncoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ function packToBytes(uint256 value, uint256 b) pure returns (bytes memory) {
}
}

function encodeWord(bytes32 _value) pure returns (bytes memory) {
return encodeWord(uint256(_value));
}

function encodeWord(uint256 _value) pure returns (bytes memory) {
uint8 b = requiredBytesFor(_value);
return abi.encodePacked(b, packToBytes(_value, b));
Expand Down Expand Up @@ -187,3 +191,31 @@ function encode_raw_address(address _addr) pure returns (bytes memory) {
function encode_bytes_n(bytes memory _data) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x2b), encodeWord(_data.length), _data);
}

function encode_abi_call(bytes4 _selector) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x2d), _selector);
}

function encode_abi_call(bytes4 _selector, bytes32 _v1) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x2e), _selector, encodeWord(_v1));
}

function encode_abi_call(bytes4 _selector, bytes32 _v1, bytes32 _v2) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x2f), _selector, encodeWord(_v1), encodeWord(_v2));
}

function encode_abi_call(bytes4 _selector, bytes32 _v1, bytes32 _v2, bytes32 _v3) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x30), _selector, encodeWord(_v1), encodeWord(_v2), encodeWord(_v3));
}

function encode_abi_call(bytes4 _selector, bytes32 _v1, bytes32 _v2, bytes32 _v3, bytes32 _v4) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x31), _selector, encodeWord(_v1), encodeWord(_v2), encodeWord(_v3), encodeWord(_v4));
}

function encode_abi_call(bytes4 _selector, bytes32 _v1, bytes32 _v2, bytes32 _v3, bytes32 _v4, bytes32 _v5) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x32), _selector, encodeWord(_v1), encodeWord(_v2), encodeWord(_v3), encodeWord(_v4), encodeWord(_v5));
}

function encode_abi_call(bytes4 _selector, bytes32 _v1, bytes32 _v2, bytes32 _v3, bytes32 _v4, bytes32 _v5, bytes32 _v6) pure returns (bytes memory) {
return abi.encodePacked(uint8(0x33), _selector, encodeWord(_v1), encodeWord(_v2), encodeWord(_v3), encodeWord(_v4), encodeWord(_v5), encodeWord(_v6));
}
115 changes: 107 additions & 8 deletions foundry_test/modules/utils/L2CompressorHuffReadFlag.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import "forge-std/console2.sol";
import { HuffConfig } from "foundry-huff/HuffConfig.sol";
import { HuffDeployer } from "foundry-huff/HuffDeployer.sol";

import "./L2CompressorEncoder.sol";

uint256 constant FMS = 0xa0;

contract L2CompressorHuffReadFlagTests is AdvTest {
Expand Down Expand Up @@ -244,18 +246,115 @@ contract L2CompressorHuffReadFlagTests is AdvTest {
assertEq(res, _data);
}

function test_read_flag_abi_encode_1() external {
bytes4 selector = 0x9988aabb;
uint256 val = type(uint64).max;
function test_read_flag_abi_encode_0(bytes4 _selector) external {
bytes memory encoded = encode_abi_call(_selector);
(bool s, bytes memory r) = imp.staticcall(encoded);

(bool s, bytes memory r) = imp.staticcall(
abi.encodePacked(hex"2e", selector, hex"08", uint64(val))
);
assertTrue(s);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector), res);
}

function test_read_flag_abi_encode_1(bytes4 _selector, bytes32 _v1) external {
bytes memory encoded = encode_abi_call(_selector, _v1);
(bool s, bytes memory r) = imp.staticcall(encoded);

assertTrue(s);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector, _v1), res);
}

function test_read_flag_abi_encode_2(bytes4 _selector, bytes32 _v1, bytes32 _v2) external {
bytes memory encoded = encode_abi_call(_selector, _v1, _v2);
(bool s, bytes memory r) = imp.staticcall(encoded);

assertTrue(s);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector, _v1, _v2), res);
}

function test_read_flag_abi_encode_3(bytes4 _selector, bytes32 _v1, bytes32 _v2, bytes32 _v3) external {
bytes memory encoded = encode_abi_call(_selector, _v1, _v2, _v3);
(bool s, bytes memory r) = imp.staticcall(encoded);

assertTrue(s);
console.logBytes(r);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));
console.logBytes(res);

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector, _v1, _v2, _v3), res);
}

function test_read_flag_abi_encode_4(
bytes4 _selector,
bytes32 _v1,
bytes32 _v2,
bytes32 _v3,
bytes32 _v4
) external {
bytes memory encoded = encode_abi_call(_selector, _v1, _v2, _v3, _v4);
(bool s, bytes memory r) = imp.staticcall(encoded);

assertTrue(s);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector, _v1, _v2, _v3, _v4), res);
}

function test_read_flag_abi_encode_5(
bytes4 _selector,
bytes32 _v1,
bytes32 _v2,
bytes32 _v3,
bytes32 _v4,
bytes32 _v5
) external {
bytes memory encoded = encode_abi_call(_selector, _v1, _v2, _v3, _v4, _v5);
(bool s, bytes memory r) = imp.staticcall(encoded);

assertTrue(s);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector, _v1, _v2, _v3, _v4, _v5), res);
}

function test_read_flag_abi_encode_5(
bytes4 _selector,
bytes32 _v1,
bytes32 _v2,
bytes32 _v3,
bytes32 _v4,
bytes32 _v5,
bytes32 _v6
) external {
bytes memory encoded = encode_abi_call(_selector, _v1, _v2, _v3, _v4, _v5, _v6);
(bool s, bytes memory r) = imp.staticcall(encoded);

assertTrue(s);

(uint256 rindex, uint256 windex, bytes memory res) = abi.decode(r, (uint256, uint256, bytes));

assertEq(rindex, encoded.length);
assertEq(windex, FMS + res.length);
assertEq(abi.encodePacked(_selector, _v1, _v2, _v3, _v4, _v5, _v6), res);
}
}
134 changes: 72 additions & 62 deletions src/L2Compressor.huff
Original file line number Diff line number Diff line change
Expand Up @@ -322,25 +322,25 @@
end jump

FLAG_ABI_0_PARAM:
READ_ABI(nrfs, 0x00) // [windex, rindex]
READ_ABI_0() // [windex, rindex]
end jump
FLAG_ABI_1_PARAM:
READ_ABI(nrfs, 0x01) // [windex, rindex]
READ_ABI_1(nrfs) // [windex, rindex]
end jump
FLAG_ABI_2_PARAMS:
READ_ABI(nrfs, 0x02) // [windex, rindex]
READ_ABI_2(nrfs) // [windex, rindex]
end jump
FLAG_ABI_3_PARAMS:
READ_ABI(nrfs, 0x03) // [windex, rindex]
READ_ABI_3(nrfs) // [windex, rindex]
end jump
FLAG_ABI_4_PARAMS:
READ_ABI(nrfs, 0x04) // [windex, rindex]
READ_ABI_4(nrfs) // [windex, rindex]
end jump
FLAG_ABI_5_PARAMS:
READ_ABI(nrfs, 0x05) // [windex, rindex]
READ_ABI_5(nrfs) // [windex, rindex]
end jump
FLAG_ABI_6_PARAMS:
READ_ABI(nrfs, 0x06) // [windex, rindex]
READ_ABI_6(nrfs) // [windex, rindex]
end jump

default:
Expand Down Expand Up @@ -876,87 +876,97 @@
end_data_if:
}

#define macro READ_ABI(nrfs, nparams) = takes (3) returns (2) {
// input stack: [windex, rindex]

// Reserve 32 bytes to store the size, dynamic values
// use the first 32 bytes to store the size of the value
0x20 // [0x20, windex, rindex]
add // [0x20 + windex, rindex]
#define macro READ_ABI_4_BYTES() = takes (2) returns (2) {
// input stack: [windex, rindex]

0x04 // [0x04, windex, rindex]
dup1 // [0x04, 0x04, windex, rindex]
dup4 // [rindex, 0x04, 0x04, windex, rindex]
dup4 // [windex, rindex, 0x04, 0x04, windex, rindex]
calldatacopy // [0x04, windex, rindex]

dup2 // [windex, 0x04, windex, rindex]
swap2 // [rindex, windex, 0x04]
dup3 // [0x04, rindex, windex, 0x04]
add // [(0x04 + rindex), windex, 0x04]
swap2 // [0x04, windex, (0x04 + rindex)]
add // [(0x04 + windex), (0x04 + rindex)]

swap3 // [rindex, 0x04, windex, windex]
add // [rindex + 0x04, windex, windex]
// output stack: [windex, rindex]
}

swap1 // [windex, rindex + 0x04, windex]
0x04 add // [windex + 0x04, rindex + 0x04, windex]
swap1 // [rindex + 0x04, windex + 0x04, windex]
#define macro READ_ABI_0() = takes (2) returns (2) {
// input stack: [windex, rindex]

0x00 // [i, rindex, windex, prev_windex]
read_param: // [i, rindex, windex, prev_windex]
swap2 // [windex, rindex, i, prev_windex]
READ_ABI_4_BYTES()

PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex, i, prev_windex]
BACKREAD_SINGLE_VALUE() // [val, windex, rindex, i, prev_windex]
// output stack: [windex, rindex]
}

dup2 // [windex, val, windex, rindex, i, prev_windex]
mstore // [windex, rindex, i, prev_windex]
#define macro READ_ABI_1(nrfs) = takes (2) returns (2) {
// input stack: [windex, rindex]

0x20 add // [windex + 0x20, rindex, i, prev_windex]
READ_ABI_4_BYTES() // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]

swap2 // [i, rindex, windex + 0x20, prev_windex]
// output stack: [windex, rindex]
}

0x01 add // [i + 1, rindex, windex, prev_windex]
#define macro READ_ABI_2(nrfs) = takes (2) returns (2) {
// input stack: [windex, rindex]

dup1 // [i + 1, i + 1, rindex, windex, prev_windex]
<nparams> lt // [i + 1 < nparams, i + 1, rindex, windex, prev_windex]
read_param // [read_param, i + 1 < nparams, i + 1, rindex, windex, prev_windex]
jumpi // [i + 1, rindex, windex, prev_windex]
READ_ABI_4_BYTES() // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]

pop // [rindex, windex, prev_windex]
// output stack: [windex, rindex]
}

// We need to fill the last 32 bytes with 0x00, dynamic values
// must be padded to 32 bytes
#define macro READ_ABI_3(nrfs) = takes (2) returns (2) {
// input stack: [windex, rindex]

dup3 // [prev_windex, rindex, windex, prev_windex]
dup3 // [windex, prev_windex, rindex, windex, prev_windex]

sub // [size, rindex, windex, prev_index]
dup1 // [size, size, rindex, windex, prev_index]
READ_ABI_4_BYTES() // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]

0x1f and // [size % 32, size, rindex, windex, prev_index]
0x20 sub // [32 - size % 32, size, rindex, windex, prev_index]
0x1f and // [(32 - size % 32) % 32, size, rindex, windex, prev_index]
// output stack: [windex, rindex]
}

// Zero out the memory, just in case
#define macro READ_ABI_4(nrfs) = takes (2) returns (2) {
// input stack: [windex, rindex]

0x00 // [0x00, 32 - size % 32, size, rindex, windex, prev_index]
dup5 // [windex, 0x00, 32 - size % 32, size, rindex, windex, prev_index]
mstore // [32 - size % 32, size, rindex, windex, prev_index]
READ_ABI_4_BYTES() // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]

// output stack: [windex, rindex]
}

#define macro READ_ABI_5(nrfs) = takes (2) returns (2) {
// input stack: [windex, rindex]

// Advance the windex by the number of required bytes
swap1 // [size, 32 - size % 32, rindex, windex, prev_index]
swap3 // [windex, 32 - size % 32, rindex, size, prev_index]
add // [windex, rindex, size, prev_index]
READ_ABI_4_BYTES() // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]

// Now we need to store the full size of the value
// luckly windex - prev_index should give us the padded index
// output stack: [windex, rindex]
}

swap2 // [size, rindex, windex, prev_index]
0x20 // [0x20, size, rindex, windex, prev_index]
dup5 // [prev_index, size, rindex, windex, prev_index]
sub // [(0x20 - prev_index), size, rindex, windex, prev_index]
mstore // [rindex, windex, prev_index]
#define macro READ_ABI_6(nrfs) = takes (2) returns (2) {
// input stack: [windex, rindex]

swap2 // [prev_index, windex, rindex]
pop // [windex, rindex]
READ_ABI_4_BYTES() // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]
PERFORM_NESTED_READ_FLAG(<nrfs>) // [windex, rindex]

// output stack: [windex, rindex]
}
Expand Down

0 comments on commit 9c791a7

Please sign in to comment.