Kakarot 介紹:開發與範例

  • EthTaipei
  • 发布于 2024-10-10 17:27
  • 阅读 85

本文深入介绍了Kakarot与Ethereum的不同之处,包括操作码、预编译支持及合约开发示例,适合具备Solidity编程经验的开发者。文章通过细致的比较和实例,展示了Kakarot的功能和使用方式。

Author: ChiHaoLu ( chihaolu.eth )

Travel Preparations

本文繼前篇 Kakarot 介紹:Overview,會從開發的角度切入繼續介紹 Kakarot 相關內容,包含與 Ethereum 的差異和合約開發範例。在開始之前會希望讀者具備以下基本知識,可以更快掌握專有名詞和技術架構。

Differences between Kakarot and Ethereum

Opcodes

  • 在 Kakarot 中倒數十個區塊的 BLOCKHASH 會回傳 0,需要等待前篇提到的 Blockhash Registry 完成設定。且 Etherum 中 BLOCKHASH 的計算是 keccak256,而 Kakarot 是使用 pedersen。
  • 在 Kakarot 中沒有 Blob 的存在,所以 BLOBBASEFEE 會回傳 1。這個數字是根據 EIP-4844 的 MIN_BASE_FEE_PER_BLOB_GAS 定義。
  • 在 Kakarot 中 BLOBHASH 會回傳 0。

另外,在選擇 evm version 以及 solc version 時請確定當前的鏈支援 PUSH0 或以太坊升級會出現的新 opcodes。目前 Kakarot 是支援的,所以我們可以放心把合約版本設定在 0.8.19 以上和 shanghai。

Precompile

在 Precompile 這個議題可以分成幾個角度:

  • Kakarot 支援 EVM 的 precompile
  • Kakarot 支援 EVM 還不支援的 precompile
  • Kakarot 支援 StarkNet 的 precompile

首先在 EVM Precompile 的支援上,Kakarot 100% 支援 10 個合約中的 7 個,包含:

  • 0x01: ecRecover
  • 0x02: SHA2–256
  • 0x03: RIPEMD-160
  • 0x04: identity
  • 0x06: ecAdd
  • 0x07: ecMul
  • 0x09: blake2f

不支援的是:

  • 0x05: modexp
  • 0x08: ecPairing
  • 0x0a: point evaluation

而 P256 Verification (secp256r1 — RIP-7212) 這個 precompile 在 Ethereum 還不支持,若在 Ethereum 驗證目前還是使用 DAIMO P256 Verifer 為主,但是在 Kakarot 已經可以使用 precompile(0x100)完成驗證。

在 StarkNet 上,我們可以在 Kakarot 合約中呼叫 Cairo precompile(在 0x75001 上)這個合約來呼叫任何 Cairo 合約。由於這部分的使用需要與 Kakarot 官方聯繫,就不擴展篇幅,細節大家可見 官方文件

Development Example

Contract Side

這裡我們使用 Kakarot 官方文件 沒有提到的 Foundry 來做為範例開發,原始碼的連結在 ChiHaoLu/kakarot-foundry。基本上設定與命令我都已經寫好確定能跑了,大家只要把合約、測試、腳本改成自己的形狀就行(記得檔名改了指令也要記得改)。

在撰寫上和其他 EVM 相容的鏈一樣不能說很像,只能說幾乎一模一樣,我就不把程式碼貼過來佔版面了。在這邊我們測試在 Kakarot 的環境中能不能順利使用 ecrecover(0x01)這個 precompiled 合約。

function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) internal pure returns (address) {
    (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);

    return ecrecover(_ethSignedMessageHash, v, r, s);
}

在撰寫完合約之後,可以使用 — fork 指令來 fork 測試,參數填上 Kakarot 的 public RPC URL:

$ forge test --fork-url "https://sepolia-rpc.kakarot.org"

部署時依然可以使用同樣的 RPC URL:

$ forge script ./script/SignatureVerifier.s.sol --broadcast --rpc-url "https://sepolia-rpc.kakarot.org"

