Rand Protocol
ドキュメント
RISC-V プログラム

Ethereum トランスパイラ

evm2rv は、EVM のランタイムバイトコードを Rand の RISC-V ISA に変換します。本ページでは、その概要、信頼モデルとコードガード、対応するオペコードとプリコンパイル、およびトラップする箇所、実測値を説明し、さらに Solidity から solc --bin-runtime を経て、EVM インタプリタと一語一句一致する出力に至るまでの ERC-20 の完全なウォークスルーを示します。

evm2rv は、solc --bin-runtime の出力である EVM ランタイムバイトコードを受け取り、Rand プログラムに変換します。出力は C で、rand-guest build がその C を RV32IM イメージにコンパイルします。このイメージは、Rand の EVM インタープリタゲスト evm.bin と同じ入力ベクトルを受け取り、同じ 8 個の出力ワードを公開します。コントラクトをオペコードごとに解釈するのではなく、ネイティブに実行します。このページでは、ERC-20 を例に全体の流れを示します。

概要

入力EVM ランタイムバイトコード。16 進テキスト(.hex)または生のバイト列
出力C のシム crate。rand-guest build でイメージコンテナにします
実行場所オフチェーン、開発者のマシン上。チェーンが見るのはイメージだけです
一致が必要なものevm.bin のステータス、8 個の出力ワード、gas_used
リポジトリcircuits リポジトリの evm2rv/
固定されたツールチェーンRust 1.98.1、clang 23.1.1、cc crate 1.4.6

トランスパイラが受け取るのは、作成コードではなくランタイムコードです。証明の対象はデプロイ済みコントラクトへの 1 回の呼び出しであり、コンストラクタは実行されません。コンストラクタが書き込むはずの状態は、代わりにストレージウィットネスとして事前状態に含まれます。

変換には 2 つのステージがあります。どちらも結果とガスは同じで、それぞれが独自の hc を持つ別のプログラムです。

ステージフラグ内容
1--stage 1すべてのオペコードをメモリ上のスタックで処理します
2--stage 2(デフォルト)各ブロックのスタックワードを C のローカル変数に置き、定数を変換時に畳み込みます

入力ベクトルはインタープリタのものと同じです。コード、calldata、呼び出し元などの環境ワード、ガスリミット、事前状態ルート、そして呼び出しが触れるスロットごとに 1 つのストレージウィットネスで構成されます。出力は out[0] のステータス(1 が成功、0 がリバート、2 が例外的停止)と、out[1..8] の EVM_OUT ダイジェストです。このダイジェストは、コードハッシュ、両方の状態ルート、返却データ、ログにわたります。

信頼モデル

検証者は、変換済みコントラクトを 2 段階で確認します。

  1. hc == translate(bytecode)。 公開されたバイトコードに対して、同じ --stage と --chain-id で evm2rv を再実行し、固定されたツールチェーンで再ビルドして hc を比較します。生成される crate は cc を正確なバージョンに固定し、独自の Cargo.lock を持ちます。
  2. コードガードが hc をバイトコードに結び付けます。 変換されたロジックはイメージにコンパイルされますが、CODECOPY と CODESIZE は入力ベクトル内のコードを読みます。チェックがなければ、1 つの hc が、呼び出し側の選んだコードバイトで実行されうることになります。そのため contract.c には元のバイトコード(その長さとバイト列)の Poseidon2 ダイジェストが含まれ、シムは変換済みコードを実行する前に、入力ベクトルのコードを同じ方法でハッシュします。それ以外のコードは拒否されます。ステータスは 2、gas_used は 0、停止理由は OutOfBounds です。

EVM_OUT ダイジェストは、インタープリタのものと同様に、コードの keccak256 にも結び付いています。チェーンは元のバイトコードもそのハッシュも記録しません。他者が hc を確認できるようにするには、バイトコード、または Solidity ソースと正確な solc ビルドを公開してください。

コードガードのコストは、transfer で 1,008 サイクルです。ソースと 1 バイトでも異なるコードは、ステージ 2 で 30,418 サイクルで拒否されます(ティア 16)。

