From 8ca85446ff730d4aaae4c77e46aceac894016a3e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 16 Aug 2023 10:50:36 +0530 Subject: [PATCH] fix: update solidity-rlp to v2.0.8 --- contracts/lib/RLPReader.sol | 89 ++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/contracts/lib/RLPReader.sol b/contracts/lib/RLPReader.sol index 939e351..70db5a5 100644 --- a/contracts/lib/RLPReader.sol +++ b/contracts/lib/RLPReader.sol @@ -4,8 +4,7 @@ * @author Hamdi Allam hamdi.allam97@gmail.com * Please reach out with any questions or concerns */ - -pragma solidity ^0.8.0; +pragma solidity >=0.5.10 <0.9.0; library RLPReader { uint8 constant STRING_SHORT_START = 0x80; @@ -74,21 +73,33 @@ library RLPReader { } /* - * @param item RLP encoded bytes + * @param the RLP item. */ function rlpLen(RLPItem memory item) internal pure returns (uint256) { return item.len; } /* - * @param item RLP encoded bytes + * @param the RLP item. + * @return (memPtr, len) pair: location of the item's payload in memory. + */ + function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { + uint256 offset = _payloadOffset(item.memPtr); + uint256 memPtr = item.memPtr + offset; + uint256 len = item.len - offset; // data length + return (memPtr, len); + } + + /* + * @param the RLP item. */ function payloadLen(RLPItem memory item) internal pure returns (uint256) { - return item.len - _payloadOffset(item.memPtr); + (, uint256 len) = payloadLocation(item); + return len; } /* - * @param item RLP encoded list in bytes + * @param the RLP item containing the encoded list. */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); @@ -135,13 +146,6 @@ library RLPReader { return result; } - function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { - uint256 offset = _payloadOffset(item.memPtr); - uint256 memPtr = item.memPtr + offset; - uint256 len = item.len - offset; // data length - return (memPtr, len); - } - /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. @@ -171,7 +175,7 @@ library RLPReader { return result; } - // any non-zero byte < 128 is considered true + // any non-zero byte except "0x80" is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint256 result; @@ -180,7 +184,15 @@ library RLPReader { result := byte(0, mload(memPtr)) } - return result == 0 ? false : true; + // SEE Github Issue #5. + // Summary: Most commonly used RLP libraries (i.e Geth) will encode + // "0" as "0x80" instead of as "0". We handle this edge case explicitly + // here. + if (result == 0 || result == STRING_SHORT_START) { + return false; + } else { + return true; + } } function toAddress(RLPItem memory item) internal pure returns (address) { @@ -193,11 +205,9 @@ library RLPReader { function toUint(RLPItem memory item) internal pure returns (uint256) { require(item.len > 0 && item.len <= 33); - uint256 offset = _payloadOffset(item.memPtr); - uint256 len = item.len - offset; + (uint256 memPtr, uint256 len) = payloadLocation(item); uint256 result; - uint256 memPtr = item.memPtr + offset; assembly { result := mload(memPtr) @@ -227,8 +237,7 @@ library RLPReader { function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); - uint256 offset = _payloadOffset(item.memPtr); - uint256 len = item.len - offset; // data length + (uint256 memPtr, uint256 len) = payloadLocation(item); bytes memory result = new bytes(len); uint256 destPtr; @@ -236,7 +245,7 @@ library RLPReader { destPtr := add(0x20, result) } - copy(item.memPtr + offset, destPtr, len); + copy(memPtr, destPtr, len); return result; } @@ -267,12 +276,15 @@ library RLPReader { byte0 := byte(0, mload(memPtr)) } - if (byte0 < STRING_SHORT_START) itemLen = 1; - else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; - else if (byte0 < LIST_SHORT_START) { + if (byte0 < STRING_SHORT_START) { + itemLen = 1; + } else if (byte0 < STRING_LONG_START) { + itemLen = byte0 - STRING_SHORT_START + 1; + } else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte + /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) @@ -299,12 +311,16 @@ library RLPReader { byte0 := byte(0, mload(memPtr)) } - if (byte0 < STRING_SHORT_START) return 0; - else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; - else if (byte0 < LIST_SHORT_START) + if (byte0 < STRING_SHORT_START) { + return 0; + } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) { + return 1; + } else if (byte0 < LIST_SHORT_START) { // being explicit return byte0 - (STRING_LONG_START - 1) + 1; - else return byte0 - (LIST_LONG_START - 1) + 1; + } else { + return byte0 - (LIST_LONG_START - 1) + 1; + } } /* @@ -325,15 +341,14 @@ library RLPReader { dest += WORD_SIZE; } - if (len == 0) return; - - // left over bytes. Mask is used to remove unwanted bytes from the word - uint256 mask = 256 ** (WORD_SIZE - len) - 1; - - assembly { - let srcpart := and(mload(src), not(mask)) // zero out src - let destpart := and(mload(dest), mask) // retrieve the bytes - mstore(dest, or(destpart, srcpart)) + if (len > 0) { + // left over bytes. Mask is used to remove unwanted bytes from the word + uint256 mask = 256 ** (WORD_SIZE - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) // zero out src + let destpart := and(mload(dest), mask) // retrieve the bytes + mstore(dest, or(destpart, srcpart)) + } } } }