odan blog

zkSync を試した

Rollup が熱いらしい。

チュートリアルをやる

L2 にデポジットする

  • チュートリアルのコードをコピペしてくる
async function main(): Promise<void> {
  const MNEMONIC = process.env.MNEMONIC!;
  const syncProvider = await zksync.getDefaultProvider("rinkeby");
  const ethersProvider = ethers.getDefaultProvider("rinkeby");

  // memo: 0x13FCd5b4348feFe49aAcf98275cBd9f5F2A2acd2
  const ethWallet = ethers.Wallet.fromMnemonic(MNEMONIC).connect(
    ethersProvider
  );

  console.log(ethWallet.address);

  const syncWallet = await zksync.Wallet.fromEthSigner(ethWallet, syncProvider);

  const deposit = await syncWallet.depositToSyncFromEthereum({
    depositTo: syncWallet.address(),
    token: "ETH",
    amount: ethers.utils.parseEther("0.00000000000001"),
  });

  console.log(deposit);

  console.log(await deposit.awaitReceipt());

  console.log(await deposit.awaitVerifyReceipt());
}
  • deposit.awaitReceipt の結果はわりとすぐ返ってくる
{
  executed: true,
  block: { blockNumber: 5090, committed: true, verified: false }
}

アカウントのアンロック

  if (!(await syncWallet.isSigningKeySet())) {
    if ((await syncWallet.getAccountId()) == undefined) {
      throw new Error("Unknown account");
    }

    const changePubkey = await syncWallet.setSigningKey({ feeToken: "ETH" });

    await changePubkey.awaitReceipt();
  }

実行しても次のエラーが出る

ZKSyncTxError: zkSync transaction failed: Not enough balance
    at Transaction.<anonymous> (/Users/odan/source/github.com/odan-sandbox/zksync-sandbox/node_modules/zksync/build/wallet.js:619:36)
    at Generator.next (<anonymous>)
    at fulfilled (/Users/odan/source/github.com/odan-sandbox/zksync-sandbox/node_modules/zksync/build/wallet.js:5:58)
    at processTicksAndRejections (node:internal/process/task_queues:93:5) {
  value: {
    executed: true,
    success: false,
    failReason: 'Not enough balance',
    block: { blockNumber: 5178, committed: true, verified: false }
  }
}

アカウントの状態を見る

  const { syncWallet } = await getProviderAndWallet(MNEMONIC);

  const state = await syncWallet.getAccountState();

  console.log({ state });
  • committed か verified な state を見ることができる
{
  state: {
    address: '0x13fcd5b4348fefe49aacf98275cbd9f5f2a2acd2',
    id: 6722,
    depositing: { balances: {} },
    committed: {
      balances: [Object],
      nonce: 1,
      pubKeyHash: 'sync:00b0ee1b1934ac8f606bceaebb6ffaf2ae520ee1'
    },
    verified: {
      balances: [Object],
      nonce: 1,
      pubKeyHash: 'sync:00b0ee1b1934ac8f606bceaebb6ffaf2ae520ee1'
    }
  }
}
  • pubKeyHash が committed と verified の両方にあるのは changePubKey 中は値が違うからかな

zkSync 上で ETH を転送

  const amount = zksync.utils.closestPackableTransactionAmount(
    ethers.utils.parseEther("0.01")
  );
  console.log({ amount });

  // 0xd2820FA24B72D7d25DE2C932dC40b10b0536e06C
  console.log(syncWallet2.address());

  const transfer = await syncWallet.syncTransfer({
    to: syncWallet2.address(),
    token: "ETH",
    amount,
  });
  console.log({ transfer });

  const transferReceipt = await transfer.awaitReceipt();
  console.log({ transferReceipt });

Ethereum に引き出す

  // 0xd2820FA24B72D7d25DE2C932dC40b10b0536e06C
  console.log(syncWallet2.address());
  const withdraw = await syncWallet2.withdrawFromSyncToEthereum({
    ethAddress: ethWallet2.address,
    token: "ETH",
    amount: ethers.utils.parseEther("0.001"),
  });

  console.log({ withdraw });

  console.log(await withdraw.awaitReceipt());

  console.log(await withdraw.awaitVerifyReceipt());
{
  value: {
    executed: true,
    success: false,
    failReason: 'Account is locked',
    block: { blockNumber: 5180, committed: true, verified: false }
  }
}

感想

  • L1 => L2 へは Ethereum を信頼すればいいから L2 => L1 にゼロ知識証明を使う感じ?
  • ゼロ知識証明周りの実装は Verifier.sol を見れば良さそう
  • Rollup は calldata が〜って言う話を聞いた事あったけど、コード追う感じだと deposit などの情報を普通に変数に保存しているぽくて謎
    • 変数に保存しておいて、後でまとめて実行しているって理解であっている...?