Clones.t.sol 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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. assembly ("memory-safe") {
  13. spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
  14. }
  15. assertEq(spillage, bytes32(0));
  16. }
  17. function testCloneDirty() external {
  18. address cloneClean = Clones.clone(address(this));
  19. address cloneDirty = Clones.clone(_dirty(address(this)));
  20. // both clones have the same code
  21. assertEq(keccak256(cloneClean.code), keccak256(cloneDirty.code));
  22. // both clones behave as expected
  23. assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
  24. assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
  25. }
  26. function testCloneDeterministicDirty(bytes32 salt) external {
  27. address cloneClean = Clones.cloneDeterministic(address(this), salt);
  28. address cloneDirty = Clones.cloneDeterministic(_dirty(address(this)), ~salt);
  29. // both clones have the same code
  30. assertEq(keccak256(cloneClean.code), keccak256(cloneDirty.code));
  31. // both clones behave as expected
  32. assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
  33. assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
  34. }
  35. function testPredictDeterministicAddressDirty(bytes32 salt) external {
  36. address predictClean = Clones.predictDeterministicAddress(address(this), salt);
  37. address predictDirty = Clones.predictDeterministicAddress(_dirty(address(this)), salt);
  38. //prediction should be similar
  39. assertEq(predictClean, predictDirty);
  40. }
  41. function _dirty(address input) private pure returns (address output) {
  42. assembly ("memory-safe") {
  43. output := or(input, shl(160, not(0)))
  44. }
  45. }
  46. }