Skip to content

Commit

Permalink
Read transaction initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Agusx1211 committed Jan 18, 2024
1 parent 61b4280 commit 052e918
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 1 deletion.
2 changes: 1 addition & 1 deletion foundry_test/modules/utils/L2CompressorHuffReadFlag.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { HuffDeployer } from "foundry-huff/HuffDeployer.sol";

uint256 constant FMS = 0xa0;

contract L2CompressorHuffTests is AdvTest {
contract L2CompressorHuffReadFlagTests is AdvTest {
address public imp;

function setUp() public {
Expand Down
36 changes: 36 additions & 0 deletions foundry_test/modules/utils/L2CompressorHuffReadTx.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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";

uint256 constant FMS = 0xa0;

contract L2CompressorHuffReadTxTests is AdvTest {
address public imp;

function setUp() public {
imp = address(
HuffDeployer
.config()
.with_evm_version("paris")
.deploy("imps/L2CompressorReadTx")
);
}

function test_read_simple_transaction(bytes32 _data) external {
(bool s, bytes memory r) = imp.staticcall(
abi.encodePacked(uint8(0xc0), uint8(0x14), address(0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E))
);

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

console.logBytes(res);
}
}
144 changes: 144 additions & 0 deletions src/L2Compressor.huff
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,150 @@
0x03 eq ASSERT() // []
}

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

// The first byte gives us information about what the transaction contains

dup2 // [rindex, windex, rindex]
calldataload // [cdata[rindex], windex, rindex]
0x00 byte // [tflag, windex, rindex]
swap2 // [rindex, windex, tflag]
0x01 add // [rindex + 1, windex, tflag]
swap2 // [tflag, windex, rindex + 1]

// First bit of the flag determines if the transaction uses delegateCall

dup1 // [tflag, tflag, windex, rindex]
0x07 shr // [tflag >> 0x07, tflag, windex, rindex]
dup3 // [windex, tflag >> 0x07, tflag, windex, rindex]
mstore // [tflag, windex, rindex]

swap1 // [windex, tflag, rindex]
0x20 add // [windex + 0x20, tflag, rindex]

// Second bit of the flag determines if the transaction uses revertOnError

dup2 // [tflag, windex, tflag, rindex]
0x06 shr // [tflag >> 0x06, windex, tflag, rindex]
0x01 and // [tflag >> 0x06 & 0x01, windex, tflag, rindex]
dup3 // [windex, tflag >> 0x06 & 0x01, windex, tflag, rindex]
mstore // [windex, tflag, rindex]

0x20 add // [windex + 0x20, tflag, rindex]

// Third bit of the flag determines if the transaction has a defined gasLimit

dup2 // [tflag, windex, tflag, rindex]
0x05 shr // [tflag >> 0x05, windex, tflag, rindex]
0x01 and // [has_gas_limit, windex, tflag, rindex]
has_gas_limit jumpi // [windex, tflag, rindex]

// The transaction has no gas_limit, we still need to write 0s
// to the memory and push the write index

0x00 dup2 mstore // [windex, tflag, rindex]
0x20 add // [windex + 0x20, tflag, rindex]

// Re-arrange the stack so it matches the other branch

swap1 // [tflag, windex, rindex]
swap2 // [rindex, windex, tflag]
swap1 // [windex, rindex, tflag]

end_gas_Limit_if jump

has_gas_limit:

// Read advanced; this should only increase 32 bytes
// but we don't check that, buyer beware

swap1 // [tflag, windex, rindex]
swap2 // [rindex, windex, tflag]
swap1 // [windex, rindex, tflag]

READ_FLAG() // [windex, rindex, tflag]

end_gas_Limit_if:

// All transactions must define an address
// this is simple, as it is just one more flag

READ_FLAG()

// 4th bit of the flag determines if the transaction has a defined value

dup3 // [tflag, windex, rindex, tflag]
0x04 shr // [tflag >> 0x04, windex, rindex, tflag]
0x01 and // [tflag >> 0x04 & 0x01, windex, rindex, tflag]
has_value jumpi // [windex, rindex, tflag]

// The transaction has no value, we still need to write 0s
// to the memory and push the write index

0x00 dup2 mstore // [windex, rindex, tflag]
0x20 add // [windex + 0x20, rindex, tflag]
end_value_if jump

has_value:

// Read advanced; this should only increase 32 bytes
// but we don't check that, buyer beware

READ_FLAG() // [windex, rindex, tflag]

end_value_if:

// 1st bit determines if the transaction has data

swap2 // [tflag, rindex, windex]
0x01 and // [has_data, rindex, windex]

swap1 // [rindex, has_data, windex]
swap2 // [windex, has_data, rindex]
swap1 // [has_data, windex, rindex]

has_data jumpi // [windex, rindex]

// The transaction has no data, we still need to write 0s
// both for the pointer and size

dup1 // [windex, windex, rindex]
0x20 add // [windex + 0x20, windex, rindex]
dup1 // [windex + 0x20, windex + 0x20, windex, rindex]
swap2 // [windex, windex + 0x20, windex + 0x20, rindex]
mstore // [windex + 0x20, rindex]
0x00 // [0x00, windex + 0x20, rindex]
dup2 // [windex + 0x20, 0x00, windex + 0x20, rindex]
mstore // [windex + 0x20, rindex]
0x20 add // [windex + 0x40, rindex]

end_data_if jump

has_data: // [windex, rindex]

swap1 // [rindex, windex]
dup2 // [windex, rindex, prev_windex]

// Leave some room to store the size of the data
0x20 add // [windex + 0x20, rindex, prev_windex]

READ_FLAG() // [windex, rindex, prev_windex]

dup3 // [prev_windex, windex, rindex, prev_windex]
dup2 // [windex, prev_windex, windex, rindex, prev_windex]
sub // [(windex - prev_windex), windex, rindex, prev_windex]
0x20 add // [size, windex, rindex, prev_windex]

dup4 // [prev_windex, size, windex, rindex, prev_windex]
mstore // [windex, rindex, prev_windex]
swap2 // [prev_windex, rindex, windex]
pop // [rindex, windex]
swap1 // [windex, rindex]

end_data_if:
}

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

Expand Down
30 changes: 30 additions & 0 deletions src/imps/L2CompressorReadTx.huff
Original file line number Diff line number Diff line change
@@ -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_TRANSACTION() // [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
}

0 comments on commit 052e918

Please sign in to comment.