Title: ERC_2470__Singleton_Factory
Category: ERCs

Author: 3esmit
Date: 2020-01-15T20:30:06.481Z

github.com


status-im/EIPs/blob/singleton-factory/EIPS/eip-2470.md
---
eip: 2470
title: Singleton Factory
author: Ricardo Guilherme Schmidt (@3esmit)
discussions-to: https://ethereum-magicians.org/t/erc-2470-singleton-factory/3933
status: Draft
type: Standards Track
category: ERC
created: 15-01-2020
requires: 1014
---

## Simple Summary

Some DApps needs one, and only one, instance of an contract, which have the same address on any chain.

A permissionless factory for deploy of keyless deterministic contracts addresses based on its bytecode. 

## Abstract





  This file has been truncated. show original





I am writing a project that needs a singleton, I seen that there was no standard about it so I am creating one.
The idea is that a factory can create one deterministic address per byte-code, so everyone knows what to use and it can be deployed in any chain.
This factory would be using also nick’s method, so it would also be deployable in any chain, which then would always generate the same addresses for that bytecode, regardless of chain.
Any suggestions?

Author: Amxx
Date: 2020-01-16T09:37:26.641Z

This already exist:

factory.kistune-wallet.eth (on mainnet)
0xFaC100450Af66d838250EA25a389D8Cd09062629 (on all networks)
Available on mainnet, ropsten, rinkeby, goerli, kovan, lukso, …

Author: Amxx
Date: 2020-01-16T09:38:28.777Z

Salt is needed for people to deploy multiple instance of a contract that is only differenciated through initialisation (like proxies)

Author: Amxx
Date: 2020-01-16T09:42:35.754Z

Also, have a look at my code, the callback mechanism is really important for some contracts. For example, ownable contracts will be owned by the factory, an we need the user to tell the factory to transfer ownership to him.

Author: 3esmit
Date: 2020-01-16T10:57:59.370Z

Hi, thanks for the interest in this EIP. I presume you want to join this effort?



 Amxx:

This already exist:


Does it exists as an EIP/ERC? I searched it there and didnt founded any standarization on that.



 Amxx:

factory.kistune-wallet.eth (on mainnet)
0xFaC100450Af66d838250EA25a389D8Cd09062629 (on all networks)


I noticed that you hold the private key of the address that deploys 0xFaC100450Af66d838250EA25a389D8Cd09062629, which is not ideal, for 2470 we want to use keyless.



 Amxx:

Salt is needed for people to deploy multiple instance of a contract that is only differenciated through initialisation (like proxies)


I think that if the instance is being deployed, the unique address would be obtained by the constructor parameters.



 Amxx:

Also, have a look at my code, the callback mechanism is really important for some contracts. For example, ownable contracts will be owned by the factory, an we need the user to tell the factory to transfer ownership to him.


That would work, but IMO this is not ideal, because is possible to encode the correct behavior into the constructor. If the contract is intended to be deployed and have its owner to the factory caller, it should be handled by the initialization data.
if you use this design, it won’t be deterministic anymore based only on initialization condition.
Contracts that are constructed by the Singleton Factory MUST not use msg.sender as Owner or Controller, instead they MUST be designed to accept the “Controller” or “Owner” address into it’s constructor, so their initialization data (including constructor data) defines the deterministic address, not salt. Otherwise, if the factory allowed to send a message to the created contract as part of initialization, but without changing the resulting address, the same address could be initialized with different initialization state, therefore not guaranteeing the “Singleton” Property.

Author: 3esmit
Date: 2020-01-16T12:47:50.461Z

Amxx:

ownable contracts will be owned by the factory, an we need the user to tell the factory to transfer ownership to him.


For example, using this is not correct:
contract BadSingletonExample {
    address public owner = msg.sender;

    function setOwner(address _owner) external {
        owner = _owner;
    }
}

If in the case we use GenericFactory.sol to create the above contract, I could deploy it on different chains the same address with different owner. Thats why I am against this for the “SingletonFactory” EIP.
The equivalent version would be this:
contract SingletonExample {
    address public owner;

    constructor(address _owner) public {
        owner = _owner;
    }

    function setOwner(address _owner) external {
        owner = _owner;
    }
}

and the intended owner would be encoded in the initialization code (not in the msg.sender).
Some contracts wont work in SingletonFactory, and this is intended by design, using msg.sender in contract constructor should only be used to read the factory address (if this have any use).
However they just need to do a small change (replace msg.sender in constructor by parameter) and it would work better.
If you really need to use msg.sender with SingletonFactory to decide the owner, you could wrap another factory around and use SingletonFactory.deploy(abi.encode(Contract.creationCode, msg.sender), _salt);

Author: Amxx
Date: 2020-01-16T19:26:51.246Z

