diff --git a/contracts/mocks/ComputedAddressRemainderMock.sol b/contracts/mocks/ComputedAddressRemainderMock.sol deleted file mode 100644 index a265cbf43f2..00000000000 --- a/contracts/mocks/ComputedAddressRemainderMock.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.20; - -import {Clones} from "../proxy/Clones.sol"; -import {Create2} from "../utils/Create2.sol"; - -contract ComputedAddressRemainderMock { - uint256 private constant _REMAINDER_MASK = ~(uint256(type(uint160).max)); - - function getCreate2ComputedRemainder( - bytes32 salt, - bytes32 bytecodeHash, - address deployer - ) external pure returns (uint256 remainder) { - address predicted = Create2.computeAddress(salt, bytecodeHash, deployer); - remainder = _getRemainder(predicted); - } - - function getClonesPredictedRemainder( - address implementation, - bytes32 salt, - address deployer - ) external pure returns (uint256 remainder) { - address predicted = Clones.predictDeterministicAddress(implementation, salt, deployer); - remainder = _getRemainder(predicted); - } - - function _getRemainder(address addr) internal pure returns (uint256 remainder) { - uint256 remainderMask = _REMAINDER_MASK; - - /// @solidity memory-safe-assembly - assembly { - remainder := and(addr, remainderMask) - } - } -} diff --git a/test/proxy/Clones.t.sol b/test/proxy/Clones.t.sol new file mode 100644 index 00000000000..cfe025b5c23 --- /dev/null +++ b/test/proxy/Clones.t.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; + +contract ClonesTest is Test { + function testClonesPredicted(address implementation, bytes32 salt) public { + address predicted = Clones.predictDeterministicAddress(implementation, salt); + bytes32 spill; + /// @solidity memory-safe-assembly + assembly { + spill := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000) + } + assertEq(spill, bytes32(0)); + } +} diff --git a/test/proxy/Clones.test.js b/test/proxy/Clones.test.js index 37dda9d9dd7..626b1e56467 100644 --- a/test/proxy/Clones.test.js +++ b/test/proxy/Clones.test.js @@ -9,7 +9,6 @@ async function fixture() { const factory = await ethers.deployContract('$Clones'); const implementation = await ethers.deployContract('DummyImplementation'); - const computedAddressMock = await ethers.deployContract('ComputedAddressRemainderMock'); const newClone = async (initData, opts = {}) => { const clone = await factory.$clone.staticCall(implementation).then(address => implementation.attach(address)); @@ -28,7 +27,7 @@ async function fixture() { return clone; }; - return { deployer, factory, implementation, computedAddressMock, newClone, newCloneDeterministic }; + return { deployer, factory, implementation, newClone, newCloneDeterministic }; } describe('Clones', function () { @@ -84,15 +83,5 @@ describe('Clones', function () { .to.emit(this.factory, 'return$cloneDeterministic') .withArgs(predicted); }); - - it('clean address prediction', async function () { - const salt = ethers.randomBytes(32); - const predictedRemainder = await this.computedAddressMock.getClonesPredictedRemainder( - this.implementation, - salt, - ethers.Typed.address(this.deployer), - ); - expect(predictedRemainder).to.equal(0); - }); }); }); diff --git a/test/utils/Create2.t.sol b/test/utils/Create2.t.sol new file mode 100644 index 00000000000..18f920fd0ef --- /dev/null +++ b/test/utils/Create2.t.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; + +contract Create2Test is Test { + function testClonesPredicted(bytes32 salt, bytes32 bytecodeHash, address deployer) public { + address predicted = Create2.computeAddress(salt, bytecodeHash, deployer); + bytes32 spill; + /// @solidity memory-safe-assembly + assembly { + spill := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000) + } + assertEq(spill, bytes32(0)); + } +} diff --git a/test/utils/Create2.test.js b/test/utils/Create2.test.js index 75472ded2f1..86d00e13197 100644 --- a/test/utils/Create2.test.js +++ b/test/utils/Create2.test.js @@ -6,7 +6,6 @@ async function fixture() { const [deployer, other] = await ethers.getSigners(); const factory = await ethers.deployContract('$Create2'); - const computedAddressMock = await ethers.deployContract('ComputedAddressRemainderMock'); // Bytecode for deploying a contract that includes a constructor. // We use a vesting wallet, with 3 constructor arguments. @@ -20,7 +19,7 @@ async function fixture() { .getContractFactory('$Create2') .then(({ bytecode, interface }) => ethers.concat([bytecode, interface.encodeDeploy([])])); - return { deployer, other, factory, computedAddressMock, constructorByteCode, constructorLessBytecode }; + return { deployer, other, factory, constructorByteCode, constructorLessBytecode }; } describe('Create2', function () { @@ -55,15 +54,6 @@ describe('Create2', function () { ); expect(onChainComputed).to.equal(offChainComputed); }); - - it('computes the clean contract address', async function () { - const computedRemainder = await this.computedAddressMock.getCreate2ComputedRemainder( - saltHex, - ethers.keccak256(this.constructorByteCode), - ethers.Typed.address(this.deployer), - ); - expect(computedRemainder).to.equal(0); - }); }); describe('deploy', function () {