Skip to content

Commit

Permalink
RLP encode legacy transactions without to address (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranbt authored Jan 5, 2024
1 parent ed5306e commit 2485457
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
15 changes: 13 additions & 2 deletions src/Transactions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ library Transactions {
items[0] = RLPWriter.writeUint(txStruct.nonce);
items[1] = RLPWriter.writeUint(txStruct.gasPrice);
items[2] = RLPWriter.writeUint(txStruct.gas);
items[3] = RLPWriter.writeAddress(txStruct.to);

if (txStruct.to == address(0)) {
items[3] = RLPWriter.writeBytes(bytes(""));
} else {
items[3] = RLPWriter.writeAddress(txStruct.to);
}
items[4] = RLPWriter.writeUint(txStruct.value);
items[5] = RLPWriter.writeBytes(txStruct.data);
items[6] = RLPWriter.writeBytes(txStruct.v);
Expand All @@ -47,7 +52,13 @@ library Transactions {
txStruct.nonce = uint64(ls[0].toUint());
txStruct.gasPrice = uint64(ls[1].toUint());
txStruct.gas = uint64(ls[2].toUint());
txStruct.to = ls[3].toAddress();

if (ls[3].toRlpBytes().length == 1) {
txStruct.to = address(0);
} else {
txStruct.to = ls[3].toAddress();
}

txStruct.value = uint64(ls[4].toUint());
txStruct.data = ls[5].toBytes();
txStruct.v = ls[6].toBytes();
Expand Down
31 changes: 26 additions & 5 deletions test/Transactions.sol → test/Transactions.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ contract TestTransactions is Test {
using Transactions for *;

function testLegacyTransactionRLPEncoding() public {
Transactions.Legacy memory legacyTxn0 = Transactions.Legacy({
Transactions.Legacy memory txnWithToAddress = Transactions.Legacy({
to: address(0x095E7BAea6a6c7c4c2DfeB977eFac326aF552d87),
gas: 50000,
gasPrice: 10,
Expand All @@ -21,17 +21,38 @@ contract TestTransactions is Test {
s: abi.encodePacked(hex"8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1")
});

bytes memory rlp = Transactions.encodeRLP(legacyTxn0);

bytes memory expected = abi.encodePacked(
hex"f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1"
);
assertEq0(rlp, expected);
_testLegacyTransaction(txnWithToAddress, expected);

Transactions.Legacy memory txnWithoutToAddress = Transactions.Legacy({
to: address(0),
gas: 50000,
gasPrice: 10,
value: 10,
nonce: 1,
data: abi.encodePacked(hex"02"),
chainId: 0,
v: abi.encodePacked(hex"1b"),
r: abi.encodePacked(hex"754a33a9c37cfcf61cd61939fd93f5fe194b7d1ee6ef07490e8c880f3bd0d87d"),
s: abi.encodePacked(hex"715bd50fa2c24e2ce0ea595025a44a39ac238558882f9f07dd885ddc51839419")
});

expected = abi.encodePacked(
hex"f84b010a82c350800a021ba0754a33a9c37cfcf61cd61939fd93f5fe194b7d1ee6ef07490e8c880f3bd0d87da0715bd50fa2c24e2ce0ea595025a44a39ac238558882f9f07dd885ddc51839419"
);
_testLegacyTransaction(txnWithoutToAddress, expected);
}

function _testLegacyTransaction(Transactions.Legacy memory legacyTxn, bytes memory expectedRlp) public {
bytes memory rlp = Transactions.encodeRLP(legacyTxn);
assertEq0(rlp, expectedRlp);

Transactions.Legacy memory legacyTxn1 = Transactions.decodeRLP(rlp);

// re-encode to validate that the decoding was correct
bytes memory rlp1 = Transactions.encodeRLP(legacyTxn1);
assertEq0(rlp1, expected);
assertEq0(rlp1, expectedRlp);
}
}

0 comments on commit 2485457

Please sign in to comment.