I was trying create2 + minimal proxy implementation. I was able to deploy a wallet contract using create2 + minimal proxy. But I was not able to compute the address for create2+minimal proxy.
Code snippet to create a clone:
function createClone(address target, uint256 salt) public returns (address result) {
bytes20 targetBytes = bytes20(target);
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone, 0x14), targetBytes)
mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
result := create2(0, clone, 0x37, salt)
}
}
}
How to compute address for create2 + minimal proxy? Similar way like this function thats done for create2 https://github.com/OpenZeppelin/openzeppelin-sdk/blob/de895221ffeb8a99a5314d0b203db2580a2074f7/packages/lib/contracts/upgradeability/ProxyFactory.sol#L47
2 Likes
Hi @Thrilok_kumar ,
I assume that for the deploy of the minimal proxy the salt should be calculated in a similar way as in the ProxyFactory
:
function _deployProxy(uint256 _salt, address _logic, address _admin, bytes memory _data, address _sender) internal returns (address) {
InitializableAdminUpgradeabilityProxy proxy = _createProxy(_salt, _sender);
emit ProxyCreated(address(proxy));
proxy.initialize(_logic, _admin, _data);
return address(proxy);
}
function _createProxy(uint256 _salt, address _sender) internal returns (InitializableAdminUpgradeabilityProxy) {
address payable addr;
bytes memory code = type(InitializableAdminUpgradeabilityProxy).creationCode;
bytes32 salt = _getSalt(_salt, _sender);
assembly {
addr := create2(0, add(code, 0x20), mload(code), salt)
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
return InitializableAdminUpgradeabilityProxy(addr);
}
This would give us a deploy function something like:
function deployMinimalWithCreate2(
uint256 _salt,
address _logic,
bytes memory _data
) public returns (address proxy) {
bytes32 salt = _getSalt(_salt, msg.sender);
// Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol
bytes20 targetBytes = bytes20(_logic);
assembly {
let clone := mload(0x40)
mstore(
clone,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(clone, 0x14), targetBytes)
mstore(
add(clone, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
proxy := create2(0, clone, 0x37, salt)
}
emit ProxyCreated(address(proxy));
if (_data.length > 0) {
(bool success, ) = proxy.call(_data);
require(success);
}
}
We then need an equivalent of getDeploymentAddress
for our minimal proxy.
function deploy(uint256 _salt, address _logic, address _admin, bytes memory _data) public returns (address) {
return _deployProxy(_salt, _logic, _admin, _data, msg.sender);
}
function deploySigned(uint256 _salt, address _logic, address _admin, bytes memory _data, bytes memory _signature) public returns (address) {
address signer = getSigner(_salt, _logic, _admin, _data, _signature);
require(signer != address(0), "Invalid signature");
return _deployProxy(_salt, _logic, _admin, _data, signer);
}
function getDeploymentAddress(uint256 _salt, address _sender) public view returns (address) {
// Adapted from https://github.com/archanova/solidity/blob/08f8f6bedc6e71c24758d20219b7d0749d75919d/contracts/contractCreator/ContractCreator.sol
bytes32 salt = _getSalt(_salt, _sender);
bytes32 rawAddress = keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
contractCodeHash
)
);
We need a hash of our minimal proxy code creation equivalent to the following:
import "./InitializableAdminUpgradeabilityProxy.sol";
import "../cryptography/ECDSA.sol";
contract ProxyFactory {
event ProxyCreated(address proxy);
bytes32 private contractCodeHash;
constructor() public {
contractCodeHash = keccak256(
type(InitializableAdminUpgradeabilityProxy).creationCode
);
}
function deployMinimal(address _logic, bytes memory _data) public returns (address proxy) {
// Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol
bytes20 targetBytes = bytes20(_logic);
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
I don’t know assembly, so haven’t worked out how to put this part together.
Have you seen the Create2
library included in OpenZeppelin Contracts?
https://docs.openzeppelin.com/contracts/3.x/api/utils#Create2
It gives you code to deploy a contract and to compute the address.
Hey @abcoathup , I tried the way you have told me. So, while computing the address, the computed address and the deployed address is not the same.
Here is my code snippet.
create2MinimalProxy.sol
pragma solidity ^0.6.6;
import {IERC20, Wallet} from "./wallet.sol";
contract Deployer {
bytes public contractCode;
constructor () public {
contractCode = type(Wallet).creationCode;
}
This file has been truncated. show original
wallet.sol
pragma solidity ^0.6.6;
interface IERC20 {
function balanceOf(address) external view returns (uint);
function transfer(address, uint) external returns (bool);
}
contract Wallet {
function flush(address token) public {
This file has been truncated. show original
1 Like
Hey @frangio ,
Create2
Library is just a create2 implementation. I am looking for create2 + minimal proxy
implementation. I was able to deploy using this implementation. but the computed address is not matching with the deployed address.
1 Like
Hi @Thrilok_kumar ,
When calculating the deployment address we need to use the creation code for the minimal proxy, not the logic contract that the minimal proxy points to.
Your code snippet appears to use the creation code for the wallet and not the minimal proxy which is why you get a different address: https://gist.github.com/thrilok209/d9d1ebc15f27a3a1ef1e6358110dd274#file-create2minimalproxy-sol-L9
If you haven’t already, it is worth having a read through Deep dive into the Minimal Proxy contract
abcoathup
Split this topic
June 17, 2020, 1:30am
7
Hi @Thrilok_kumar ,
I created a simple Minimal Proxy Factory that computes the address for create2 and minimal proxies:
2 Likes
Did you manage to solve this? I have the same problem and so far no one has managed to find the solution. The javascript function in this tutorial does not return the same address
1 Like
Hi @itxtoledo ,
Welcome to the community forum
Have you tried using the following that I recently put together?: How to compute the CREATE2 address for a minimal proxy?
jimmy
October 6, 2020, 4:42am
11
Hey @Thrilok_kumar @abcoathup
Re the CREATE2 implementation from Coinbase Commerce in that post. Are Coinbase themselves the contract creator/owners- eg. only they would have the salt for the computed addresses?
Thanks,
J
1 Like
Hi @jimmy ,
Welcome to the community
I haven’t looked at their implementation other than the contract example given in the article. Anyone calling the factory could provide a salt (as long as it was unique).