対応範囲とトラップ

オペコード。 Shanghai のセットです。--evm-version shanghai でコンパイルしてください。より新しいターゲットは MCOPY などの Cancun のオペコードを出力し、これらはトラップします。

環境オペコード:

オペコード変換
ADDRESS, CALLER, CALLVALUE, CALLDATASIZE, CODESIZEインタープリタと同様に、入力ベクトルから読みます
CHAINID--chain-id の値を変換時に埋め込むため、hc がそれに結び付きます。コードに CHAINID が含まれる場合は必須です
ORIGINCALLER と等しくなります(呼び出しは 1 回で、リレイヤーはありません)
GASPRICE, COINBASE, TIMESTAMP, NUMBER, PREVRANDAO, GASLIMIT, SELFBALANCE, BASEFEE, BLOCKHASHインタープリタと同じくトラップします(ステータス 2)

9 個のブロックコンテキストオペコードは、ブロックに結び付ける設計ができるまでトラップします。非公開入力はブロックの事実を運べません。検証者が H_IN を開けないためです。この判断が下るまで、時刻やブロック番号を読むコントラクト(たとえば permit の期限)はトラップします。

呼び出し。 CALL、CALLCODE、DELEGATECALL、STATICCALL は、宛先がアドレス 1〜9 のときにプリコンパイルを実行します。それ以外の宛先はトラップします。CALL または CALLCODE で 0 でない value を指定するとトラップします。 残高モデルがないためです。

プリコンパイル。 9 つすべてがソフトウェアで動作します。1 つの証明が保持できる行数は最大 2²⁰ であるため、現状では証明するには遅すぎるものがあります。

プリコンパイルベクトルサイクル2²⁰ に収まるか
1 ecrecoverValidKey14,510,525いいえ
2 sha256”abc” / 200 バイト2,791 / 5,289はい
3 ripemd160”abc”12,195はい
4 identity100 バイト4,498はい
5 modexpnagydani-1-square / -1-pow0x10001122,332 / 874,548はい
5 modexpeip_example1(256 ビット)11,170,118いいえ
5 modexpnagydani-5-pow0x10001(1,024 バイト)55,076,950いいえ
6 bn256 addchfast1978,262はい、ぎりぎりです
7 bn256 mulchfast13,060,669いいえ
8 bn256 pairing1 ペア / 2 ペア1,853,656,212 / 2,019,000,469いいえ
9 blake2f12 ラウンド14,493はい、約 1,800 ラウンドまで

modexp の base と modulus は、それぞれ 1,024 バイトが上限です。

許容される差異。 ステータス、8 個のワード、gas_used は一致しなければなりません。次の 3 つの差異は許容されます。停止の種類が異なる場合があること(静的ガスは各ブロックの先頭で課金されるため、OutOfGas と別の停止が入れ替わることがあります。どちらもステータスは 2 で、ガスはすべて消費されます)。変換が CHAINID、ORIGIN、プリコンパイル呼び出しを実装していること(インタープリタはこれらをトラップします)。そしてコードガードが、ソース以外のコードを拒否することです。

計測値

コードガードを含めた ERC-20 の呼び出しです。サイクルは rand-guest run の値で、括弧内はティアです。

呼び出しインタープリタ(evm.bin)ステージ 1ステージ 2(デフォルト)
transfer(BOB, 250)121,638 (18)80,211 (18)66,235 (18)
approve(BOB, 5)85,645 (18)56,261 (16)48,119 (16)
transferFrom(ALICE, BOB, 100)161,434 (18)110,074 (18)88,824 (18)
プログラムワード数hc
evm.bin、インタープリタ18,0097e1aea2b…854c08
ERC-20、ステージ 115,8049cdb79e7…2fd048c8
ERC-20、ステージ 211,686a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6

ステージ 2 は、3 つの呼び出しをインタープリタのサイクル数のそれぞれ 54.5%、56.2%、55.0% で実行します。transfer はティア 18 のままです。66,235 サイクルに 3,155 行のダイジェストを加えると 69,390 行となり、ティア 16 の 65,535 を 3,855 行超えます。

ステージ 2 の transfer のおよそ 60%(約 39,928 サイクル)は、両方のイメージが共有するハーネスです。入力のデコード、ストレージウィットネスの検証、ABI の keccak256 呼び出し、出力ダイジェストがそれにあたります。どんな変換作業も、この下限より下には進めません。

ウォークスルー: ERC-20 を Solidity から一致する出力まで

すべてのコマンドは、7ef3220 の circuits チェックアウトのルートから実行します。ツールチェーンは Rust プログラムのデプロイのもの、clang 23.1.1 は RISC-V プログラムのデプロイのものを使います。長い出力は … の箇所で省略しています。

0. ツールをビルドする

(cd evm2rv && cargo +1.98.1 build --release)
(cd rand-guest && cargo +1.98.1 build --release)

1. Solidity をランタイムバイトコードにコンパイルする

コントラクトは、コミット済みの guests-compiled/evm/contracts/ERC20.sol です。OpenZeppelin v4 のストレージレイアウトを持つ自己完結型の ERC-20 で、pragma solidity 0.8.37 を使います。solc は必ず 0.8.37 を使ってください。別のバージョンでは最適化が異なり、バイトコードも変わります。

リリースgithub.com/ethereum/solidity/releases の v0.8.37
macOS のアセットsolc-macos、sha256 a27396e7732aa52e80ff89ad7bd8a2e46fec2a6dcc4ef20cd16e5e0c502d6821
Linux のアセット同じリリースの solc-static-linux
$ curl -sSL -o solc https://github.com/ethereum/solidity/releases/download/v0.8.37/solc-macos
$ shasum -a 256 solc
a27396e7732aa52e80ff89ad7bd8a2e46fec2a6dcc4ef20cd16e5e0c502d6821  solc
$ chmod +x solc && ./solc --version
solc, the solidity compiler commandline interface
Version: 0.8.37+commit.f401782d.Darwin.appleclang

$ (cd guests-compiled/evm && ../../solc --optimize --optimize-runs 200 --evm-version shanghai \
      --bin-runtime contracts/ERC20.sol) | tee solc.out
======= contracts/ERC20.sol:ERC20 =======
Binary of the runtime part:
608060405234801561000f575f5ffd5b5060043610610060575f3560e01c8063095ea7b31461006457806318160ddd1461008c57806323b872dd1461…
$ tail -1 solc.out > evm2rv/target/mytoken.hex

最後の行がランタイムバイトコードで、1,296 バイトです。コミット済みの guests-compiled/evm/contracts/erc20.runtime.hex とバイト単位で一致します。SOLC=$PWD/solc bash guests-compiled/evm/contracts/build.sh がそれを確認し、contracts: erc20.runtime.hex reproduces と出力します。

フラグには意味があります。

  • --bin-runtime: 作成コードではなく、デプロイされるコードを出力します。
  • --evm-version shanghai: 0.8.37 のデフォルトターゲットは MCOPY を出力し、これはトラップします。
  • --optimize --optimize-runs 200: デプロイ済みコントラクト向けのプロファイルです。

2. 変換する

$ evm2rv/target/release/evm2rv evm2rv/target/mytoken.hex --out evm2rv/target/mytoken --chain-id 12
1296 code bytes: 74 blocks, 798 opcodes, 51 jumpdests (stage 2)
CHAINID is the constant 12
no trapping opcodes present
wrote evm2rv/target/mytoken (crate mytoken): contract.c, Cargo.toml, Cargo.lock, build.rs, src/main.rs, shim.ld
  • --out は circuits チェックアウトの内側でなければなりません。指定しない場合、evm2rv はコードの解析だけを行います。
  • トラップするオペコードがあれば、pc とともに警告としてここに列挙されます。
  • このセッションは --chain-id 12 で記録したものです。この ERC-20 は CHAINID を使わないため、--chain-id はその hc を変えません。CHAINID を読むコントラクトではこのフラグが必須です。デプロイ先のチェーンを指定してください(稼働中のチェーンなら --chain-id 19)。

contract.c は、コードガードのダイジェストで終わります。

const uint32_t *evm_code_digest(void) {
    static const uint32_t d[8] = {0xf679280fu, 0x86c10e83u, 0x7e8f1f39u, 0xa2377de3u, 0x8a2e282fu, 0xc54cad42u, 0xddfaf009u, 0x7d28a8afu};
    return d;
}

3. イメージをビルドする

デフォルトの上限は 4,096 ワードなので、--max-words 65535 を渡します。

$ rand-guest/target/release/rand-guest build evm2rv/target/mytoken --max-words 65535
…
11686 words against a cap of 65535 (fits); 0 ecall(s) with a non-static a7
OK
wrote evm2rv/target/mytoken/image.bin and its .sha256 (11686 words, hc a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6, program id f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d)

$ rand-guest/target/release/rand-guest info evm2rv/target/mytoken/image.bin
form: image container
text 11147 words at 0x10000; data 408 words (205 non-zero) at 0x1ae2c; prologue 539 words; program 11686 words from base_pc 0xf794
hc a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6
program id f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d
11686 words against a cap of 4096: does not fit

これが公開されているステージ 2 の hc です。crate 名はこれに影響しません。

4. 入力ベクトルを作成して transfer を実行する

erc20_vector の例は、パリティテストのベクトルを入力ワードとして出力します。transfer(ALICE が 1,000 のうち 250 を BOB に送る)、approve(ALICE が BOB に 5 の使用を許可する)、transferFrom(BOB が、許可額 300 のもとで ALICE の 1,000 のうち 100 を移す)です。ご自身のコントラクトでは、Rust で同じように EvmCall を組み立ててください。この例がテンプレートになります。

$ (cd evm2rv && cargo +1.98.1 run -q --release --example erc20_vector -- transfer > target/transfer.words)
921 input words

$ rand-guest/target/release/rand-guest run evm2rv/target/mytoken/image.bin --input $(cat evm2rv/target/transfer.words)
out[0] = 1
out[1] = 513227413
out[2] = 3087537901
out[3] = 995619457
out[4] = 4004100029
out[5] = 234390638
out[6] = 3262201797
out[7] = 3842361427
cycles 66235
tier 18

5. インタープリタと比較する

同じ入力をインタープリタゲストで実行します。

$ rand-guest/target/release/rand-guest run guests-compiled/bin/evm.bin --input $(cat evm2rv/target/transfer.words)
out[0] = 1
out[1] = 513227413
out[2] = 3087537901
out[3] = 995619457
out[4] = 4004100029
out[5] = 234390638
out[6] = 3262201797
out[7] = 3842361427
cycles 121638
tier 18

そして、ホスト上でネイティブに実行したインタープリタ(テストのオラクル)です。

$ (cd evm2rv && cargo +1.98.1 run -q --release --example erc20_vector -- transfer --expected)
out[0] = 1
out[1] = 513227413
…
out[7] = 3842361427
interpreter (native): status 1, Return, gas_used 29956

チェックを1つのコマンドにまとめると次のとおりです。

$ diff <(rand-guest/target/release/rand-guest run evm2rv/target/mytoken/image.bin --input $(cat evm2rv/target/transfer.words) | grep '^out') \
       <(rand-guest/target/release/rand-guest run guests-compiled/bin/evm.bin --input $(cat evm2rv/target/transfer.words) | grep '^out') \
  && echo "the eight words are identical"
the eight words are identical

手順4と5を approve と transferFrom で繰り返します。どちらも同一のワードになります。cd evm2rv && cargo +1.98.1 test --release は、これらに加えて5つのベクターを両方のステージで実行し、gas_used も検証します(70件のテストと、無視される2件の証明)。

変換後(ステージ2)インタープリタ(evm.bin)
8個の出力ワード同一同一
サイクル数(transfer)66,235121,638
ティア1818
プログラムワード数11,68618,009

6. デプロイ

rand program deploy evm2rv/target/mytoken/image.bin

ウォレットはプログラム ID、ワード数、hc を出力し、その後、証明を行う前にチェーンの上限を確認します。イメージは 11,686 ワードであるため、ジェネシスで max_program_words が 11,686 以上に設定されたチェーンが必要です。チェーン12はデフォルトの 4,096 で動いていたため、そこではデプロイが拒否されました。v0.4 のチェーンであるチェーン13は max_program_words を 65,535 に設定し、以降のすべてのチェーンがこの値を維持しています。稼働中のチェーンであるチェーン20(ジェネシス 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135)も、チェーン13のブロック、コールエンベロープ、パブリック入力の上限を維持し、証明の上限を 4 MiB(4,194,304 バイト。チェーン17以降。チェーン13から16は 8 MiB)に半減しています。ワード数の上限だけが関門ではなくなりました。チェーン20のジェネシスは hardening_v6 を設定しており、これにより、ティア14のコール上限で1回のコールが保持できるプログラムワード数を超えるデプロイは無効になります(ProgramUncallable)。パブリック入力がない場合、上限は 8,180 ワードです。このイメージは 11,686 ワードであるため、チェーン20はデプロイを拒否し、コールも拒否します。ERC-20 のコールはいずれもティア16または18で証明され、ティア14のコール上限を超えるためです(手順7)。チェーン20ではブロックアグリゲーションは無効です(ジェネシスに aggregation セクションがありません)。ブートストラップノードは Running a validator に記載されています。デプロイ手数料は 0.001 + 0.0001 × 11,686 = 1.1696 RAND で、これは下記のチェーン13でのデプロイで支払われた手数料です。

このデプロイは、チェーン13が稼働中のチェーンであった 2026-09-19 に、チェーン13(本番の FRI プロファイル、ジェネシス 8123ccac1883a45750e4df6964fb7cd3f0b321798cde4c0ef406a0293939ece3)上で、ジェネシスウォレット shielded-1 から実行されました。以降のチェーン(14から19)はいずれもチェーン13のプログラムを持たない新しいチェーンとして切り出され、イメージはそのいずれにも再デプロイされていません。したがって、下記のトランザクションと高さはチェーン13のものであり、エクスプローラーでは解決できません。プログラム ID は base_pc とワードのみのハッシュであるため、デプロイを受け入れるチェーンであれば、同じイメージは同じ ID になります。ウォレットの出力です(進捗行は省略しています: …)。

$ rand program deploy <image.bin>
program id: f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d (11686 words, hc 92aefea0951c31a717574962aeb70e10a37012a7d035d48e8713c36df68feae0)
…
proved in 92.2s: tier 14, 1419655 bytes
submitted deploy c7a66dc4d9cdb7f9bfc4bde01f618c356e5abad7097e6bf7dc04e2e49c53acd0
…
プログラム IDf074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d
イメージ11,686 ワード。rand-guest の表記では hc a0feae92…、ウォレットの表記では 92aefea0…
手数料バンドル(チェーン13の 2-in-2-out バンドル)ティア14、1,419,655 バイト、92.2 秒で証明
デプロイ tx(チェーン13)c7a66dc4d9cdb7f9bfc4bde01f618c356e5abad7097e6bf7dc04e2e49c53acd0
コミット時の高さ(チェーン13)381

チェーン14以降、手数料を支払うバンドルは、すべてのトランザクションが持つ 4-in-4-out の隠蔽アセットバンドル1つであり、トランザクションのバインディングに対して証明されます。ティアは引き続き14です。チェーン14と15の本番プロファイルでは、約100秒、約 1.42 MB です。チェーン17以降はバンドルに ティア10の認可証明(分割認可)も付くため、チェーン18と19では、トランザクションの手数料バンドルはバンドル証明が約 1.49 MB、認可証明が約 1.37 MB になります。

7. コール

transfer のコールは、921ワードのベクターをプライベート入力として持ち、どのチェーンでも入力上限の範囲内に収まり(デフォルトでは 4,295 ワード、チェーン20では 16,071 ワード)、パブリックワードはありません。チェーン20には送信できません。 プログラムをそこにデプロイできず(手順6)、transfer はティア18で証明され、fullnode v0.5.6(2026-09-25)以降、ノードはティア14を超えるコール証明を、検証鍵を構築する前に CallTierTooHigh で拒否するためです。以下のコマンドはローカルで証明を行い、チェーンはその結果を拒否します。測定値はオフチェーンの証明によるものです。rand call は各ワードを繰り返しの --input として受け取ります。

rand call f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d \
    $(for w in $(cat evm2rv/target/transfer.words); do printf -- '--input %s ' "$w"; done)

測定結果は次のとおりです。ティア18の証明は、48 GB のラップトップでは 24.7 GB の時点で強制終了されましたが、128 GB のドロップレット(m-16vcpu-128gb)では、変換後の transfer コールが証明されました。ピーク RSS は 85.0 GB、3,230.5 秒(53.8分)、証明サイズは 811,600 バイトです。検証にはドロップレットで 101.4 秒、48 GB の Apple シリコン搭載ラップトップで 3.66 GB RSS、50.2 秒かかりました(証明のメモリ)。gas セクションのないチェーン(チェーン17まで)の規則であるレジャーの固定ティアスケジュールでは、ティア18のコール手数料は 0.0024 RAND でした。チェーン18と19は、コールを、宣言されたガス上限とそのバイト数で価格付けします。ジェネシス価格では、ガス1単位あたり 100、KiB あたり 800 です。また、ティア14を超えるコールは受け付けません。

チェーン13でのコール(2026-09-19)

approve(BOB, 5) のコール(649プライベートワード、ティア16)は、チェーン13が稼働中のチェーン(本番 FRI プロファイル)であった 2026-09-19 に、同じウォレットから実行されました。それ以降のチェーンではコールは行われておらず、プログラムもデプロイされていません。チェーン20は、このティア16のコール証明を拒否します(CallTierTooHigh)。ウォレットの出力です(進捗行は省略しています: …)。

$ rand call f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d --input <w0> --input <w1> …   # the 649 words of approve(BOB, 5)
…
proved in 388.7s: tier 16, 3412405 bytes, outputs [1, 942495465, 790002515, 1351749335, 1059083501, 2923046783, 2814575942, 696258848]
…
proved in 96.0s: tier 14, 1420423 bytes
submitted call 279e1f62abf3f177ca71b08c633e051c37bc4720118c79ddb00936f036c4bfa7
…
コール証明ティア16、3,412,405 バイト、388.7 秒で証明
手数料バンドル(チェーン13の 2-in-2-out バンドル)ティア14、1,420,423 バイト、96.0 秒で証明
シールされたエンベロープ2,700 バイト
コール tx(チェーン13)279e1f62abf3f177ca71b08c633e051c37bc4720118c79ddb00936f036c4bfa7
アンカー時 / コミット時高さ 802 / 高さ 919
手数料0.00357 RAND
レシート h_pubnull
レシート出力同じベクターに対するインタープリタの8ワードと等しい
経過時間、ピーク RSS622.8 秒、22.9 GB、48 GB の M シリーズ搭載ラップトップ上
  • 本番の証明は 3,412,405 バイトで、チェーン12の 2 MiB の証明上限を超えています。チェーン12はこのコールを受け付けられませんでしたが、チェーン13の 8 MiB の上限では受け付けられました。チェーン14から16も同じ上限を維持し、チェーン17から20は 4 MiB(4,194,304 バイト)に設定しましたが、この大きさの証明はそれでも収まります。v0.5.6 以降、ノードはサイズを確認する前に、ティアを理由にこのコールを拒否します。
  • 手数料には、チェーン13のスケジュールのバイト項が含まれます。3.41 MB の証明は、2 MiB + 18,432 バイトの無料枠を超えています。チェーン18以降、すべてのコールは 0 バイト目から KiB 単位で支払います。

レシートの8ワードは手順4のものです。チェーンは EVM の状態を保持しません。呼び出し側が事前状態ルートとストレージウィットネスを提供し、事後状態ルートは EVM_OUT ダイジェストの中にあります。