I never thought it was worth being an ERC. It’s just a small hack I made one night (took me less then 30min) … But if that is what it takes to have people be aware of it and not reinvent the weel then so be it.
Your approach is only focussed on singleton, so you it makes sens to you to have a fixed salt. I wanted to support any contract. My first objective was to help developper deploy any contract at the same address on multiple blockchain… And if you want singletons, then just use my approach with salt = 0. You could even build a singleton deployer that, given the contract code, calls my factory with salt = 0. And you could deploy the singleton deployer using my factory (and salt = 0) to make sure it has the same address on all blockchain.
Same goes for the callback mechanism. I understand that if you want to singleton, you should not use it, and you should build your contract in a way that prevents that. But some people could just want to use a “standard” contract that inherits from openZeppelin’s ownable, without having to modify and recompile the code, and deploy it on multiple blockchain at the same address. It’s just more flexible.
→ Now that I think about it, I could have used keccak256(encode.packed(_salt, _callback) as a salt. Would have ensure singleton even with callbacks. I’m putting that in the v2
It’s true that I own the private key. I was thinking that if I gave the private key away, trools could do useless transaction with it on some blockchain, preventing the factory from ever being deployed at the right address to these blockchain. I’m thinking about what would be the best way to give signed transaction for any chainid, without disclosing the private key.

Author: 3esmit
Date: 2020-01-17T21:48:40.560Z

Hey,
It needs to be an ERC for properly being reused in other ERCs.
I added salt to help deploy of vanity addresses, I did this because it is fairly easy to change a bit in comments and it changes the hash included in the bytecode, so why not make things easier, then harder, when there is no reason for.
Salt keeps singleton, as is fixed behavior, after deploy, nothing is done, no variables, all fixed - if the same address - the same (initial) behavior.

I don’t understand why I want to deploy it on chainId 2470? Why not using pre EIP-155, so its valid on any chain?
If you want to be really generic on your contract you should use msg.value at create2 value, instead of 0, and obviously also marking the deploy function as payable.
You should not give the private key, you should have used a keyless method, which not even you have the key. Learn more here https://medium.com/@weka/how-to-send-ether-to-11-440-people-187e332566b7 Nick helped with DAO rescue where he neede to proof he didnt owned the private key of the addresses, but still deploy a contract from there. So he did that. This was used as basis for EIP-2470, EIP-1820 and EIP-820. So I need that keyless deploy for EIP-2429, but then instead of making it once just for that, I made EIP-2470 for using in EIP-2429 or any other EIPs, all will inherit the keyless property of 2470 (anyone can deploy on anychain and noone knows the private key).

If you see, in ERC2470 the r,s of EC deploy signature are both 0x247000...0002470… Impossible for me to know what PK creates a signature to deploy that content with this r,s values…

Author: Amxx
Date: 2020-01-18T10:48:26.761Z

3esmit:

I don’t understand why I want to deploy it on chainId 2470? Why not using pre EIP-155, so its valid on any chain?


Sorry I missunderstood your past question. I’ll have to check pre EIP-155 has I am not familiar with it


If you want to be really generic on your contract you should use msg.value at create2 value, instead of 0, and obviously also marking the deploy function as payable.


That is a really big no! The origin of this factoryis the deployment of musisig wallets/proxys. I wanted to make sure you can have the same multisig at the same address on multiple network to avoid the issue of funds sent to a adress that is valid on another network but not on this. If you put msg.sender you either:

prevent semone else to deploy a wallet at an address were funds have already been sent to from deploying it when he needs to interact with.
Trust someone will do the deployment and give it the possibility of sensoring the deployment.

The payable part if a really good idea!


You should not give the private key, you should have used a keyless method, which not even you have the key. Learn more here How to send Ether to 11,440 people | by Nick Johnson | Medium Nick helped with DAO rescue where he neede to proof he didnt owned the private key of the addresses, but still deploy a contract from there. So he did that. This was used as basis for EIP-2470, EIP-1820 and EIP-820. So I need that keyless deploy for EIP-2429, but then instead of making it once just for that, I made EIP-2470 for using in EIP-2429 or any other EIPs, all will inherit the keyless property of 2470 (anyone can deploy on anychain and noone knows the private key).


I’ll have to check that out. The only method I know is to prepare the transaction, and then put a random value in the signature, resulting in a random sender that you have to fund to do the deployment. This is great for a single blockchain, but I don’t know how to apply that method in a way that will produce the same address on all blockchains. I’ll definitelly check that out.

Author: 3esmit
Date: 2020-01-18T16:31:31.089Z

That is a really big no!

What?

I wanted to make sure you can have the same multisig at the same address on multiple network to avoid the issue of funds sent to a adress that is valid on another network but not on this.

GerenricFactory allows Bob to initialize and set themsselves as owners of the wallet at chain 1, and allows Alice to initialize and set themselves as owners of the same wallet of Bob, but at chain id 2.
Isn’t this bad?

The payable part if a really good idea!

Maybe for Generic Factory, but not for Singleton Factory, as the msg.value can interfere on how the contract is initialized.

This is great for a single blockchain, but I don’t know how to apply that method in a way that will produce the same address on all blockchains.

I can assure it work in all blockchains, with the exact same signature, see:
https://ropsten.etherscan.io/address/0x247087a9061f30de86a9E63B68B4e7d8ebf4A51a
https://rinkeby.etherscan.io/address/0x247087a9061f30de86a9E63B68B4e7d8ebf4A51a

Author: Amxx
Date: 2020-01-18T22:49:26.013Z

3esmit:

GerenricFactory allows Bob to initialize and set themsselves as owners of the wallet at chain 1, and allows Alice to initialize and set themselves as owners of the same wallet of Bob, but at chain id 2.
Isn’t this bad?


This is bad. And it’s not possible if the initialisation is part of the constructor (which it is for my multisigs). It can only happen if the owner selection is part of the callback, which I’ve corrected in version 2 : https://etherscan.io/address/0xfac2006166c5b88a9e0a320e933a75813ccc7ecd#code


Maybe for Generic Factory, but not for Singleton Factory, as the msg.value can interfere on how the contract is initialized.


If you include the msg.value in the way the salt is generate then there is no risk. Also, ether can be sent to the address BEFORE the contract is created, so this kind of interferance will always be possible.
I’m still convinced a well designed generic factory is much more powerfull then a singleton factory.


I can assure it work in all blockchains, with the exact same signature, see:


I’ve just read about EIP155, I didn’t know there was something before that. I though I had read the yellowpaper carefully but I must have missed it.
It there any tooling for creating this kind of transaction?
I think this kind of deployment is really cool, but it means the sender address (and thus the factory address) is directly link to the deploy bytecode:

We should really focus on one exact code for the factory + on exact compiler version to fix the transaction once and for all.
Knowing this is possible, do we need singleton factory at all? The approach used to deploy the factory sounds easy enough that it can be used for any singleton.

Author: 3esmit
Date: 2020-01-19T00:03:56.831Z

First of all, you should stop calling this “callback”, because its not a callback, is an “additional call” to the freshly created contract.
I don’t think that the design you suggest is good, because the constructor is the “embedded additional call” of ethereum while creating a smart contract.



 Amxx:

But some people could just want to use a “standard” contract that inherits from openZeppelin’s ownable, without having to modify and recompile the code, and deploy it on multiple blockchain at the same address. It’s just more flexible.


The account contracts that you mention uses msg.sender in constructor to set owner, are therefore not designed for factories in general. OpenZeppelin should provide contracts for being used with factories, not using additional calls, this is bad design.
If a developer want to use EIP2470, they must be aware of what they are coding.
Also, you don’t want to give the responsibility to users that have no idea of solidity to deploy their own account contracts - this is clear to go wrong. Users would be scared away of having to decide in account contracts and factories and standards,
I don’t see the use case for that, seems like you pushing forward a legacy support for nonexistent use case?
So I am against adding additional complexity in this standard to support smart contract not designed to be used with factory, the additional complexity don’t bring any benefit and this is not a Backwards Compatibility issue, so including this would not be an improvement, as its only giving option to developers keep using a bad design.



 Amxx:

It’s just more flexible.


If you give me an use case that is not possible to use the constructor, then I would reconsider it for this EIP.

Author: 3esmit
Date: 2020-01-19T00:53:20.228Z

BTW, your GenericFactory is a type of Singleton, so you can use EIP-2470 to inherit the keyless property. if you want a GenericFactory that always have the same address in any ethereum chain possible and no one controls the keys to this process (becoming part of ethereum infra), you can simply say the bytecode of its deploy and then point it to EIP-2470.
Or you could follow Nick method and go to all this effort yourself…

Author: Amxx
Date: 2020-01-19T19:32:02.237Z

You are saying openzeppelin’s contract are bad by design, and dev should not use them and rather implement something of their own with the right pattern. This is something have been fighting for years. Feature duplication is causing bugs that this community cannot afford.
The “construct then initialize” pattern is an old one that has been working long before solidity was even here. Sure it’s not perfect. Sure we would rather not have to rely on it. But i’ll rather make sure to include the possibility then dictate how people should refactor their code.
I’ve been pushing for “initialized through constructor” proxies but most people use the regular zos proxies that are initialized after the fact. Upgradeability is (IMO) a great feature and making the most used framework for it not compatible would (again IMO) not be the way to go.
And yes, solidity developers have to be carefull of what they do. I don’t see it changing anytime soon

Author: Amxx
Date: 2020-01-19T19:34:22.638Z

You can do you very limited singleton factory, and then expect people to use it to deploy more generic factories. And I’ll be the first one to admit that it’s unlikelly we will build the perfect factory on the first try. But I think it’s forth it to try get as much features (that do not compromise security) in the “root” factory.
I also think it would be nice to have additional opinions beside ours.

Author: Amxx
Date: 2020-01-19T19:47:46.625Z

Also, I’m still convinced this doesn’t need to be an ERC. we obviously have different visions of what this could/should be. What usually happens is that a bunch of project build their own solution, use them, share the code/address, and then a some point some actors like openzeppelin makes a mix of all existing solution that answers most people needs and becomes the de-facto standard.
I believe this is a much better process then arguing over potential usecases.

Author: 3esmit
Date: 2020-01-19T20:59:37.184Z

Amxx:

You are saying openzeppelin’s contract are bad by design,


Not the contract themselves, but using it with factory that then set the owner. This is not a really huge problem, but is inherently a bad design as its waste of gas and there is a better way of doing it.
If they are supposed to be used with a factory, they should have been designed for that.

But i’ll rather make sure to include the possibility then dictate how people should refactor their code.

That’s the case, I don’t want to include the possibility of doing bad things, and if they want to use a factory, they should refactor it - or use some factory who don’t care.

You can do you very limited singleton factory, and then expect people to use it to deploy more generic factories.

Yes, that can be a point, as I mentioned, an factory that support msg.value or other behavior might be interesting for you or other. In the case of account contracts, a singleton factory could be used, but might not be the best behavior for it, another factory that controls the deploy based on a signed message would be wiser, so we dont allow anyone init other people accounts…

still convinced this doesn’t need to be an ERC

I need it as ERC because it will be used in other ERCs.

Author: Amxx
Date: 2020-01-20T10:00:20.583Z

3esmit:


still convinced this doesn’t need to be an ERC

I need it as ERC because it will be used in other ERCs.


Fair point!

I’ve seen you added a salt to the EIP 
The deploy transaction includes 100Gwei. Do we really need such a high value? I get it’s a one-time thing but it still feels unecessarily high.

Author: 3esmit
Date: 2020-01-20T18:38:04.671Z

salt

Yes, I enabled salt because it didn’t made sense to hide it, as it was very easy to switch one insignificant bit (such the ones in the source hash) on the initCode. Salt can be used as wanted by project, but for Singleton the only use I see is “vanity address”.

100gwei

This is to ensure that it will be deployed on any chain no matter the gas cost. Its 100gwei and with the gas used it costs 0.027 to deploy. With 10gwei I might not have a deploy in some cases, and it would cost 0.0027 ETH.
I also hate to waste my precious gas to leave it there in a keyless address, but is not much, and this will save ETH in my other projects that also need keyless deploy (and are singletons), where the contracts are much bigger and using 100gwei would cost a lot. These singletons will use  any gas price  so we have to waste only a high amount in the Singleton Factory deploy.
This 100gwei value decisions was copied from ERC-820 and ERC-1820, which I found were plausible, instead of making everything very tight “gasLimit exactly the cost of deploy” and “gasPrice at a low price”, but then it wont be guaranteed to work in every situation.
For example, I don’t plan to deploy this on ETC, simply because I don’t own any ETC, but it might happen in future that some DApp gets ported to there and uses this ERC, so it will be guaranteed to work in ETC, even if they changed opcode costs and the gas market is competitive.

Author: Amxx
Date: 2020-01-20T22:11:52.140Z

3esmit:

For example, I don’t plan to deploy this on ETC, simply because I don’t own any ETC, but it might happen in future that some DApp gets ported to there and uses this ERC, so it will be guaranteed to work in ETC, even if they changed opcode costs and the gas market is competitive.


Completelly unrellated, but does ETC have create2?

Author: 3esmit
Date: 2020-01-20T22:37:42.973Z

but does ETC have create2

I have no idea, the only blockchain I know about is Ethereum.

Author: 3esmit
Date: 2020-01-23T02:33:25.915Z

Regarding “GenericFactory2”, it’s still clearly possible to collide addresses.
I created for you a contract that enables what “GenericFactory” does, but it’s guaranteed to not have colliding addresses, and allows payable! I named it “InitializerFactory” because it seemed more proper to what it does, however, I didn’t deployed or tested (just mentally), and I am releasing here under CC0, feel free to use it or take it for inspiration to fix “GenericFactory”.
/**
 * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
 * @notice Allows Creation of contracts that require one call after creation. 
 */
contract InitializerFactory {
    /**
     * @notice Deploys a deterministic address based on `_initCode`, `msg.value`, `_initCall`, `_salt`.
     * @param _initCode Initialization code.
     * @param _initCall Calldata to be made to created contract 
     * @param _salt Arbitrary value to modify resulting address.
     * @return Created contract address.
     */
    function deploy(bytes memory _initCode, bytes memory _initCall, bytes32 _salt)
        public
        payable
        returns (address payable createdContract)
    {
        bytes32 actualSalt = keccak256(abi.encodePacked(msg.value, _initCall, _salt));
        assembly {
            createdContract := create2(msg.value, add(_initCode, 0x20), mload(_initCode), actualSalt)
        }
        if(_initCall.length > 0){
            (bool success, bytes memory reason) = createdContract.call(_initCall);
            require(success, string(reason));
        }
    }
}

If you are satisfied with the contract you can deploy ERC-2470 on mainnet and use it to deploy this factory. Or you can give me the code and I deploy the GenericFactory3 with 2470.

Author: 3esmit
Date: 2020-01-23T02:49:53.929Z

Perhaps this would be the fixed “ConterfactualFactory”:
contract CounterfactualFactory
{
        constructor() internal {}

	function _create2(bytes memory _code, bytes32 _salt, uint256 _value, bytes memory _initCall)
	internal returns(address)
	{
		bytes memory code = _code;
		bytes32      salt = keccak256(abi.encodePacked(_salt, _value, _initCall));
		address      addr;
		// solium-disable-next-line security/no-inline-assembly
		assembly
		{
			addr := create2(_value, add(code, 0x20), mload(code), salt)
			if iszero(extcodesize(addr)) { revert(0, 0) }
		}
                if(_initCall.length > 0){
                        (bool success, bytes memory reason) = addr.call(_initCall);
                        require(success, string(reason));
                }
		return addr;
	}

	function _predictAddress(bytes memory _code, bytes32 _salt, uint256 _value, bytes memory _initCall) 
	internal view returns (address)
	{
		return address(bytes20(keccak256(abi.encodePacked(
			bytes1(0xff),
			address(this),
			keccak256(abi.encodePacked(_salt, _value, _initCall)),
			keccak256(_code)
		)) << 0x60));
	}
}

Author: Amxx
Date: 2020-01-23T18:39:29.921Z

3esmit:

Regarding “GenericFactory2”, it’s still clearly possible to collide addresses.


How?
The code you proposed is really similar to mine. The only difference I see is you made the function payable and put the msg.value in the actualSalt.
I see that you put the msg.value in the constructor (I would have put it in the .call(). It that something you plan to include in ERC2470? I’ve never seen payable constructor but who knows, it might be a thing …

Author: 3esmit
Date: 2020-01-24T01:43:29.951Z

Amxx:

How?


You left open the direct _salt of create2 exposed, while in the other function you wrap around the parameters of callback. This means that in one chain one contract could have been initialized with the callback function, and other chain the same address could have been initialized without callback just by passing directly the same salt used in the other function/chain.
Therefore, if there is no callback, it should even hash it against an empty callback.
I don’t plan to include msg.value or payable in ERC2470, it don’t seem to be a Singleton use-case to initialize a contract with funds, however in Ethereum that possible, and as you intent to support any type of contract, I imagine you want to have payable in the constructor call too. To be honest, I never seen a contract using a payable constructor.

Author: 3esmit
Date: 2020-01-24T01:43:35.009Z

ERC2470 was done for other developers don’t have to replicate what ERC820 and ERC1820 every-time they need a key-less contract deploy. I have other plans for ERC2470 and development chains as well, so these infrastructure contracts, such as ERC2470 and the ones derived from it could be initialized at genesis of ganache development chains, for example.
After create2, this was not possible, but now as is possible, it seems a useful piece to have available for building Ethereum infrastructure of Singleton.
As you might now due your prior research on this topic. this also solves the problem of who gets to deploy a trustless contract, which technically is anyone, but in the case of ERC2470, a contract exists based on it’s code.
Other great advantage of ERC2470 is the vanity generator for ERC2470, in past, creating a vanity contract was complicated, usually involved brute-forcing key generation until found a nonce 0 contract that does the starting bytes desired, however for key-less deploys that greatly increases complexity.

Author: 3esmit
Date: 2020-03-30T23:13:17.151Z

Ethereum Improvement Proposals



EIP 2470: Singleton Factory
Details on Ethereum Improvement Proposal 2470 (EIP 2470): Singleton Factory





https://etherscan.io/address/0xce0042B868300000d44A59004Da54A005ffdcf9f#code

Author: MicahZoltu
Date: 2020-09-03T16:01:29.481Z

I recommend checking out GitHub - Zoltu/deterministic-deployment-proxy: An Ethereum proxy contract that can be used for deploying contracts to a deterministic address on any chain..  I (and others) have been using that for deterministic deployments of contracts for over a year now.  It has the advantage of letting you just do a normal deployment transaction but set the to field on the transaction to the deployment proxy address.  It also has the nice property that the deployment proxy deployment code is very tiny, so it can be inlined easily into say another EIP.  
The reason I didn’t create an EIP is because I don’t think there is significant value in standardizing it.  Anyone can deploy with whatever mechanisms they want.  I can use my deployer and you can use your deployer and everything works just as well as if we both used the same deployer.
Something being a good idea, or a good design pattern doesn’t mean it needs to be standardized.  There are many good design patterns that are not also standards, but end up widely used because they are good ideas.  Generally, a standard should exist if you he a many to many relationship of actors who need to communicate with each other.
You have indicated that you plan to refer to this in other standards.  The only place I can think of where this would make sense is a standard for a central registry.  In such a case you can simply define the deployment process in that standard, like how EIP 1820 did, but in this case it would be a bit simpler as the steps are just “send this data to this contract address, if no contract exists at that address then send ETH to this address and then submit this transaction”.

Author: 3esmit
Date: 2020-10-10T07:53:51.788Z

MicahZoltu:

deterministic deployments of contracts


ERC-2470 uses this yes, but it’s not only this, but also the “keyless deployment”. No one control any keys that are related to the deployment of ERC-2470 or it’s children.



 MicahZoltu:

in this case it would be a bit simpler as the steps are just “send this data to this contract address, if no contract exists at that address then send ETH to this address and then submit this transaction”.


Exactly, so instead of everyone that needs this feature of “deterministic keyless deploy”, don’t have to redo the process. they can just use ERC-2470. Also, they don’t have to mention about how to deploy the 2470 contract, because it would be described in the 2470 document.
I see that this is interesting to have as an EIP, so dev tools can integrate this behavior, so everyone uses the same thing instead of each one using a different or own implementation.

Author: MicahZoltu
Date: 2020-10-10T12:42:15.307Z

3esmit:

ERC-2470 uses this yes, but it’s not only this, but also the “keyless deployment”. No one control any keys that are related to the deployment of ERC-2470 or it’s children.


Perhaps I’m misunderstanding, but the deterministic-deployment-proxy I linked above also supports “keyless deployment”?  That is, anyone can deploy the contract from any address and it will end up deployed at the same address on all chains no matter who the deployer is.

Author: 3esmit
Date: 2020-10-10T15:48:36.202Z

Ah, I see now, you also did the keyless deploy of the factory. Yes, it exactly the same thing.

Author: 3esmit
Date: 2020-10-10T16:14:37.415Z

Seems like the only difference is that in 2470 the salt of create2 is exposed. This was done to make easier to create vanity addresses.

Author: rmeissner
Date: 2020-10-22T11:31:26.010Z

Also the yul implementation reverts if create2 fails, which the current eip 2470 implementation doesn’t. I would recommend to add this else quite some tools cannot properly estimate the transaction.

Author: 3esmit
Date: 2020-10-22T12:04:12.397Z

Hey, I would like to test this behavior before implement it. Can you give me an example of a tool/contract that fails to estimate the create2? I never experienced that with Singleton Factory, maybe it depends on what constructor is doing?

Author: rmeissner
Date: 2020-10-22T12:41:38.903Z

truffle fails on this you can tests this with https://github.com/gnosis/delegate-registry/commit/1a181e5aacca33a743cc3f51e7473728a8a063be
Also I find it very unexpected that the transaction doesn’t revert if the deployment fails.

Author: 3esmit
Date: 2020-10-22T23:58:48.940Z

Thanks for reporting this issue.
I see the issue with the gas estimator. It looks like everytime create2 is used the check must be done, or the gas estimator should be fixed.
I ran the script you linked but there I had no issues, I just had issues when using it with Metamask directly on the etherscan dapp.
I’ve had other problems with gas estimator, like in GnosisMultisig, when the last confirmation is supposed to execute something, or even calling execute. As the execution failed generates an event informing the fail instead of reverting, its the “less gas cost” path the estimator finds.
Personally I think that this is not a issue with SingletonFactory contract, but with the gas estimator should be fixed for all cases, as this is not only affecting this case, but other systems as well.
For working around the issue, there are 3 paths forward for this:

Creating a new singleton factory that reverts if deploy failed
a. redeploying from a keyless deploy
b. deploying in top of current singleton factory.
Creating a wrapper contract around singleton factory that does this check.
Using a custom gas calculation for this issue.

For  1,2, I’ll provide a version with that feature.
For 3.:
Can you see if this workaround works for you?
in migrations/utils/singleton_factory.js line 74:
    const blockGasLimit = (await web3.eth.getBlock('latest')).gasLimit
    const txGasLimit = await new web3.eth.Contract(SINGLETON_FACTORY_ABI, SINGLETON_FACTORY).methods.deploy(bytecode, salt).estimateGas({from: deployer, gas: blockGasLimit});
    const { tx } = await factory.deploy(bytecode, salt, { from: deployer, gas: txGasLimit });

Author: rmeissner
Date: 2020-10-23T00:17:10.891Z

Calling estimateGas will not fix this (that is what truffle does under the hood). We encountered that issues on multiple machines when deploying to mainnet, rinkeby and kovan. Adding a wrapper contract will increase the deployment costs (especially since there is discussion around increasing the gas costs for internal calls). Currently I work around by checking before deployment that the call succeeds (expected address is returned) when the estimated gas limit is set. I also wrote a js lib for that (it supports also @MicahZoltu version):  https://github.com/gnosis/singleton-deployer there you can see that I do some checks for the gas limit before deployment: https://github.com/gnosis/singleton-deployer/blob/main/packages/core/src/factory.ts#L36

Author: 3esmit
Date: 2020-10-23T00:37:20.776Z

Estimate gas don’t works even if defining the gas parameter to block gas limit? Where is the best place to report this issue? https://web3js.readthedocs.io/en/v1.3.0/web3-eth-contract.html#id38 as I understand, the gas parameter should aid on cases like this.
The intent of not checking the deploy was that this could be done externally, and the factory would just try to deploy with the gas provided.
I agree the wrapper contract is the worst way to go on this solution.
I liked you workaround
I think that, if we are unable to have a fix for gas estimate, than the best is to make a new keyless deploy. This might take some time as I will let the script find an address that contains as many zeros as possible.
What way you recommend of checking the contract deploy worked? Just check if address returned is not zero? Or also check if extcodesize is greater than zero?

Author: rmeissner
Date: 2020-10-23T06:35:31.967Z

So if I set the Gaslimit for the deployment tx to the block gas limit it would work. The estimateGas always tries to find the lowest value where the ethereum transaction is “successful” (aka not reverting).
Maybe I would say it is just unexpected, if described in the eip that you need to pay attention to the gas as the factory does not enforce success I don’t see an immediate need to fix it.
Checking that the returned value is != 0 should be enough, afaik that is how success is defined in the eip for create2.
I would collect more feedback before a redeploy. (E.g. add the fallback behaviour that is used in the yul implementation).
I agree that estimations are still annoying, especially for gas intensive, nested calls … Which deployment of a contract via factory is. Not sure should “fix” this

Author: 3esmit
Date: 2020-10-23T14:10:51.558Z

I opened an issue in ethereum-go: https://github.com/ethereum/go-ethereum/issues/21746

Author: 3esmit
Date: 2020-10-25T05:17:20.941Z

I submitted a fix to the eth_estimateGas on go-ethereum https://github.com/ethereum/go-ethereum/pull/21751

Author: 3esmit
Date: 2020-10-29T02:02:31.242Z

@rmeissner so this is what you suggest?
contract ERC2470 {

    fallback() external payable {
        deploy(msg.data, 0);
    }

    function deploy(bytes memory _initCode, bytes32 _salt)
        public
        payable
        returns (address payable createdContract)
    {
        assembly {
            createdContract := create2(callvalue(), add(_initCode, 0x20), mload(_initCode), _salt)
        }
        require(createdContract != address(0), "ERC2470: CREATE2 failed");
    }

}

Anything else you want to add?
This seems wrong, because with “payable” creations some contracts might deploy something different, however this can already be achieved by using other transaction parameters like gas limit or gas price.
So I might allow this and just add to security considerations that when a contract accepts value at creation, it should also work when msg.value is zero, or execute the same procedure regardless of value in constructor.

Author: saurik
Date: 2020-12-04T21:19:49.191Z

So, the 100 gas bid for this contract feels “high”, but in practice isn’t high enough :(. In fact, it is below the minimum gas bid for Avalanche, and so this contract cannot be deployed to their C-chain at all. It is sadly too late to fix this EIP over this, but I’m going to assert the bid should have been 500, with the argument that geth actually used to (and sort of still does?) have a maximum gas suggestion limit of 500, which makes this that schilling point for “a lot of gas”.
(This also happens to be greater than the weirdly-hardcoded gas limit on Avalanche C-chain, which is 470. FWIW, I do not consider Avalanche’s design here reasonable, and have an issue filed at https://github.com/ava-labs/coreth/issues/40; but, even so, I am still sad that EIP2470 went with what feels like an arbitrary 100 instead of seeing the existing 500 limit, particularly as the gas bid on Ethereum itself was up towards 500 for quite a bit of time this year.)
What I’m currently intending to do is to deploy a variant of EIP2470 to all of the chains I’m working with that uses the exact same transaction as the one in EIP2470 but with 500 instead of 100 as the gas bid (as I figure that that is the schilling point for such a contract, given the further existence of EIP2470; this is of course throwing away the 00s optimization, but it isn’t even clear to me what that was gaining us, as the non-0s in that address don’t cost anything, right?).
That said, I actually ended up coming to this thread because of a link I found in that issue that was filed about gas cost estimation, so I’m guessing that I should probably deploy that deterministic-deployment-proxy project instead, if it is in fact fixing that issue. (Sadly, I see it is also using 100 Gwei. Is there something I’m missing for why 100 Gwei is considered firmly “enough a-lot-of-gas that the idea that a currency would need more would be preposterous”?)

Author: 3esmit
Date: 2021-02-23T20:08:30.274Z

saurik:

Is there something I’m missing for why 100 Gwei is considered firmly “enough a-lot-of-gas that the idea that a currency would need more would be preposterous”


What we should have used? gasPrice at 1000 Gwei?
In ETH chain, currently there are times where you could deploy it.
The reason 100 was choosen is because 1820 used it, and 1820 probably choosed it because the normal gas prices at that time were like 10gwei.

Author: saurik
Date: 2021-04-01T09:12:06.882Z

What we should have used? gasPrice at 1000 Gwei?

I made an explicit argument–seemingly ignored ;P–that the schelling point (which to me is a very useful way of analyzing this question) is “500 Gwei” due to what as-far-as-I-know continues to be a soft cap (and which certainly used to be a pretty hard cap) in geth at that value (and, in the few months since my writing that, I’ve only become more convinced of this based on actually seeing the weird behavior that happens as the network pushes up towards 500 Gwei).

Author: 3esmit
Date: 2021-04-05T16:26:46.095Z

Do you have any idea on how to let this fee open?
I can update the EIP to use 500 gwei for the final interation, but I am not sure if there wont be another new chain or new situation where 500 gwei wont work

Author: saurik
Date: 2021-04-06T01:05:27.165Z

Do you have any idea on how to let this fee open?

FWIW, I (at least) don’t: techniques surrounding hacks on top of CREATE and CREATE2 seem to fundamentally require predicting the future, as the gas bid has to be signed. I don’t think this is quite “hopeless” to do “pretty well”, as if the price of gas is going up typically the price of the coin will go up as well, seeing that the primarily utility of the coin is to pay for gas; and I think that the common standard of 10^18 decimals combined with psychological price points surrounding new coin launches caps the low end of gas fees somewhat.
But it is of course still easy to come up with mechanisms and scenarios where any “reasonable price”–which is maybe at least vaguely important to consider: Orchid paid thousands of dollars to deploy the aforementioned Gnosis contract on RSK, as the coin on their chain is Bitcoin, now at ~$50k (so, fwiw, if anyone wants to use a factory across a number of chains: I have one for you to use, and we will even help deploy it places)… but if it had been hundreds or even tens of thousands, we probably would not have ;P–is going to just not be workable.
I do have a suggestion, though! One might argue that, to the extent to which this is considered functionality the platform “should have”–and the existence of EIP-1820, which developers currently are unable to deploy on Avalanche, as even their “lower as of last week” minimum gas price of 225 nanoAVAX is too high, seems to argue for given that it is a dependency of other standards–the platform needs to provide a guaranteed way to do this: it should either be specified as a hardcoded address or as a new CREATE3 instruction.
In the world where this is CREATE3, it should be pretty clear how it would work… but it would now require getting implementation buy in from all of the chains to add it–and it is kind of feeling like the ship has sailed as of mid-2020: new feature are going to be hard to rely upon–but, in a world where it were a hardcoded address, then Nick’s method could merely be a fallback. Like, AFAIK nothing prevents there from being a special case on (for example) Avalanche to have this factory’s creation be either a one-off special case or even a built-in.

Author: flockonus
Date: 2023-03-02T04:29:09.260Z

Hey @3esmit this EIP is quite interesting, any update to it, OR do you know of Singleton Factory that we can use today has been deployed across the majority of chains?

Author: dror
Date: 2023-06-22T14:11:42.623Z

There is one deficiency of this EIP, and that it doesn’t revert on failure.
This means you can’t even estimate its gas usage.
It does use a standard ABI encoding, which makes it slightly easier to use from solidity than the deterministic deployment proxy.
Not sure that this makes it a better candidate to be a standard, though.

Author: SKYBITDev3
Date: 2023-08-19T17:14:20.890Z

dror:

There is one deficiency of this EIP, and that it doesn’t revert on failure


Axelar’s CREATE2 factory has similiar code and has reverts: axelar-gmp-sdk-solidity/contracts/deploy/ConstAddressDeployer.sol at main · axelarnetwork/axelar-gmp-sdk-solidity · GitHub
They’ve deployed it to a number of blockchains. Here’s their guide: Axelar Documentation
These days I find the “CREATE3” method much more interesting, as contract bytecode is not used to calculate the address.
It would be great if both methods were part of Ethereum, so that we wouldn’t have to do the keyless deployment of the factory contract on multiple blockchains. Keyless deployment is best practice but now getting more difficult due to chainId enforcement by nodes.
We really need a solution to EIP-155 enforcement.

Author: 0x3114
Date: 2023-10-12T22:04:20.469Z

hey 3esmit! i’m taking a close look at AA and see that originally there was a relatively high probability of using this eip to implement a standard account creation factory compatible with other eips like 4337. would love to learn more about how those convos progressed and ultimately why the outcome was moving this proposal to stagnant. lmk how might be best to chat.

Author: dror
Date: 2023-10-31T19:01:35.223Z

SKYBITDev3:

Keyless deployment is best practice but now getting more difficult due to chainId enforcement by nodes.


Yes, non-EIP155 deployment is tricky on new networks, but I think that adding a new opcode (or precompile) for that purpose is an overkill: it is much simpler to do a “nonstandard state change” for those networks and deploy the deterministic deployer…
(actually, this is exactly what “Base” did, and I think other networks too, to have the deployer available)