12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- // 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 getNumber() external pure returns (uint256) {
- return 42;
- }
- function testSymbolicPredictDeterministicAddressSpillage(address implementation, bytes32 salt) public {
- address predicted = Clones.predictDeterministicAddress(implementation, salt);
- bytes32 spillage;
- assembly ("memory-safe") {
- spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
- }
- assertEq(spillage, bytes32(0));
- }
- function testSymbolicPredictDeterministicAddressWithImmutableArgsSpillage(
- address implementation,
- bytes32 salt,
- bytes memory args
- ) public {
- vm.assume(args.length < 0xbfd3);
- address predicted = Clones.predictDeterministicAddressWithImmutableArgs(implementation, args, salt);
- bytes32 spillage;
- /// @solidity memory-safe-assembly
- assembly {
- spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
- }
- assertEq(spillage, bytes32(0));
- }
- function testCloneDirty() external {
- address cloneClean = Clones.clone(address(this));
- address cloneDirty = Clones.clone(_dirty(address(this)));
- // both clones have the same code
- assertEq(cloneClean.code, cloneDirty.code);
- // both clones behave as expected
- assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
- assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
- }
- function testCloneDeterministicDirty(bytes32 salt) external {
- address cloneClean = Clones.cloneDeterministic(address(this), salt);
- address cloneDirty = Clones.cloneDeterministic(_dirty(address(this)), ~salt);
- // both clones have the same code
- assertEq(cloneClean.code, cloneDirty.code);
- // both clones behave as expected
- assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
- assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
- }
- function testPredictDeterministicAddressDirty(bytes32 salt) external {
- address predictClean = Clones.predictDeterministicAddress(address(this), salt);
- address predictDirty = Clones.predictDeterministicAddress(_dirty(address(this)), salt);
- //prediction should be similar
- assertEq(predictClean, predictDirty);
- }
- function testFetchCloneArgs(bytes memory args, bytes32 salt) external {
- vm.assume(args.length < 0xbfd3);
- address instance1 = Clones.cloneWithImmutableArgs(address(this), args);
- address instance2 = Clones.cloneDeterministicWithImmutableArgs(address(this), args, salt);
- // both clones have the same code
- assertEq(instance1.code, instance2.code);
- // both clones behave as expected and args can be fetched
- assertEq(ClonesTest(instance1).getNumber(), this.getNumber());
- assertEq(ClonesTest(instance2).getNumber(), this.getNumber());
- assertEq(Clones.fetchCloneArgs(instance1), args);
- assertEq(Clones.fetchCloneArgs(instance2), args);
- }
- function _dirty(address input) private pure returns (address output) {
- assembly ("memory-safe") {
- output := or(input, shl(160, not(0)))
- }
- }
- }
|