The exact claim this pattern was proposed to solve is the following:

There is no way today to guarantee the deployment, under asynchrony, by non-trusted parties, of particular code to a particular address without an insanely concocted multi-transaction hack relying on keyless signatures that are forced to precommit to specific gas prices, potentially even months or years in advance depending on your use case, and if you guess wrong all state can be permanently destroyed.

The pattern above does exactly this: it commits to deploying specific code to a specific address in advance of needing the code itself. It does not require “multi-transaction hack[s]”, “keyless signatures”, or “precommit[ments] to specific gas prices”. Simple modifications can be made to the pattern to support non-trusted or arbitrary parties being the deployer. Beyond the initial commitment, no assumptions are made about the (a)syncrony of interactions involving the address.

When this particular pattern was proposed as a solution, the response wasn’t to note that it was indeed possible, but instead to critique various aspects of it.

The first critique was that anyone can call the commit method and consume the commitment themselves. This is true, commit is a public function that anyone can call. However, this can be solved with any authentication scheme, but might actually be a desirable property in the future. We will come back to this point later, when we actually build something with this pattern.

The second critique was that the constructor might require arguments. However, because we are tightly coupling our commitment to the code being deployed, this is possible with some slight modifications.

The third critique was that one requires a specific factory for each contract you want to deploy in the future. This is valid, but again, this is merely a prototype. We can accomplish this in a number of ways, but the simplest would be to borrow from well-known proxy patterns to create a generic commitment:

A more generic commitment

As you can see, the commitment is now completely decoupled from the code being deployed. The factory is a generic address, and the fallback function forwards all call data to the factory, allowing arbitrary methods on the factory to be called. In this particular example, one can use the return value from getSig on a deployed Factory as the calldata in a call to the fallback function on your Commitment .

But what if we wanted to take it further? What if we just wanted a commitment to some arbitrary code? Well, it turns out we can do that, too. In fact, it’s around this point in my research that I realized I’m not the first one to have thought this pattern up (search for “Counterfactual”).

To accomplish our goal of commitment to arbitrary code, let’s put all of the pieces together:

Ain’t that a sweet lil’ thang

So, now our MachineCommitment is simply a commitment to deploy some particular code, with the help of a generic Deployer contract that can deploy the code for us. We also get assurance that the code being deployed (the init_code , as it were) is what was committed to in the first place. We still have the two required pieces: the commitment to a specific address, and the commitment to specific code.

But we can make this even better. We don’t need a deployer at all, really. It shaves a few gas off to use the delegatecall method above, but isn’t really a required feature, and adds complexity.

Instead, we can make a contract that is itself pretty much is create2 , by itself. It’s pretty simple, really:

If you want to try it out in a slightly cleaner environment (no offense to ethfiddle, it’s just lacking a couple features), try heading to the Remix IDE and dropping this code in there. You can deploy your own Machine to capture the init code values, and experiment with deploying different Create2 commitments. This could probably be slimmed down slightly (by removing the committedAddress helper, for example). Also, if you want to use different init_code than what is supplied above, you will need to compute the codeHash on your own.

I’ve also put this final form into a gist, in case it needs updates or fixes.