diff --git a/.changeset/fluffy-steaks-exist.md b/.changeset/fluffy-steaks-exist.md new file mode 100644 index 00000000000..b625e243481 --- /dev/null +++ b/.changeset/fluffy-steaks-exist.md @@ -0,0 +1,5 @@ +--- +'openzeppelin-solidity': patch +--- + +`Create2`, `Clones`: Mask `computeAddress` and `cloneDeterministic` outputs to produce a clean value for an `address` type (i.e. only use 20 bytes) diff --git a/contracts/proxy/Clones.sol b/contracts/proxy/Clones.sol index 43532dcab30..7001572b6e6 100644 --- a/contracts/proxy/Clones.sol +++ b/contracts/proxy/Clones.sol @@ -110,7 +110,7 @@ library Clones { mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) - predicted := keccak256(add(ptr, 0x43), 0x55) + predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff) } } diff --git a/contracts/utils/Create2.sol b/contracts/utils/Create2.sol index b98253bf3ad..9523c404142 100644 --- a/contracts/utils/Create2.sol +++ b/contracts/utils/Create2.sol @@ -82,7 +82,7 @@ library Create2 { mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff mstore8(start, 0xff) - addr := keccak256(start, 85) + addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff) } } } diff --git a/test/proxy/Clones.t.sol b/test/proxy/Clones.t.sol new file mode 100644 index 00000000000..214de2d5a51 --- /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 testPredictDeterministicAddressSpillage(address implementation, bytes32 salt) public { + address predicted = Clones.predictDeterministicAddress(implementation, salt); + bytes32 spillage; + /// @solidity memory-safe-assembly + assembly { + spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000) + } + assertEq(spillage, bytes32(0)); + } +} diff --git a/test/utils/Create2.t.sol b/test/utils/Create2.t.sol new file mode 100644 index 00000000000..d602eded0a5 --- /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 testComputeAddressSpillage(bytes32 salt, bytes32 bytecodeHash, address deployer) public { + address predicted = Create2.computeAddress(salt, bytecodeHash, deployer); + bytes32 spillage; + /// @solidity memory-safe-assembly + assembly { + spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000) + } + assertEq(spillage, bytes32(0)); + } +}