From 514a766d3d0850f006a59e824d10f023dcb961f1 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 14:40:00 +0000 Subject: [PATCH 1/7] FixedBytesLib --- src/utils/FixedBytesLib.sol | 359 ++++++++++++++++++++++++++++++++++++ src/utils/LibRLP.sol | 52 +++--- test/Lifebuoy.t.sol | 18 +- 3 files changed, 393 insertions(+), 36 deletions(-) create mode 100644 src/utils/FixedBytesLib.sol diff --git a/src/utils/FixedBytesLib.sol b/src/utils/FixedBytesLib.sol new file mode 100644 index 0000000000..3a069ac8eb --- /dev/null +++ b/src/utils/FixedBytesLib.sol @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @notice Library for bytes1 to bytes32. +/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedBytesLib.sol) +/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedBytesLib.sol) +library FixedBytesLib { + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes1 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 1) + mstore(add(result, 0x20), shl(248, shr(248, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes2 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 2) + mstore(add(result, 0x20), shl(240, shr(240, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes3 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 3) + mstore(add(result, 0x20), shl(232, shr(232, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes4 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 4) + mstore(add(result, 0x20), shl(224, shr(224, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes5 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 5) + mstore(add(result, 0x20), shl(216, shr(216, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes6 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 6) + mstore(add(result, 0x20), shl(208, shr(208, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes7 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 7) + mstore(add(result, 0x20), shl(200, shr(200, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes8 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 8) + mstore(add(result, 0x20), shl(192, shr(192, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes9 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 9) + mstore(add(result, 0x20), shl(184, shr(184, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes10 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 10) + mstore(add(result, 0x20), shl(176, shr(176, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes11 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 11) + mstore(add(result, 0x20), shl(168, shr(168, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes12 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 12) + mstore(add(result, 0x20), shl(160, shr(160, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes13 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 13) + mstore(add(result, 0x20), shl(152, shr(152, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes14 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 14) + mstore(add(result, 0x20), shl(144, shr(144, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes15 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 15) + mstore(add(result, 0x20), shl(136, shr(136, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes16 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 16) + mstore(add(result, 0x20), shl(128, shr(128, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes17 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 17) + mstore(add(result, 0x20), shl(120, shr(120, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes18 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 18) + mstore(add(result, 0x20), shl(112, shr(112, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes19 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 19) + mstore(add(result, 0x20), shl(104, shr(104, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes20 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 20) + mstore(add(result, 0x20), shl(96, shr(96, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes21 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 21) + mstore(add(result, 0x20), shl(88, shr(88, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes22 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 22) + mstore(add(result, 0x20), shl(80, shr(80, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes23 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 23) + mstore(add(result, 0x20), shl(72, shr(72, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes24 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 24) + mstore(add(result, 0x20), shl(64, shr(64, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes25 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 25) + mstore(add(result, 0x20), shl(56, shr(56, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes26 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 26) + mstore(add(result, 0x20), shl(48, shr(48, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes27 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 27) + mstore(add(result, 0x20), shl(40, shr(40, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes28 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 28) + mstore(add(result, 0x20), shl(32, shr(32, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes29 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 29) + mstore(add(result, 0x20), shl(24, shr(24, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes30 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 30) + mstore(add(result, 0x20), shl(16, shr(16, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes31 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 31) + mstore(add(result, 0x20), shl(8, shr(8, x))) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns `abi.encodePacked(x)`, but more efficiently. + function toBytes(bytes32 x) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + mstore(result, 32) + mstore(add(result, 0x20), shl(0, shr(0, x))) + mstore(0x40, add(result, 0x40)) + } + } +} diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol index d89d048996..782dea17ae 100644 --- a/src/utils/LibRLP.sol +++ b/src/utils/LibRLP.sol @@ -125,13 +125,10 @@ library LibRLP { /// @dev Appends `x` to `list`. Returns `list` for function chaining. function p(List memory list, uint256 x) internal pure returns (List memory result) { + result._data = x << 48; + _updateTail(list, result); /// @solidity memory-safe-assembly assembly { - mstore(result, shl(48, x)) - let v := or(shr(mload(list), result), mload(list)) - let tail := shr(40, v) - mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail. - mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`. // If `x` is too big, we cannot pack it inline with the node. // We'll have to allocate a new slot for `x` and store the pointer to it in the node. if shr(208, x) { @@ -140,8 +137,8 @@ library LibRLP { mstore(0x40, add(m, 0x20)) mstore(result, shl(40, or(1, shl(8, m)))) } - result := list } + result = list; } /// @dev Appends `x` to `list`. Returns `list` for function chaining. @@ -149,12 +146,9 @@ library LibRLP { /// @solidity memory-safe-assembly assembly { mstore(result, shl(40, or(4, shl(8, x)))) - let v := or(shr(mload(list), result), mload(list)) - let tail := shr(40, v) - mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail. - mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`. - result := list } + _updateTail(list, result); + result = list; } /// @dev Appends `x` to `list`. Returns `list` for function chaining. @@ -162,12 +156,9 @@ library LibRLP { /// @solidity memory-safe-assembly assembly { mstore(result, shl(48, iszero(iszero(x)))) - let v := or(shr(mload(list), result), mload(list)) - let tail := shr(40, v) - mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail. - mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`. - result := list } + _updateTail(list, result); + result = list; } /// @dev Appends `x` to `list`. Returns `list` for function chaining. @@ -175,12 +166,9 @@ library LibRLP { /// @solidity memory-safe-assembly assembly { mstore(result, shl(40, or(2, shl(8, x)))) - let v := or(shr(mload(list), result), mload(list)) - let tail := shr(40, v) - mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail. - mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`. - result := list } + _updateTail(list, result); + result = list; } /// @dev Appends `x` to `list`. Returns `list` for function chaining. @@ -188,12 +176,9 @@ library LibRLP { /// @solidity memory-safe-assembly assembly { mstore(result, shl(40, or(3, shl(8, x)))) - let v := or(shr(mload(list), result), mload(list)) - let tail := shr(40, v) - mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail. - mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`. - result := list } + _updateTail(list, result); + result = list; } /// @dev Returns the RLP encoding of `list`. @@ -377,4 +362,19 @@ library LibRLP { } } } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PRIVATE HELPERS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /// @dev Updates the tail in `list`. + function _updateTail(List memory list, List memory result) private pure { + /// @solidity memory-safe-assembly + assembly { + let v := or(shr(mload(list), result), mload(list)) + let tail := shr(40, v) + mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail. + mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`. + } + } } diff --git a/test/Lifebuoy.t.sol b/test/Lifebuoy.t.sol index b9b8f59f7a..24863c8dc5 100644 --- a/test/Lifebuoy.t.sol +++ b/test/Lifebuoy.t.sol @@ -38,7 +38,7 @@ contract LifebuoyTest is SoladyTest { } function _deployViaCreate(address deployer, bytes memory initcode) internal returns (address) { - (bool success, bytes memory result) = deployer.call(type(MockERC721).creationCode); + (bool success, bytes memory result) = deployer.call(initcode); assertTrue(success); return abi.decode(result, (address)); } @@ -50,24 +50,22 @@ contract LifebuoyTest is SoladyTest { vm.etch(deployer, hex"3d3d363d3d37363d34f09052602081f3"); for (uint256 i; i != 3; ++i) { r = r >> 32; + address expected; if (r & 31 == 0) { - address expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); - address deployed = _deployViaCreate(deployer, type(MockERC721).creationCode); - assertEq(deployed, expected); + expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); + assertEq(_deployViaCreate(deployer, type(MockERC721).creationCode), expected); continue; } r = r >> 8; if (r & 1 == 0) { - address expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); + expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); bytes memory initcode = type(MockLifebuoyOwned).creationCode; initcode = abi.encodePacked(initcode, owner); - address deployed = _deployViaCreate(deployer, initcode); - assertEq(deployed, expected); + assertEq(_deployViaCreate(deployer, initcode), expected); continue; } - address expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); - address deployed = _deployViaCreate(deployer, type(MockLifebuoy).creationCode); - assertEq(deployed, expected); + expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); + assertEq(_deployViaCreate(deployer, type(MockLifebuoy).creationCode), expected); } } From 68ce82c1b35049194f8f108ab905e56430009056 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 14:53:33 +0000 Subject: [PATCH 2/7] Add fixed bytes methods to LibRLP --- src/utils/FixedBytesLib.sol | 359 ------------------------------------ src/utils/LibRLP.sol | 19 ++ 2 files changed, 19 insertions(+), 359 deletions(-) delete mode 100644 src/utils/FixedBytesLib.sol diff --git a/src/utils/FixedBytesLib.sol b/src/utils/FixedBytesLib.sol deleted file mode 100644 index 3a069ac8eb..0000000000 --- a/src/utils/FixedBytesLib.sol +++ /dev/null @@ -1,359 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/// @notice Library for bytes1 to bytes32. -/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedBytesLib.sol) -/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedBytesLib.sol) -library FixedBytesLib { - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes1 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 1) - mstore(add(result, 0x20), shl(248, shr(248, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes2 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 2) - mstore(add(result, 0x20), shl(240, shr(240, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes3 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 3) - mstore(add(result, 0x20), shl(232, shr(232, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes4 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 4) - mstore(add(result, 0x20), shl(224, shr(224, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes5 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 5) - mstore(add(result, 0x20), shl(216, shr(216, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes6 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 6) - mstore(add(result, 0x20), shl(208, shr(208, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes7 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 7) - mstore(add(result, 0x20), shl(200, shr(200, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes8 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 8) - mstore(add(result, 0x20), shl(192, shr(192, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes9 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 9) - mstore(add(result, 0x20), shl(184, shr(184, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes10 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 10) - mstore(add(result, 0x20), shl(176, shr(176, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes11 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 11) - mstore(add(result, 0x20), shl(168, shr(168, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes12 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 12) - mstore(add(result, 0x20), shl(160, shr(160, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes13 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 13) - mstore(add(result, 0x20), shl(152, shr(152, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes14 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 14) - mstore(add(result, 0x20), shl(144, shr(144, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes15 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 15) - mstore(add(result, 0x20), shl(136, shr(136, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes16 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 16) - mstore(add(result, 0x20), shl(128, shr(128, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes17 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 17) - mstore(add(result, 0x20), shl(120, shr(120, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes18 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 18) - mstore(add(result, 0x20), shl(112, shr(112, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes19 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 19) - mstore(add(result, 0x20), shl(104, shr(104, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes20 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 20) - mstore(add(result, 0x20), shl(96, shr(96, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes21 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 21) - mstore(add(result, 0x20), shl(88, shr(88, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes22 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 22) - mstore(add(result, 0x20), shl(80, shr(80, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes23 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 23) - mstore(add(result, 0x20), shl(72, shr(72, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes24 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 24) - mstore(add(result, 0x20), shl(64, shr(64, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes25 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 25) - mstore(add(result, 0x20), shl(56, shr(56, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes26 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 26) - mstore(add(result, 0x20), shl(48, shr(48, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes27 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 27) - mstore(add(result, 0x20), shl(40, shr(40, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes28 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 28) - mstore(add(result, 0x20), shl(32, shr(32, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes29 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 29) - mstore(add(result, 0x20), shl(24, shr(24, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes30 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 30) - mstore(add(result, 0x20), shl(16, shr(16, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes31 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 31) - mstore(add(result, 0x20), shl(8, shr(8, x))) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns `abi.encodePacked(x)`, but more efficiently. - function toBytes(bytes32 x) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - mstore(result, 32) - mstore(add(result, 0x20), shl(0, shr(0, x))) - mstore(0x40, add(result, 0x40)) - } - } -} diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol index 782dea17ae..7bbedf002b 100644 --- a/src/utils/LibRLP.sol +++ b/src/utils/LibRLP.sol @@ -118,6 +118,11 @@ library LibRLP { p(result, x); } + /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x, n)`. + function l(bytes32 x, uint256 n) internal pure returns (List memory result) { + p(result, x, n); + } + /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`. function l(List memory x) internal pure returns (List memory result) { p(result, x); @@ -171,6 +176,20 @@ library LibRLP { result = list; } + /// @dev Appends `x` as an `n` bytes string to `list`. Returns `list` for function chaining. + function p(List memory list, bytes32 x, uint256 n) internal pure returns (List memory result) { + /// @solidity memory-safe-assembly + assembly { + let m := mload(0x40) + mstore(m, n) + mstore(add(m, 0x20), x) + mstore(0x40, add(m, 0x40)) + mstore(result, shl(40, or(2, shl(8, x)))) + } + _updateTail(list, result); + result = list; + } + /// @dev Appends `x` to `list`. Returns `list` for function chaining. function p(List memory list, List memory x) internal pure returns (List memory result) { /// @solidity memory-safe-assembly From ec39b7093d99c564ace7766ebb7fff109a37182d Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 15:30:32 +0000 Subject: [PATCH 3/7] Screw it... the API is not beautiful... just use encodePacked --- src/utils/LibRLP.sol | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol index 7bbedf002b..782dea17ae 100644 --- a/src/utils/LibRLP.sol +++ b/src/utils/LibRLP.sol @@ -118,11 +118,6 @@ library LibRLP { p(result, x); } - /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x, n)`. - function l(bytes32 x, uint256 n) internal pure returns (List memory result) { - p(result, x, n); - } - /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`. function l(List memory x) internal pure returns (List memory result) { p(result, x); @@ -176,20 +171,6 @@ library LibRLP { result = list; } - /// @dev Appends `x` as an `n` bytes string to `list`. Returns `list` for function chaining. - function p(List memory list, bytes32 x, uint256 n) internal pure returns (List memory result) { - /// @solidity memory-safe-assembly - assembly { - let m := mload(0x40) - mstore(m, n) - mstore(add(m, 0x20), x) - mstore(0x40, add(m, 0x40)) - mstore(result, shl(40, or(2, shl(8, x)))) - } - _updateTail(list, result); - result = list; - } - /// @dev Appends `x` to `list`. Returns `list` for function chaining. function p(List memory list, List memory x) internal pure returns (List memory result) { /// @solidity memory-safe-assembly From 66fc09a9e7397e4efde373162790ab5455448344 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 15:34:58 +0000 Subject: [PATCH 4/7] Add comment --- src/utils/LibRLP.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol index 782dea17ae..3ef3c00732 100644 --- a/src/utils/LibRLP.sol +++ b/src/utils/LibRLP.sol @@ -94,6 +94,8 @@ library LibRLP { // - addresses are treated like byte strings of length 20, agnostic of leading zero bytes. // - uint256s are converted to byte strings, stripped of leading zero bytes, and encoded. // - bools are converted to uint256s (`b ? 1 : 0`), then encoded with the uint256. + // - For bytes1 to bytes32, you must manually convert them to bytes memory + // with `abi.encodePacked(x)` before encoding. /// @dev Returns a new empty list. function l() internal pure returns (List memory result) {} From 6f40758cd93d94a41708f4f51c5a99cfc0bf1881 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 15:35:46 +0000 Subject: [PATCH 5/7] T --- test/LibRLP.t.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/LibRLP.t.sol b/test/LibRLP.t.sol index 657b09979a..fd89946c71 100644 --- a/test/LibRLP.t.sol +++ b/test/LibRLP.t.sol @@ -47,7 +47,8 @@ contract LibRLPTest is SoladyTest { pure returns (address) { - return address(uint160(uint256(keccak256(LibRLP.l(deployer).p(nonce).encode())))); + return + address(uint160(uint256(keccak256(LibRLP.l(_brutalized(deployer)).p(nonce).encode())))); } function computeAddressOriginal(address deployer, uint256 nonce) From f2a9c108ee48c4931cb8e0e3873a7b4653ab96af Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 15:39:26 +0000 Subject: [PATCH 6/7] T --- test/LibRLP.t.sol | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/LibRLP.t.sol b/test/LibRLP.t.sol index fd89946c71..0a61e5e1de 100644 --- a/test/LibRLP.t.sol +++ b/test/LibRLP.t.sol @@ -47,8 +47,7 @@ contract LibRLPTest is SoladyTest { pure returns (address) { - return - address(uint160(uint256(keccak256(LibRLP.l(_brutalized(deployer)).p(nonce).encode())))); + return address(uint160(uint256(keccak256(LibRLP.l(deployer).p(nonce).encode())))); } function computeAddressOriginal(address deployer, uint256 nonce) @@ -247,6 +246,15 @@ contract LibRLPTest is SoladyTest { assertEq(LibRLP.encode(s), abi.encodePacked(hex"b9fffe", s)); } + function testRLPEncodeAddressViaList(address a0, address a1) public { + _maybeBzztMemory(); + bytes memory computed = LibRLP.l(_brutalized(a0)).p(_brutalized(a1)).encode(); + _checkMemory(computed); + _maybeBzztMemory(); + bytes memory expected = LibRLP.l(abi.encodePacked(a0)).p(abi.encodePacked(a1)).encode(); + assertEq(computed, expected); + } + function testRLPEncodeListDifferential(bytes memory x0, uint256 x1) public { _maybeBzztMemory(); LibRLP.List memory list = LibRLP.l(x0).p(x1).p(x1).p(x0); @@ -287,7 +295,7 @@ contract LibRLPTest is SoladyTest { function testRLPEncodeAddressDifferential(address x) public { _maybeBzztMemory(); - bytes memory computed = LibRLP.encode(x); + bytes memory computed = LibRLP.encode(_brutalized(x)); _checkAndMaybeBzztMemory(computed); bytes memory computed2 = _encode(x); _checkAndMaybeBzztMemory(computed2); From 76146de7ae6395085ed243c903dd68128b69fdc6 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 1 Jul 2024 15:44:06 +0000 Subject: [PATCH 7/7] T --- .gas-snapshot | 49 +++++++++++++++++++++++---------------------- test/Lifebuoy.t.sol | 17 ++++++++-------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 35ce343d44..333e32ccc3 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -732,25 +732,26 @@ LibPRNGTest:testPRNGShuffleGas() (gas: 1610927) LibPRNGTest:testPRNGUniform() (gas: 559430) LibPRNGTest:testStandardNormalWad() (gas: 4425913) LibPRNGTest:test__codesize() (gas: 14289) -LibRLPTest:testComputeAddressDifferential(address,uint256) (runs: 299, μ: 4184, ~: 3982) +LibRLPTest:testComputeAddressDifferential(address,uint256) (runs: 299, μ: 4191, ~: 3950) LibRLPTest:testComputeAddressForLargeNonces() (gas: 1760) LibRLPTest:testComputeAddressForSmallNonces() (gas: 1007) LibRLPTest:testComputeAddressOriginalForLargeNonces() (gas: 3766) -LibRLPTest:testComputeAddressOriginalForSmallNonces() (gas: 2207) -LibRLPTest:testRLPEncodeAddressDifferential(address) (runs: 299, μ: 341127, ~: 25910) -LibRLPTest:testRLPEncodeBool(bool) (runs: 299, μ: 27501, ~: 27507) +LibRLPTest:testComputeAddressOriginalForSmallNonces() (gas: 2185) +LibRLPTest:testRLPEncodeAddressDifferential(address) (runs: 299, μ: 395252, ~: 647525) +LibRLPTest:testRLPEncodeAddressViaList(address,address) (runs: 299, μ: 272884, ~: 27588) +LibRLPTest:testRLPEncodeBool(bool) (runs: 299, μ: 27570, ~: 27576) LibRLPTest:testRLPEncodeBytes() (gas: 382226) -LibRLPTest:testRLPEncodeBytesDifferential(bytes32) (runs: 299, μ: 459461, ~: 652902) -LibRLPTest:testRLPEncodeList() (gas: 746242) -LibRLPTest:testRLPEncodeList2() (gas: 822824) -LibRLPTest:testRLPEncodeListDifferential(bytes,uint256) (runs: 299, μ: 713819, ~: 665865) -LibRLPTest:testRLPEncodeUint() (gas: 1471535) -LibRLPTest:testRLPEncodeUint(uint256) (runs: 299, μ: 187389, ~: 25238) -LibRLPTest:testRLPEncodeUintDifferential(uint256) (runs: 299, μ: 405042, ~: 27345) -LibRLPTest:testRLPMemory(bytes32) (runs: 299, μ: 490840, ~: 653508) -LibRLPTest:testRLPPUint256() (gas: 365221) -LibRLPTest:testSmallLog256Equivalence(uint256) (runs: 299, μ: 23642, ~: 23689) -LibRLPTest:test__codesize() (gas: 14888) +LibRLPTest:testRLPEncodeBytesDifferential(bytes32) (runs: 299, μ: 410210, ~: 648521) +LibRLPTest:testRLPEncodeList() (gas: 742271) +LibRLPTest:testRLPEncodeList2() (gas: 818622) +LibRLPTest:testRLPEncodeListDifferential(bytes,uint256) (runs: 299, μ: 686538, ~: 661505) +LibRLPTest:testRLPEncodeUint() (gas: 1304532) +LibRLPTest:testRLPEncodeUint(uint256) (runs: 299, μ: 183869, ~: 25217) +LibRLPTest:testRLPEncodeUintDifferential(uint256) (runs: 299, μ: 427942, ~: 27489) +LibRLPTest:testRLPMemory(bytes32) (runs: 299, μ: 449222, ~: 648847) +LibRLPTest:testRLPPUint256() (gas: 364901) +LibRLPTest:testSmallLog256Equivalence(uint256) (runs: 299, μ: 23647, ~: 23689) +LibRLPTest:test__codesize() (gas: 14839) LibSortTest:testCopy(uint256) (runs: 299, μ: 138416, ~: 26968) LibSortTest:testInsertionSortAddressesDifferential(uint256) (runs: 299, μ: 73253, ~: 25190) LibSortTest:testInsertionSortInts() (gas: 112151) @@ -924,17 +925,17 @@ LibZipTest:testFlzCompressDecompress() (gas: 1250953) LibZipTest:testFlzCompressDecompress(bytes) (runs: 299, μ: 762658, ~: 671356) LibZipTest:testFlzCompressDecompress2() (gas: 760133) LibZipTest:test__codesize() (gas: 20369) -LifebuoyTest:testLifebuoyCreateDeployment(address,address,uint256) (runs: 299, μ: 4618186, ~: 4613846) -LifebuoyTest:testLifebuoyOwnedCloneRescuePermissions(bytes32) (runs: 299, μ: 941483, ~: 941344) -LifebuoyTest:testLifebuoyOwnedRescuePermissions(bytes32) (runs: 299, μ: 945539, ~: 938554) -LifebuoyTest:testLifebuoyRescuePermissions(bytes32) (runs: 299, μ: 928653, ~: 935789) +LifebuoyTest:testLifebuoyCreateDeployment(address,address,uint256) (runs: 299, μ: 3278409, ~: 4598970) +LifebuoyTest:testLifebuoyOwnedCloneRescuePermissions(bytes32) (runs: 299, μ: 941424, ~: 941319) +LifebuoyTest:testLifebuoyOwnedRescuePermissions(bytes32) (runs: 299, μ: 946934, ~: 938716) +LifebuoyTest:testLifebuoyRescuePermissions(bytes32) (runs: 299, μ: 929861, ~: 935934) LifebuoyTest:testLockEverything() (gas: 662008) LifebuoyTest:testLockRescue() (gas: 687529) LifebuoyTest:testLockRescueETH() (gas: 699031) -LifebuoyTest:testRescueERC20(uint256) (runs: 299, μ: 655263, ~: 657104) -LifebuoyTest:testRescueERC721(bytes32) (runs: 299, μ: 651562, ~: 651708) -LifebuoyTest:testRescueETH(uint256) (runs: 299, μ: 664144, ~: 664830) -LifebuoyTest:test__codesize() (gas: 31171) +LifebuoyTest:testRescueERC20(uint256) (runs: 299, μ: 655667, ~: 657326) +LifebuoyTest:testRescueERC721(bytes32) (runs: 299, μ: 651579, ~: 651790) +LifebuoyTest:testRescueETH(uint256) (runs: 299, μ: 664114, ~: 664835) +LifebuoyTest:test__codesize() (gas: 31001) MerkleProofLibTest:testEmptyCalldataHelpers() (gas: 985) MerkleProofLibTest:testVerifyMultiProof(bool,bool,bool,bool,bytes32) (runs: 299, μ: 747632, ~: 622800) MerkleProofLibTest:testVerifyMultiProofForHeightOneTree(bool,bool,bool,bool,bool,bool[]) (runs: 299, μ: 37580, ~: 37202) @@ -1243,7 +1244,7 @@ UpgradeableBeaconTest:testUpgradeableSolidityBeaconOnlyOwnerFunctions() (gas: 26 UpgradeableBeaconTest:testUpgradeableYulBeaconOnlyFnSelectorNotRecognised() (gas: 172796) UpgradeableBeaconTest:testUpgradeableYulBeaconOnlyOwnerFunctions() (gas: 198398) UpgradeableBeaconTest:test__codesize() (gas: 8808) -WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 10, calls: 150, reverts: 78) +WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 10, calls: 150, reverts: 77) WETHInvariants:test__codesize() (gas: 5178) WETHTest:testDeposit() (gas: 62272) WETHTest:testDeposit(uint256) (runs: 299, μ: 61545, ~: 62566) diff --git a/test/Lifebuoy.t.sol b/test/Lifebuoy.t.sol index 24863c8dc5..314fb55650 100644 --- a/test/Lifebuoy.t.sol +++ b/test/Lifebuoy.t.sol @@ -43,6 +43,11 @@ contract LifebuoyTest is SoladyTest { return abi.decode(result, (address)); } + function _testLifebuoyCreateDeployment(address deployer, bytes memory initcode) internal { + address expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); + assertEq(_deployViaCreate(deployer, initcode), expected); + } + function testLifebuoyCreateDeployment(address deployer, address owner, uint256 r) public { while (deployer.code.length != 0 || uint160(deployer) < 0xffffffffff) { deployer = _randomNonZeroAddress(); @@ -50,22 +55,18 @@ contract LifebuoyTest is SoladyTest { vm.etch(deployer, hex"3d3d363d3d37363d34f09052602081f3"); for (uint256 i; i != 3; ++i) { r = r >> 32; - address expected; if (r & 31 == 0) { - expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); - assertEq(_deployViaCreate(deployer, type(MockERC721).creationCode), expected); + _testLifebuoyCreateDeployment(deployer, type(MockERC721).creationCode); continue; } r = r >> 8; if (r & 1 == 0) { - expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); bytes memory initcode = type(MockLifebuoyOwned).creationCode; - initcode = abi.encodePacked(initcode, owner); - assertEq(_deployViaCreate(deployer, initcode), expected); + initcode = abi.encodePacked(initcode, abi.encode(owner)); + _testLifebuoyCreateDeployment(deployer, initcode); continue; } - expected = LibRLP.computeAddress(deployer, vm.getNonce(deployer)); - assertEq(_deployViaCreate(deployer, type(MockLifebuoy).creationCode), expected); + _testLifebuoyCreateDeployment(deployer, type(MockLifebuoy).creationCode); } }