-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(protocol): fix LibTrieProof.verifyMerkleProof by RLP-encoding the…
… byte32 value first (#16018)
- Loading branch information
Showing
4 changed files
with
213 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
163 changes: 163 additions & 0 deletions
163
packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
/// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode | ||
/// @title RLPWriter | ||
/// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's | ||
/// RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor | ||
/// modifications to improve legibility. | ||
library RLPWriter { | ||
/// @notice RLP encodes a byte string. | ||
/// @param _in The byte string to encode. | ||
/// @return out_ The RLP encoded string in bytes. | ||
function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) { | ||
if (_in.length == 1 && uint8(_in[0]) < 128) { | ||
out_ = _in; | ||
} else { | ||
out_ = abi.encodePacked(_writeLength(_in.length, 128), _in); | ||
} | ||
} | ||
|
||
/// @notice RLP encodes a list of RLP encoded byte byte strings. | ||
/// @param _in The list of RLP encoded byte strings. | ||
/// @return list_ The RLP encoded list of items in bytes. | ||
function writeList(bytes[] memory _in) internal pure returns (bytes memory list_) { | ||
list_ = _flatten(_in); | ||
list_ = abi.encodePacked(_writeLength(list_.length, 192), list_); | ||
} | ||
|
||
/// @notice RLP encodes a string. | ||
/// @param _in The string to encode. | ||
/// @return out_ The RLP encoded string in bytes. | ||
function writeString(string memory _in) internal pure returns (bytes memory out_) { | ||
out_ = writeBytes(bytes(_in)); | ||
} | ||
|
||
/// @notice RLP encodes an address. | ||
/// @param _in The address to encode. | ||
/// @return out_ The RLP encoded address in bytes. | ||
function writeAddress(address _in) internal pure returns (bytes memory out_) { | ||
out_ = writeBytes(abi.encodePacked(_in)); | ||
} | ||
|
||
/// @notice RLP encodes a uint. | ||
/// @param _in The uint256 to encode. | ||
/// @return out_ The RLP encoded uint256 in bytes. | ||
function writeUint(uint256 _in) internal pure returns (bytes memory out_) { | ||
out_ = writeBytes(_toBinary(_in)); | ||
} | ||
|
||
/// @notice RLP encodes a bool. | ||
/// @param _in The bool to encode. | ||
/// @return out_ The RLP encoded bool in bytes. | ||
function writeBool(bool _in) internal pure returns (bytes memory out_) { | ||
out_ = new bytes(1); | ||
out_[0] = (_in ? bytes1(0x01) : bytes1(0x80)); | ||
} | ||
|
||
/// @notice Encode the first byte and then the `len` in binary form if `length` is more than 55. | ||
/// @param _len The length of the string or the payload. | ||
/// @param _offset 128 if item is string, 192 if item is list. | ||
/// @return out_ RLP encoded bytes. | ||
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) { | ||
if (_len < 56) { | ||
out_ = new bytes(1); | ||
out_[0] = bytes1(uint8(_len) + uint8(_offset)); | ||
} else { | ||
uint256 lenLen; | ||
uint256 i = 1; | ||
while (_len / i != 0) { | ||
lenLen++; | ||
i *= 256; | ||
} | ||
|
||
out_ = new bytes(lenLen + 1); | ||
out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55); | ||
for (i = 1; i <= lenLen; i++) { | ||
out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256)); | ||
} | ||
} | ||
} | ||
|
||
/// @notice Encode integer in big endian binary form with no leading zeroes. | ||
/// @param _x The integer to encode. | ||
/// @return out_ RLP encoded bytes. | ||
function _toBinary(uint256 _x) private pure returns (bytes memory out_) { | ||
bytes memory b = abi.encodePacked(_x); | ||
|
||
uint256 i = 0; | ||
for (; i < 32; i++) { | ||
if (b[i] != 0) { | ||
break; | ||
} | ||
} | ||
|
||
out_ = new bytes(32 - i); | ||
for (uint256 j = 0; j < out_.length; j++) { | ||
out_[j] = b[i++]; | ||
} | ||
} | ||
|
||
/// @custom:attribution https://github.com/Arachnid/solidity-stringutils | ||
/// @notice Copies a piece of memory to another location. | ||
/// @param _dest Destination location. | ||
/// @param _src Source location. | ||
/// @param _len Length of memory to copy. | ||
function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure { | ||
uint256 dest = _dest; | ||
uint256 src = _src; | ||
uint256 len = _len; | ||
|
||
for (; len >= 32; len -= 32) { | ||
assembly { | ||
mstore(dest, mload(src)) | ||
} | ||
dest += 32; | ||
src += 32; | ||
} | ||
|
||
uint256 mask; | ||
unchecked { | ||
mask = 256 ** (32 - len) - 1; | ||
} | ||
assembly { | ||
let srcpart := and(mload(src), not(mask)) | ||
let destpart := and(mload(dest), mask) | ||
mstore(dest, or(destpart, srcpart)) | ||
} | ||
} | ||
|
||
/// @custom:attribution https://github.com/sammayo/solidity-rlp-encoder | ||
/// @notice Flattens a list of byte strings into one byte string. | ||
/// @param _list List of byte strings to flatten. | ||
/// @return out_ The flattened byte string. | ||
function _flatten(bytes[] memory _list) private pure returns (bytes memory out_) { | ||
if (_list.length == 0) { | ||
return new bytes(0); | ||
} | ||
|
||
uint256 len; | ||
uint256 i = 0; | ||
for (; i < _list.length; i++) { | ||
len += _list[i].length; | ||
} | ||
|
||
out_ = new bytes(len); | ||
uint256 flattenedPtr; | ||
assembly { | ||
flattenedPtr := add(out_, 0x20) | ||
} | ||
|
||
for (i = 0; i < _list.length; i++) { | ||
bytes memory item = _list[i]; | ||
|
||
uint256 listPtr; | ||
assembly { | ||
listPtr := add(item, 0x20) | ||
} | ||
|
||
_memcpy(flattenedPtr, listPtr, item.length); | ||
flattenedPtr += _list[i].length; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters