anvil のdeploy proxy をEVMアセンブリ解析してみた

FoundryのテストネットツールAnvilにはデフォルトでCREATE2 Deployerというコントラクトが `0x4e59b44847b379578588920ca78fbf26c0b4956c`に入っています。実際のメインネットにもありますがetherscanにもソースコードがないんですよね。　使い方がよくわからなかったので調べてみました。

#### 先に結論
`CREATE2_FACTORY.call(abi.encodePacked(salt32bytes,initCode))`
先頭に32bytesのsaltをつけてあげたcreationCodeをなげるとよいです。

##### deply proxy EVM アセンブリ解析
これがそのgithubなのですが、コントラクトはYULで書かれています。
https://github.com/Arachnid/deterministic-deployment-proxy

YULがよくわからないのでアセンブリからみてみました。（コードが短いしEVMアセンブラの勉強もかねて。）
以下がruntimeコードです。Foundryのツール`cast code <contract-address> -d`でEVMアセンブラが表示できます。
```
root@aaa:/root# cast code 0x4e59b44847b379578588920ca78fbf26c0b4956c -d
00000000: PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0
00000021: CALLDATASIZE
00000022: ADD
00000023: PUSH1 0x0
00000025: DUP2
00000026: PUSH1 0x20
00000028: DUP3
00000029: CALLDATACOPY
0000002a: DUP1
0000002b: CALLDATALOAD
0000002c: DUP3
0000002d: DUP3
0000002e: CALLVALUE
0000002f: CREATE2
00000030: DUP1
00000031: ISZERO
00000032: ISZERO
00000033: PUSH1 0x39
00000035: JUMPI
00000036: DUP2
00000037: DUP3
00000038: REVERT
00000039: JUMPDEST
0000003a: DUP1
0000003b: DUP3
0000003c: MSTORE
0000003d: POP
0000003e: POP
0000003f: POP
00000040: PUSH1 0x14
00000042: PUSH1 0xc
00000044: RETURN

```

以下がEVMアセンブリとスタックの状態。EVMはレジスタを持っていないでStackで操作するスタックマシンです。


| hex | opcode and operand                                                           | stack                                                                                |
|-----|------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|
| 0   |  PUSH32   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 | {0xfff…e0}                                                                           |
| 21  |  CALLDATASIZE                                                                | {len(msg.data)} {0xfff…e0}                                                           |
| 22  |  ADD                                                                         | { len(msg.data)-0x20}                                                                |
| 23  |  PUSH1 0x0                                                                   | {0x0} { len(msg.data) - 0x20}                                                        |
| 25  |  DUP2                                                                        | {len(msg.data) - 0x20} {0x0} {len(msg.data)-0x20}                                    |
| 26  |  PUSH1 0x20                                                                  | {0x20}{len(msg.data)-0x20} {0x0} {len(msg.data)-0x20}                                |
| 28  |  DUP3                                                                        | {0x0} {0x20}{len{msg.data)-0x20} {0x0} {len(msg.data)-0x20}                               |
| 29  |  CALLDATACOPY                                                                | {0x0} {len(msg.data)-0x20}                                                           |
| 2a  |  DUP1                                                                        | {0x0}{0x0} {len(msg.data)-0x20}                                                      |
| 2b  |  CALLDATALOAD                                                                | {msg.data[0:32]} {0x0} {len(msg.data)-0x20}                                          |
| 2c  |  DUP3                                                                        | {len(msg.data)-0x20} {msg.data[0:32]} {0x0} {len(msg.data)-0x20}                     |
| 2d  |  DUP3                                                                        | {0x0} {len(msg.data)-0x20} {msg.data[0:32]} {0x0} {len(msg.data)-0x20}               |
| 2e  |  CALLVALUE                                                                   | {msg.value} {0x0}   {len(msg.data)-0x20} {msg.data[0:32]} {0x0} {len(msg.data)-0x20} |
| 2f  |  CREATE2                                                                     | {newaddress}  {0x0}   {len(msg.data)-0x20}                                           |
| 30  |  DUP1                                                                        | {newaddress } {newaddress} {datacopy} {0x0} {len(msg.data)-0x20}                     |
| 31  |  ISZERO                                                                      |                                                                                      |
| 32  |  ISZERO                                                                      | { 0x1 } {newaddress}  {0x0}   {len(msg.data)-0x20}                                   |
| 33  |  PUSH1 0x39                                                                  | {0x39} { 0x1 } {newaddress}  {0x0}   {len(msg.data)-0x20}                            |
| 35  |  JUMPI                                                                       | {newaddress} {datacopy} {0x0} {len(msg.data)-0x20}                                   |
| 36  |  DUP2                                                                        |                                                                                      |
| 37  |  DUP3                                                                        |                                                                                      |
| 38  |  REVERT                                                                      |                                                                                      |
| 39  |  JUMPDEST                                                                    |                                                                                      |
| 3a  |  DUP1                                                                        | {newaddress} {newaddress} {0x0} {len(msg.data)-0x20}                                 |
| 3b  |  DUP3                                                                        | {0x0} {newaddress} {newaddress} {0x0} {len(msg.data)-0x20}                           |
| 3c  |  MSTORE                                                                      | {newaddress} {0x0} {len(msg.data)-0x20}                                              |
| 3d  |  POP                                                                         | {0x0} {len(msg.data)-0x20}                                                           |
| 3e  |  POP                                                                         |  {len(msg.data)-0x20}                                                                |
| 3f  |  POP                                                                         |                                                                                      |
| 40  |  PUSH1 0x14                                                                  | {0x14}                                                                               |
| 42  |  PUSH1 0xc                                                                   | {0xc} {0x14}                                                                         |
| 44  |  RETURN                                                                      | ( mem[0xc: 0xc+0x14] )　なのでアドレスを返す。                                                                   |


