openzeppelin-contracts icon indicating copy to clipboard operation
openzeppelin-contracts copied to clipboard

Add clone variant with per-instance parameters stored in "immutable storage"

Open Amxx opened this issue 1 year ago • 2 comments

Notes about EOF:

  • The clones are not EOF objects. They are legacy contract. As a consequence, they can be used with either EOF or Legacy implementations.
  • Legacy implementations are not an issue. The clone being a legacy contract, it is observable.
  • EOF implementations will not be able to read the params directly. They could however do it indirectly by doing a static call on an helper (Legacy) contract, that would do an extcodecopy on the caller.
/// compiled in legacy mode
contract ImmutableArgsReader {
    function selfFetchCloneArgs() external returns (bytes memory) {
        return Clones.fetchCloneArgs(msg.sender); 
    }
    
    function fetchCloneArgs(address instance) external returns (bytes memory) {
        return Clones.fetchCloneArgs(instance);
    }
}

/// compiled in EOF 
contract MyEOFImplementation {
    ImmutableArgsReader private immutable immutableArgsReader = ImmutableArgsReader(...);
    
    function somefunction(...) public {
       (uint256 arg1, address arg2, ...) = abi.decode(immutableArgsReader.selfFetchCloneArgs(), (uint256, address, ...));
       //...
    }
}

PR Checklist

  • [x] Tests
  • [ ] Documentation
  • [ ] Changeset entry (run npx changeset add)

Amxx avatar Jul 10 '24 22:07 Amxx

🦋 Changeset detected

Latest commit: c9aa715d135e6267972475f0eb990284605de941

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openzeppelin-solidity Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

changeset-bot[bot] avatar Jul 10 '24 22:07 changeset-bot[bot]

If you need an ERC1967 minimal proxy with immutable args, this is the formulation of the init code.

abi.encodePacked(
    hex"61",
    uint16(args.length + 0x3d),
    hex"3d8160233d3973",
    implementation,
    hex"60095155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3",
    args
)

For minimalism, this does not emit the Upgraded event on deployment.

Vectorized avatar Jul 16 '24 04:07 Vectorized

My preference goes for CloneArgumentsTooLong because it is clear what the issue is.

If you get EIP170ExceededContractSizeLimit, you must understand that there is a contract size limit, then understand that the immutable args are part of the code, then understand that the immutable args are so long that they cause the size of the proxy to exceed the limit ...

CloneArgumentsTooLong is clear: the argument are too long, you don't need to know why, just that its not supported.

Amxx avatar Sep 03 '24 19:09 Amxx