Dev Note #3: Limitations of Instantiate2 and how to deal with them

Simon Warta
CosmWasm
Published in
3 min readDec 23, 2022

This is part 3 of the Dev Note series. See #1 for an introduction.

After lengthy discussions with various members of the ecosystem, we shipped MsgInstantiateContract2 (“Instantiate2” for short) as part of wasmd 0.29.0. The goal was to get predictable contract addresses very similar to what Ethereum’s CREATE2 is doing.

The whole idea behind [CREATE2] is to make the resulting address independent of future events. Regardless of what may happen on the blockchain, it will always be possible to deploy the contract at the precomputed address. [docs.openzeppelin.com]

MsgInstantiateContract2 does that, it works, and it can be used.

Predictable address use cases

One use case is that a contract instantiator (aka. “creator”) has control over where a contract will be deployed. In multi-contract deployment scenarios, knowing contract vance can be very handy. You can even instantiate two contracts depending on each other in a circular way in one transaction. Another use case is lazy instantiation, where a contract address is published before a contract is instantiated. This allows for deposit addresses where some party only pays the instantation cost after a deposit address is used.

Users verifying the address

Now, what if a contract user is supposed to send funds to an address that is not yet instantiated? The contract creator might promise some super secure multisig, or the escrow contract will be instantiated once the funds arrive, but can we verify that?

This is where it becomes tricky. Originally Instantiate2 added the possibility the fix the instantiation message such that a user of the contract can verify that an address belongs to a fixed creator, a fixed checksum, a fixed salt, and a fixed message. Not only do you know the code, but also the initial state of the contract. However, this is all pretty pointless since we forgot to add the admin address to the address calculation. So no matter how much the instantiation is hardened, the creator can set any admin and migrate to any code or state they want. Thus using Instantiate2 is not more secure than sending funds straight to the creator for custody.

Now what?

Predictable addresses have value even if they do not guarantee a certain code before the instantiation. It is important to understand the difference and manage expectations accordingly. Let me get that straight: The creator of an Instantiate2 address has full control over whether or not they instantiate a code and what code they instantiate (via the admin field).

As a consequence, there is no reason to fix the instantiation message anymore. The contract creator can use the salt to generate many different addresses under the same code. One way to implement the salt is hashing the instantiation message, but this part really depends on the use case. So we discourage fixing the init message, i.e., set it to empty in the address calculation and set fix_msg to false. This does not change the Instantiate2 address calculation algorithm at all. It just discourages one way of using it.

We may or may not implement verifiable contract addresses as Instantiate3 at some point in the future. But this is a new project.

--

--