diff --git a/foundry_test/modules/utils/L2CompressorHuffReadNonce.sol b/foundry_test/modules/utils/L2CompressorHuffReadNonce.sol new file mode 100644 index 0000000..2b2e46b --- /dev/null +++ b/foundry_test/modules/utils/L2CompressorHuffReadNonce.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "foundry_test/base/AdvTest.sol"; + +import "forge-std/console.sol"; +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"; + +uint256 constant FMS = 0xa0; + +import "./L2CompressorEncoder.sol"; + +contract L2CompressorHuffReadNonceTest is AdvTest { + address public imp; + + function setUp() public { + imp = address( + HuffDeployer + .config() + .with_evm_version("paris") + .deploy("imps/L2CompressorReadNonce") + ); + } + + function test_read_simple_nonce() external { + uint256 space = 76518466025766696338879503773554426820412884125; + uint256 nonce = 29095922913147819529123945996; + + bytes32 compact = 0x0d6734e95e00251b768924d47d52db3270fcc49d5e039555a5312d84eb305e0c; + + bytes memory encoded = abi.encodePacked( + encodeWord(space), encodeWord(nonce) + ); + + (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); + + assertEq(compact, abi.decode(res, (bytes32))); + } + + function test_read_nonce(uint160 _space, uint96 _nonce) external { + bytes memory encoded = abi.encodePacked( + encodeWord(_space), encodeWord(_nonce) + ); + + (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); + + assertEq(abi.encodePacked(_space, _nonce), res); + } +} diff --git a/src/L2Compressor.huff b/src/L2Compressor.huff index c5ba633..554868c 100644 --- a/src/L2Compressor.huff +++ b/src/L2Compressor.huff @@ -451,6 +451,46 @@ 0x03 eq ASSERT() // [] } +#define macro READ_NONCE_STANDALONE() = takes (2) returns (2) { + skip jump + rf: + READ_FLAG() + skip: + READ_NONCE(rf) +} + +#define macro READ_NONCE(nrfs) = takes (2) returns (2) { + // input stack: [windex, rindex] + + PERFORM_NESTED_READ_FLAG() // [windex, rindex] + BACKREAD_SINGLE_VALUE() // [val, windex, rindex] + + 0x60 shl // [space, windex, rindex] + + swap2 // [rindex, windex, space] + swap1 // [windex, rindex, space] + + PERFORM_NESTED_READ_FLAG() // [windex, rindex, space] + BACKREAD_SINGLE_VALUE() // [nonce, windex, rindex, space] + + // Assume that we are reading the nonce already masked + + swap1 // [windex, nonce, rindex, space] + swap2 // [rindex, nonce, windex, space] + swap3 // [space, nonce, windex, rindex] + or // [(space | nonce), windex, rindex] + + // Now we have the compact representation of the nonce + // we can write it to memory on windex + + dup2 // [windex, (space | nonce), windex, rindex] + mstore // [windex, rindex] + + 0x20 add // [windex + 0x20, rindex] + + // output stack: [windex, rindex] +} + #define macro READ_TRANSACTIONS_STANDALONE() = takes (2) returns (2) { skip jump rf: diff --git a/src/imps/L2CompressorReadNonce.huff b/src/imps/L2CompressorReadNonce.huff new file mode 100644 index 0000000..27541c5 --- /dev/null +++ b/src/imps/L2CompressorReadNonce.huff @@ -0,0 +1,30 @@ +#include "../L2Compressor.huff" + +#define constant FMS = 0xa0 + +// Function Dispatching +#define macro MAIN() = takes (1) returns (1) { + // readAdvanced with whatever calldata is passed + // first 32 bytes returns the new rindex and the next 32 bytes returns the new windex + + 0x00 // [rindex] + [FMS] // [windex, rindex] + + READ_NONCE_STANDALONE() // [windex, rindex] + + [FMS] // [0xa0, windex, rindex] + dup2 // [windex, 0xa0, windex, rindex] + sub // [len, windex, rindex] + + swap2 // [rindex, windex, len] + + 0x80 [FMS] sub mstore // [windex, len] + 0x60 [FMS] sub mstore // [len] + + 0x60 0x40 [FMS] sub mstore // [len] + dup1 0x20 [FMS] sub mstore // [len] + + 0x80 add // [len + 0x80] + + 0x80 [FMS] sub return +}