Limits

  • ブロックコンテキストなし。 ブロックコンテキストを扱う9つのオペコードは、ブロックへの結び付けの設計が定まるまでトラップします。
  • 価値の移転なし。 値がゼロでない CALL はトラップします。プリコンパイル以外のコントラクトへの呼び出しもトラップします。
  • ecrecover、bn256 の乗算、ペアリング、大きな modexp は現時点では証明できません。 いずれも 2²⁰ 行のティア上限を超えるため、コプロセッサテーブルが必要です。
  • チェーン上に EVM の状態はありません。 呼び出しは1回の実行に対する1つの証明であり、状態は呼び出し側が保持します。
  • デプロイも ERC-20 の呼び出しも、chain 20 ではオンチェーンで受理されません。 chain 20 の hardening_v6 では、tier 14 の呼び出しが保持できる語数を超えるデプロイは無効であり(ProgramUncallable。最大 8,180 語)、イメージは 11,686 語です。fullnode v0.5.6 以降、呼び出しの証明は tier 14 以下でなければなりません(CallTierTooHigh)。approve は tier 16、transfer と transferFrom は tier 18 で証明されます。同じチェックにより、呼び出しが宣言できるハッシュテーブルにも上限があります。Keccak は 2¹² 行(128 回の置換)、SHA-256 は 2¹³ 行(128 回の圧縮)です。呼び出し自体は、以下のとおりオフチェーンでなら引き続き証明できます。
  • ストレージインデックスの深さは32ビットです。 evm-core は、コントラクトのストレージのリーフを keccak256(slot) の上位32ビットで配置します。そのため、選ばれたスロットと衝突するスロットを見つけるには約 2³² 回の Keccak ハッシュが必要で、衝突したスロットが非ゼロの値を保持している間は、選ばれたスロットが凍結されます(偽造も値の消失も起きません)。これは現在は休眠状態です。evm.bin は 18,009 語であり、tier 14 の上限での呼び出しが保持できるのは最大 8,184 語のため、どのチェーンでも呼び出せる EVM ランタイムはありません。fullnode の docs/confidential.md には、この前提条件が呼び出し上限の隣に記録されています(監査 v6、ZKV-6。v0.6.7 タグの後、2026-09-30 から main に反映)。チェーンが tier 14 の呼び出し上限を引き上げる前、または呼び出せるほど小さい EVM ランタイムを受け入れる前に、ストレージインデックスを深くし、evm.bin を再固定しなければなりません。
  • 実証済み。 ステージ1の transfer 証明(tier 18)は、48 GB のノート PC では 1,016 秒後、24.7 GB の時点で SIGKILL されました。一方、ステージ2の transfer 呼び出しは 128 GB の droplet(m-16vcpu-128gb)で証明に成功しました。ピーク RSS は 85.0 GB、所要時間は 3,230.5 秒(53.8 分)、証明は 811,600 バイトで、検証には 101.4 秒(droplet)、50.2 秒・RSS 3.66 GB(48 GB のノート PC)かかりました。インタプリタの evm.bin による transfer 証明もほぼ同じ結果でした。85.5 GB、3,143.3 秒(52.4 分)、805,108 バイトの証明です。両者の証明は公開出力ワードが同一であり、実際のプルーバーでの同等性が確認されました。approve(tier 16、変換済み)ははるかに低コストです。21.7 GB、786.7 秒(13.1 分)、798,930 バイトの証明です。変換によって証明コストが下がるのは、呼び出しがより小さいティアに収まる場合に限られます。
  • チェーンはバイトコードを記録しません。 hc を他の人が再構築できるよう、バイトコードを公開してください。

fullnode のコミット c0878c3f(チェーン 21)に対して 2026-10-12 に最終確認しました。また、circuits `7ef3220` (`evm2rv/README.md`, `guests-compiled/evm/contracts/SOLC.md`, `docs/superpowers/specs/2026-09-18-evm-to-rv32-translator-design.md`); the walkthrough re-run on 2026-09-19 with solc 0.8.37。 コードとこのページが食い違う場合は、コードが正です。お知らせください。