Clones.t.sol 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import {Test} from "forge-std/Test.sol";
  4. import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
  5. contract ClonesTest is Test {
  6. function getNumber() external pure returns (uint256) {
  7. return 42;
  8. }
  9. function testSymbolicPredictDeterministicAddressSpillage(address implementation, bytes32 salt) public {
  10. address predicted = Clones.predictDeterministicAddress(implementation, salt);
  11. bytes32 spillage;
  12. /// @solidity memory-safe-assembly
  13. assembly {
  14. spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
  15. }
  16. assertEq(spillage, bytes32(0));
  17. }
  18. function testCloneDirty() external {
  19. address cloneClean = Clones.clone(address(this));
  20. address cloneDirty = Clones.clone(_dirty(address(this)));
  21. // both clones have the same code
  22. assertEq(keccak256(cloneClean.code), keccak256(cloneDirty.code));
  23. // both clones behave as expected
  24. assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
  25. assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
  26. }
  27. function testCloneDeterministicDirty(bytes32 salt) external {
  28. address cloneClean = Clones.cloneDeterministic(address(this), salt);
  29. address cloneDirty = Clones.cloneDeterministic(_dirty(address(this)), ~salt);
  30. // both clones have the same code
  31. assertEq(keccak256(cloneClean.code), keccak256(cloneDirty.code));
  32. // both clones behave as expected
  33. assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
  34. assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
  35. }
  36. function testPredictDeterministicAddressDirty(bytes32 salt) external {
  37. address predictClean = Clones.predictDeterministicAddress(address(this), salt);
  38. address predictDirty = Clones.predictDeterministicAddress(_dirty(address(this)), salt);
  39. //prediction should be similar
  40. assertEq(predictClean, predictDirty);
  41. }
  42. function _dirty(address input) private pure returns (address output) {
  43. assembly ("memory-safe") {
  44. output := or(input, shl(160, not(0)))
  45. }
  46. }
  47. }