驗證時則比較麻煩,因為當前 Kakarot 的區塊瀏覽器是使用 Routescan,和 Etherscan 那套不一樣,所以這邊在驗證上我們要自己提供 — verifier-url 為在 Routescan 上驗證的 API URL。另外,當前在 Kakarot Sepolia 驗證不需要申請任何 API KEY,這邊在 key flag 只要給個字串 “kakarot_sepolia” 就行:

$ forge verify-contract 0x99682dAc0D03F0D12392dCE0B0E34f4AaD0b56E1 ./src/SignatureVerifier.sol:SignatureVerifier \
--verifier-url 'https://api.routescan.io/v2/network/testnet/evm/1802203764_2/etherscan' \
--etherscan-api-key "kakarot_sepolia" \
--num-of-optimizations 200 \
--compiler-version "v0.8.26+commit.8a97fa7a"
>
Start verifying contract `0x99682dAc0D03F0D12392dCE0B0E34f4AaD0b56E1` deployed on kakarot-sepolia

Submitting verification for [src/SignatureVerifier.sol:SignatureVerifier] 0x99682dAc0D03F0D12392dCE0B0E34f4AaD0b56E1.
Submitted contract for verification:
        Response: `OK`
        GUID: `7e88936a-fe91-5599-9ede-cc19ba05dda9`
        URL: https://sepolia.kakarotscan.org/address/0x99682dac0d03f0d12392dce0b0e34f4aad0b56e1

請特別注意以下內容皆符合你自己的設定:

  • 合約路徑與名稱
  • 合約版本
  • 合約 optimizer

經過以上步驟後,就成功在 Kakarot 上部署並且驗證合約了!

Front-End Side

接下來我們來嘗試用 Metamask 簽岀合法簽章然後在我們剛剛部署的 Kakarot 合約通過驗證。原始碼的連結在 ChiHaoLu/kakarot-dapp。這個專案使用 viem 與 next.js 作為框架,細部程式碼就不貼上來,只講解比較重要的部分。

打開專案 yarn install 然後 yarn dev 即可直接嘗試!

在 viem 中已經有關於 Kakarot Sepolia 的網路資訊,我們就不用再把 RPC URL 等內容自己填上了,直接 import 即可。

import { kakarotSepolia } from "viem/chains";
import {
    createWalletClient,
    createPublicClient,
    custom,
    getContract,
    Address,
} from "viem";

const handleSignAndVerify = async () =>

    // Connect
    const publicClient = createPublicClient({
      chain: kakarotSepolia,
      transport: custom(window.ethereum!),
    });
    const walletClient = createWalletClient({
      chain: kakarotSepolia,
      transport: custom(window.ethereum!),
    });

    // 要求用戶的錢包將網路換為 Kakarot Sepolia
    await walletClient.switchChain({ id: kakarotSepolia.id });
    const contract = getContract({
      address: contractAddress as Address,
      abi: SignatureVerifierMetadata.abi,
      client: { public: publicClient, wallet: walletClient },
    }) as any;

    // remaining code...
};

簽章的部分我們 request Metamask 對 messageHash 進行簽名:

const handleSignAndVerify = async () =>
    // previous code...

    // Sign
    const [address] = await walletClient.requestAddresses();
    const messageHash = await contract.read.getMessageHash([message])
    const signature = await walletClient.signMessage({
      account: address,
      message: { raw: messageHash },
    });

    // remaining code...
};

最後可以使用 verify 得到簽章是否合法:

const handleSignAndVerify = async () =>
    // previous code...

    // Verify
    const verifyResult = await contract.read.verify([\
      address,\
      message,\
      signature,\
    ]) as boolean
};

Reference

TEM Medium 2024 有獎徵稿 TEM Medium 目前正在進行有獎徵稿!詳情請參考: https://medium.com/taipei-ethereum-meetup/tem-medium-2024-call-for-article-8412024c2390

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
EthTaipei
EthTaipei
Taipei Ethereum Meetup