Skip to content
Merged
Changes from 4 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5800339
fix L-03
luiz-lvj Nov 13, 2025
47c8048
fix N-06
luiz-lvj Nov 13, 2025
78f643d
fix N-07
luiz-lvj Nov 13, 2025
55b33a0
fix N-09
luiz-lvj Nov 13, 2025
e0a6e6b
add changeset
luiz-lvj Nov 13, 2025
f437257
Test encoding of addresses with leading zeros
Amxx Nov 13, 2025
0ac8a92
Merge branch 'testing/rlp-encoding-addresses' into audit-fixes/RLP
Amxx Nov 13, 2025
60b70b7
Update test/utils/RLP.test.js
Amxx Nov 14, 2025
6a86e31
add fuzzing test
Amxx Nov 14, 2025
08d217f
Merge branch 'testing/rlp-encoding-addresses' of https://github.com/A…
Amxx Nov 14, 2025
5f11e08
Merge branch 'testing/rlp-encoding-addresses' into audit-fixes/RLP
Amxx Nov 14, 2025
1992bed
revert back to address
luiz-lvj Nov 14, 2025
be65eb8
remove changeset
luiz-lvj Nov 14, 2025
8f2dd16
update changeset
luiz-lvj Nov 14, 2025
61b695f
Solve: Inconsistent Integer Base in Inline Assembly When Setting RLP …
luiz-lvj Nov 14, 2025
fe917b7
test string qith leading zeros
luiz-lvj Nov 14, 2025
3cea1c4
Delete .changeset/slow-lemons-rest.md
ernestognw Nov 24, 2025
2088e8e
Merge branch 'master' into audit-fixes/RLP
ernestognw Nov 24, 2025
e27858d
Update numeric literals for guidelines consistency
ernestognw Nov 24, 2025
dd70a70
Update numeric literals for guidelines consistency
luiz-lvj Nov 25, 2025
88d7ab3
Merge branch 'master' into audit-fixes/RLP
luiz-lvj Nov 25, 2025
9116839
Merge branch 'master' into audit-fixes/RLP
luiz-lvj Nov 27, 2025
f31d743
Merge branch 'master' into audit-fixes/RLP
luiz-lvj Dec 1, 2025
b1899ae
Merge branch 'master' into audit-fixes/RLP
luiz-lvj Dec 1, 2025
6cb5180
Improve NatSpec around canonical and non-canonical representations. A…
ernestognw Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions contracts/utils/RLP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,11 @@ library RLP {
}
}

/// @dev Encode an address as RLP.
/// @dev Encode an address as RLP. The address is encoded as an uint256 to avoid leading zeros.
function encode(address input) internal pure returns (bytes memory result) {
assembly ("memory-safe") {
result := mload(0x40)
mstore(result, 0x15) // length of the encoded data: 1 (prefix) + 0x14 (address)
mstore(add(result, 0x20), or(shl(248, 0x94), shl(88, input))) // prefix (0x94 = SHORT_OFFSET + 0x14) + input
mstore(0x40, add(result, 0x35)) // reserve memory
}
Comment on lines 126 to 131
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This encoding is not consistent with how the ethereum ecosystem does things.

If you try to use ethers.js to do encode an address that had zeros, you'll get them encoded

> ethers.encodeRlp(ethers.ZeroAddress);
'0x940000000000000000000000000000000000000000'

Note that this difference is important in the context of operations like getCreateAddress. If the address prefix zeros are removed, you'd get an invalid address prediction.

I'll add unit tests to show these issues.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned to the auditors that it makes sense to include leading zeroes in addresses because there's no definition of an address in RLP. My thinking about this is that leading zeroes in an address are not necessarily "leading" because they constitute relevant information for the address.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking about this is that leading zeroes in an address are not necessarily "leading" because they constitute relevant information for the address.

I agree with that!

uint256 inputAsScalar = uint256(uint160(input));

return encode(inputAsScalar);
}

/// @dev Encode a uint256 as RLP.
Expand Down Expand Up @@ -167,13 +164,17 @@ library RLP {
return encode(bytes(input));
}

/// @dev Encode an array of bytes as RLP.
/**
* @dev Encode an array of bytes as RLP.
* This function expects an array of already encoded bytes, not raw bytes.
* Users should call {encode} on each element of the array before calling it.
*/
function encode(bytes[] memory input) internal pure returns (bytes memory) {
return _encode(input.concat(), LONG_OFFSET);
}

/// @dev Encode an encoder (list of bytes) as RLP
function encode(Encoder memory self) internal pure returns (bytes memory result) {
function encode(Encoder memory self) internal pure returns (bytes memory) {
return _encode(self.acc.flatten(), LONG_OFFSET);
}

Expand Down Expand Up @@ -215,8 +216,6 @@ library RLP {

/// @dev Decode an RLP encoded address. See {encode-address}
function readAddress(Memory.Slice item) internal pure returns (address) {
uint256 length = item.length();
require(length == 1 || length == 21, RLPInvalidEncoding());
return address(uint160(readUint256(item)));
}

Expand All @@ -241,7 +240,7 @@ library RLP {
(uint256 offset, uint256 length, ItemType itemType) = _decodeLength(item);
require(itemType == ItemType.Data, RLPInvalidEncoding());

// Length is checked by {toBytes}
// Length is checked by {slice}
return item.slice(offset, length).toBytes();
}

Expand Down Expand Up @@ -326,9 +325,7 @@ library RLP {
* @dev Decodes an RLP `item`'s `length and type from its prefix.
* Returns the offset, length, and type of the RLP item based on the encoding rules.
*/
function _decodeLength(
Memory.Slice item
) private pure returns (uint256 _offset, uint256 _length, ItemType _itemtype) {
function _decodeLength(Memory.Slice item) private pure returns (uint256, uint256, ItemType) {
uint256 itemLength = item.length();

require(itemLength != 0, RLPInvalidEncoding());
Expand Down
Loading