From 8a319aeaeb3efa0f7901c95ebd5cab186579458f Mon Sep 17 00:00:00 2001 From: Agusx1211 Date: Thu, 25 Jan 2024 16:27:40 +0000 Subject: [PATCH] Add extra method self execute --- .../utils/L2CompressorHuffReadExecute.sol | 4 +- .../utils/L2CompressorHuffReadFlag.t.sol | 39 ++++++++++++- src/L2Compressor.huff | 56 +++++++++++++++++-- 3 files changed, 90 insertions(+), 9 deletions(-) diff --git a/foundry_test/modules/utils/L2CompressorHuffReadExecute.sol b/foundry_test/modules/utils/L2CompressorHuffReadExecute.sol index eb98d4a..b479177 100644 --- a/foundry_test/modules/utils/L2CompressorHuffReadExecute.sol +++ b/foundry_test/modules/utils/L2CompressorHuffReadExecute.sol @@ -11,10 +11,10 @@ import { HuffDeployer } from "foundry-huff/HuffDeployer.sol"; import "contracts/modules/commons/interfaces/IModuleCalls.sol"; -uint256 constant FMS = 0xa0; - import "./L2CompressorEncoder.sol"; +uint256 constant FMS = 0xa0; + contract L2CompressorHuffReadExecuteTest is AdvTest { address public imp; diff --git a/foundry_test/modules/utils/L2CompressorHuffReadFlag.t.sol b/foundry_test/modules/utils/L2CompressorHuffReadFlag.t.sol index 4ec4618..c033d7a 100644 --- a/foundry_test/modules/utils/L2CompressorHuffReadFlag.t.sol +++ b/foundry_test/modules/utils/L2CompressorHuffReadFlag.t.sol @@ -9,6 +9,8 @@ import "forge-std/console2.sol"; import { HuffConfig } from "foundry-huff/HuffConfig.sol"; import { HuffDeployer } from "foundry-huff/HuffDeployer.sol"; +import "contracts/modules/commons/interfaces/IModuleCalls.sol"; + import "./L2CompressorEncoder.sol"; uint256 constant FMS = 0xa0; @@ -999,7 +1001,7 @@ contract L2CompressorHuffReadFlagTests is AdvTest { } function test_read_pow_10_and_mul(uint256 _exp, uint8 _factor) external { - _exp = bound(_exp, 0, 77); + _exp = bound(_exp, 1, 77); // First bit means we aren't going to multiply it after bytes memory encoded = abi.encodePacked(uint8(0x00), uint8(_exp), uint8(_factor)); @@ -1015,4 +1017,39 @@ contract L2CompressorHuffReadFlagTests is AdvTest { assertEq(res, abi.encode(uint256(10 ** _exp) * uint256(_factor))); } } + + function test_read_self_execute() external { + // vm.assume(_txs.length != 0 && _txs.length <= type(uint8).max); + + IModuleCalls.Transaction[] memory _txs = new IModuleCalls.Transaction[](1); + + bytes memory encoded = abi.encodePacked( + uint8(0x00), uint8(0x00), + uint8(_txs.length) + ); + + for (uint256 i = 0; i < _txs.length; i++) { + IModuleCalls.Transaction memory t = _txs[i]; + + encoded = abi.encodePacked( + encoded, + build_flag(t.delegateCall, t.revertOnError, t.gasLimit != 0, t.value != 0, t.data.length != 0), + t.gasLimit != 0 ? encodeWord(t.gasLimit) : bytes(""), + encode_raw_address(t.target), + t.value != 0 ? encodeWord(t.value) : bytes(""), + t.data.length != 0 ? encode_bytes_n(t.data) : bytes("") + ); + } + + (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, res.length + FMS); + + bytes memory solidityEncoded = abi.encodeWithSelector(IModuleCalls.selfExecute.selector, _txs); + assertEq(solidityEncoded, res); + } } diff --git a/src/L2Compressor.huff b/src/L2Compressor.huff index 10215c0..dfe2c81 100644 --- a/src/L2Compressor.huff +++ b/src/L2Compressor.huff @@ -87,7 +87,7 @@ } #define jumptable__packed FLAG_TABLE { - FLAG_READ_POWER_OF_10 // 0x00 + FLAG_READ_POWER_OF_10_MISC // 0x00 FLAG_READ_BYTES32_1_BYTES // 0x01 FLAG_READ_BYTES32_2_BYTES // 0x02 FLAG_READ_BYTES32_3_BYTES // 0x03 @@ -217,8 +217,8 @@ 0xf0 shr // [word >> 0xf0, windex, rindex + 1, jump_to] jump // [windex, rindex + 1, jump_to] - FLAG_READ_POWER_OF_10: - READ_POW_10() + FLAG_READ_POWER_OF_10_MISC: + READ_POW_10_AND_SELF_EXECUTE() end jump FLAG_READ_BYTES32_1_BYTES: READ_BYTES32(0xf8, 0x01) @@ -490,12 +490,29 @@ // output stack: // [windex, rindex] } -#define macro READ_POW_10() = takes (2) returns (2) { +#define macro READ_POW_10_AND_SELF_EXECUTE(nrfs) = takes (2) returns (2) { // input stack: [windex, rindex] swap1 // [rindex, windex] LOAD_DYNAMIC_SIZE(0x01, 0xf8) // [exp_word, rindex, windex] + // We didn't had any more pleace for READ_SELF_EXECUTE without expanding + // the jumptable! so it has to live here. Sorry about that. + // 10 ** 0 * N is more expensive than just reading 1 byte, + // so this wasn't useful anyway + + dup1 // [exp_word, exp_word, rindex, windex] + normal_flow jumpi // [exp_word, rindex, windex] + + // --- WARNING UGLY CODE --- + + pop // [rindex, windex] + swap1 // [windex, rindex] + READ_SELF_EXECUTE() // [windex, rindex] + end_pow_10 jump // [windex, rindex] + + normal_flow: + // The last bit determines if we will multiply this by // the next byte or not, this is fine as the maximum value that we // can represent in a word is only 10 ** 78 @@ -512,7 +529,8 @@ swap1 // [rindex, windex, not_use_mul] swap2 // [not_use_mul, windex, rindex] - no_mul jumpi // [windex, rindex] + end_pow_10 jumpi // [windex, rindex] + BACKREAD_SINGLE_VALUE() // [pow_result, windex, rindex] swap2 // [rindex, windex, pow_result] LOAD_DYNAMIC_SIZE(0x01, 0xf8) // [factor, rindex, windex, pow_result] @@ -524,7 +542,7 @@ 0x20 // [0x20, windex, rindex] add // [(0x20 + windex), rindex] - no_mul: // [windex, rindex] + end_pow_10: // [windex, rindex] // output stack: [windex, rindex] } @@ -1606,6 +1624,32 @@ end_data_if: } +#define macro READ_SELF_EXECUTE(nrfs) = takes (2) returns (2) { + // input stack: [windex, rindex] + + // The SELF execution function signature of Sequence is 0x61c2926c + + __RIGHTPAD(0x61c2926c) // [0x61c2926c, windex, rindex] + dup2 // [windex, 0x61c2926c, windex, rindex] + mstore // [windex, rindex] + 0x04 add // [windex, rindex] + + // We need to write a single 0x20, this marks the position + // of the list of transactions. It is always the same. + 0x20 // [0x20, windex, rindex] + dup1 // [0x20, 0x20, windex, rindex] + dup3 // [windex, 0x20, 0x20, windex, rindex] + mstore // [0x20, windex, rindex] + add // [(0x20 + windex), rindex] + + // Now we can just read the list of transactions + // the macro handles all internal pointers + + READ_TRANSACTIONS() // [windex, rindex] + + // output stack: [windex, rindex] +} + #define macro READ_ABI_4_BYTES() = takes (2) returns (2) { // input stack: [windex, rindex]