1. 初めに
PS/SLの佐々木です。
最近ContractAddressがどのように導出されているのかが気になり調べていたところ、ContactAddressの導出方法は二つがあることを知りました。その中で事前にコントラクトアドレスを計算して、デプロイ前のコントラクトに対して送金できたり、署名を作成できたりと結構面白そうだったのでまとめてみました。
Ethereumのスマートコントラクトをデプロイするにオペコードというものが存在します。オペコードには*CREATE** および **CREATE2*の二つの種類があります。
この記事では、CREATE と CREATE2 の違いを比較し、CREATE2の理解や使いどころの理解の手助けになればと思います。
2. opcodeとは
EthereumのスマートコントラクトはEVM上で実行され、EVMは低レベルの命令セット(opcode)を用いて処理を行います。CREATE や CREATE2 は、新しいスマートコントラクトをデプロイするためのopcodeです。
*CREATE:一般的なスマートコントラクトのデプロイ手段。*CREATE2:特定の計算方法を用いてコントラクトアドレスを決定できる。
これらの仕組みを理解することで、スマートコントラクトの事前アドレス計算や資金送付の最適化が可能になります。
3. CREATEの仕組み
*CREATE** opcodeは、新しいスマートコントラクトをデプロイする際に利用されます。デプロイされたコントラクトのアドレスは、以下の要素から決定されます。*
keccak256(RLP_ENCODED(msg.sender+ nonce))
ここで、nonce はコントラクトを作成するアカウント(EOAまたはコントラクトアカウント)のトランザクション回数です。このため、任意のタイミングでコントラクトをでデプロイしたときのコントラクトアドレスを予測することができません。
4. CREATE2の仕組み
*CREATE2** opcode は EIP-1014 で導入され、より予測可能な方法でコントラクトのアドレスを決定できるようになりました。CREATE2 を使用した場合、コントラクトのアドレスは以下の式で決定されます。*
keccak256(0xFF + 創設者のアドレス + salt + keccak256(バイトコード))
ここで salt は任意の32バイトの値です。CREATE2 を使用することで、生成されるコントラクトアドレスがnonceに依存しなくなり任意のタイミングでデプロイする場合でもコントラクトアドレスを事前に計算することができます。
CREATE2の制約
- デプロイ時のバイトコードが一致している必要がある
- 事前に計算したアドレスと実際にデプロイされるアドレスが一致するためには、同じ
bytecodeを使用する必要があります。
- 事前に計算したアドレスと実際にデプロイされるアドレスが一致するためには、同じ
- 異なる
saltを用いると異なるアドレスが生成される*salt*を変更すると、同じコントラクトコードでも異なるアドレスが生成されます。*
- 事前にアドレスを計算できるが、バイトコードの変更は不可
- 事前に計算したアドレスに対してバイトコードを変更すると、意図したアドレスでデプロイできなくなります。
- デプロイにはコントラクトのみから実行可能で外部アカウントであるEOAからは呼び出し不可
CREATE2のユースケース
- 異なるチェーン間で同じコントラクトアドレスを使用したい場合
- デプロイ前にトランザクション署名が可能
- NFTををMintするコントラクトをデプロイする前に署名を事前に作成可能
- デプロイのタイミングを最適化&コントラクトアドレスを事前告知可能
デプロイ前に送金したETHの扱いについて
CREATE2 を使用すると、デプロイ前のアドレスが確定するため、実際にコントラクトがデプロイされる前に、そのアドレスへETHを送ることが可能になります。しかし、この時点ではそのアドレスにコードは存在しません。
EVMの仕様上、コードが存在しないアドレスに送金されたETHはそのアドレスにロックされ、誰もアクセスできなくなります。そのため、コントラクトが正しくデプロイされる前にETHを送る場合は、確実にデプロイできることを確認する必要があります
5. CREATE と CREATE2 の違い
| 項目 | CREATE | CREATE2 |
|---|---|---|
| アドレス計算 | keccak256(address + nonce) | keccak256(0xFF + address + salt + keccak256(bytecode)) |
| 事前計算 | 不可能 | 可能 |
| デプロイ方法 | 通常のトランザクション | saltを利用してアドレスを固定化 |
| 送金 | デプロイ前に送金できない | デプロイ前に送金可能 |
8. まとめ
*CREATE2*を活用すると、特定のアドレスでのスマートコントラクトの動作を保証できる。**computeAddress*関数を活用することで、デプロイ前にコントラクトアドレスを予測できる。*