- `0x29 CALLDATACOPY` の引数は`{0x0} {0x20} {msg.len)-0x20}` これは msg.dataの0x20番目からメモリの0x00番地にコピーしています。長さは実際のcalldataから0x20引いた値です。
- `0x2f CREATE2`の引数を見ると　`{msg.value} {0x0} {len(msg.data)-0x20} {msg.data[0:32]}`で仕様はvalue,ofset,length,saltになっておりoffset からlengthは`0x29 CALLDATACOPY`でコピーしたデータです。
- またsaltはcalldataの先頭から32バイトを使用しているため calldataを`[ salt 32bytes] [ creation code ]`となるように投げてあげるとよさそうです。


##### forge scriptでのデプロイコード

```
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Script} from "forge-std/Script.sol";
import {NFT} from "src/NFT.sol";
import {Factory} from "src/Factory.sol";
import "forge-std/console.sol";

contract DeterministicDeploy is Script {
    // CREATE2_FACTORY

    function run() public {
        bool success;
        bytes memory data;
        bytes32 salt=0x0102030400000000000000000000000000000000000000000000000000000000;
        vm.broadcast();
        bytes memory creationBytecode = type(NFT).creationCode;
        bytes memory initCode = abi.encodePacked(creationBytecode, abi.encode("NFT contract","NFT","http://mynft.org"));
        (success, data) = CREATE2_FACTORY.call(abi.encodePacked(salt,initCode));
        address newaddr = address(uint160(bytes20(data)));
        console.logAddress(newaddr);
        bytes memory bytecode = abi.encodePacked(bytes1(0xff),address(CREATE2_FACTORY),salt,keccak256(initCode)); 
        address newaddr2 = address(uint160(uint(keccak256(bytecode))));
        console.logAddress(newaddr2);
    }
}
```
結論は先頭に32bytesのsaltをつけてあげたcreationCodeをなげるとよいです。ちゃんとgithubにも`The data should be the 32 byte 'salt' followed by your init code.`ってかいてありました。


##### 改めてYUL を読む
EVMアセンブリ解析のあとにYULを読むと意味がわかってきました。
```
object "Proxy" {
	// deployment code
	code {
		let size := datasize("runtime")
		data
  copy(0, dataoffset("runtime"), size)
		return(0, size)
	}
	object "runtime" {
		// deployed code
		code {
			calldatacopy(0, 32, sub(calldatasize(), 32))
			let result := create2(callvalue(), 0, sub(calldatasize(), 32), calldataload(0))
			if iszero(result) { revert(0, 0) }
			mstore(0, result)
			return(12, 20)
		}
	}
}
```
まずこれは`CreationCode`というものでインストールパッケージみたいなものです。
https://github.com/Arachnid/deterministic-deployment-proxy
- はじめの object "Proxy"配下の`code { } `は実行コードをメモリにコピーします。こちらの"runtime"となっている部分がデプロイされる実行コードです。
- コンストラクタがあればこの `code{}`配下にはいります。今回はありません。
- デプロイされるとobject "runtime"以下がEVMのオンチェーンに保存されます。`deployedBytecode`とも言われます。
- `cast code <address> -d`で表示されるコードは"rumtime"以下の`deployedBytecode`になります。

rumtime以下の実行コードは
- calldatacopy(0, 32, sub(calldatasize(), 32)) で　msg.dataの32バイトをスキップして最後までメモリに記入
- create2の引数はcallvalue, コピーされたCreationCodeのメモリの位置、creationCodeの長さ、salt
- saltはcalldataload(0)で最初の32バイトを持ってきている