Skip to content

docs: Ethereum integration guide#39

Merged
marc0olo merged 4 commits into
mainfrom
docs/guides-chain-fusion-ethereum
Apr 15, 2026
Merged

docs: Ethereum integration guide#39
marc0olo merged 4 commits into
mainfrom
docs/guides-chain-fusion-ethereum

Conversation

@marc0olo
Copy link
Copy Markdown
Member

@marc0olo marc0olo commented Mar 20, 2026

Summary

  • EVM RPC canister architecture: how ICP canisters call Ethereum via multi-provider consensus
  • Supported chains table (Ethereum, Arbitrum, Base, Optimism) with provider details
  • Reading onchain data: typed API (eth_getBlockByNumber, eth_getTransactionCount) and raw JSON-RPC
  • ERC-20 balance example with ABI-encoded calls (Motoko/Rust tabs)
  • Signing and sending transactions via threshold ECDSA + EVM RPC
  • Cycle cost table for all RPC methods
  • Development setup with local EVM RPC canister
  • Common mistakes table (5 pitfalls)

Sync recommendation

Informed by dfinity/portaldocs/building-apps/chain-fusion/ethereum/*; dfinity/icskillsskills/evm-rpc/SKILL.md; dfinity/cdk-rsic-cdk/src/management_canister.rs (ECDSA management canister API)

@marc0olo
Copy link
Copy Markdown
Member Author

Review: Ethereum integration guide

Must fix

  • --with-cycles flag does not exist for icp canister call (lines 635-648): The icp-cli reference shows --cycles <CYCLES> only when --proxy is specified. There is no general --with-cycles flag. The entire "Testing via icp-cli" section needs the correct approach documented or a {/* Needs human verification */} flag.
  • icp deps pull/init/deploy commands don't exist (lines 619-621): There is no deps subcommand in icp-cli at all. The local deployment section needs a correct approach for deploying the EVM RPC canister locally.
  • Motoko canister:evm_rpc import syntax: Per project note "Motoko named imports in flux", canister:name syntax doesn't work with icp-cli. All Motoko examples use import EvmRpc "canister:evm_rpc". At minimum add a {/* Needs human verification: canister:name import syntax may not work with icp-cli */} flag, or explain the alternative (importing by canister ID).
  • dfx_test_key in comments (lines 382, 408): Comments say // Use "dfx_test_key" locally. While this is a protocol-level key name, mentioning dfx in a comment violates the spirit of the no-dfx rule. Consider rephrasing to e.g. // Use "dfx_test_key" for local testing// Use the test key "dfx_test_key" locally (this is a protocol-level key name).

Suggestions

  • Content brief gap — "Compare direct RPC vs HTTPS outcalls approach": The stub asks for this comparison. The page mentions HTTPS outcalls briefly in "How it works" but doesn't provide an explicit comparison of when to use EVM RPC canister vs. direct HTTPS outcalls. A short subsection would satisfy the brief.
  • Missing sign_with_ecdsa call: The signing step is deferred to external examples. Showing the call signature (~10 lines) inline would make the signing flow more complete without exceeding the 30-line limit.
  • Motoko ERC-20 example is ~63 lines (lines 233-296): Well over the 30-line guideline. Could be trimmed (e.g., elide the long list of null fields with a comment like // ... all optional fields null).
  • -e ic vs -n ic: Using -e ic implies an environment named "ic" in icp.yaml. For calling canisters by principal ID directly, -n ic (--network) may be more appropriate. Need to verify which approach is correct for mainnet targeting.
  • Collateral cycles "currently fully refunded" claim (lines 585-587): This is time-sensitive information. Consider adding a verification date or flag.

Verified

  • Canister ID 7hfb6-caaaa-aaaar-qadga-cai matches evm-rpc icskill
  • Supported chains and providers table matches icskill exactly
  • Cycle cost formula matches icskill: (5_912_000 + 60_000 * nodes + 2400 * request_bytes + 800 * max_response_bytes) * nodes * rpc_count
  • Rust CDK API usage verified: Call::unbounded_wait, with_args, with_cycles, candid_tuple all match .sources/cdk-rs
  • Rust ECDSA types verified: EcdsaPublicKeyArgument, EcdsaKeyId, EcdsaCurve::Secp256k1
  • Motoko core library used throughout (never base)
  • persistent actor syntax correct
  • MultiResult handling correct (Consistent(Ok), Consistent(Err), Inconsistent)
  • ERC-20 balanceOf selector 0x70a08231 correct
  • Old .md stub deleted, .mdx format correct with proper imports
  • Tab order (Motoko first), syncKey="lang", no headings in TabItem — all correct
  • Upstream comment present in correct JSX format
  • Two {/* Needs human verification */} flags present (Keccak library gap, EVM RPC WASM version)
  • All internal links resolve
  • Build passes
  • Diataxis how-to compliance confirmed

@marc0olo
Copy link
Copy Markdown
Member Author

icskills was bumped to 1d125a9. The following content on this PR may be outdated:

  1. Rust implementation should use evm_rpc_client crate. The EVM RPC skill was fully rewritten to use the evm_rpc_client crate, which provides a typed client API and re-exports all Candid types from evm_rpc_types. The PR currently uses raw Call::unbounded_wait — this still works but drifts from upstream guidance and requires manual type definitions that can diverge from the canister interface.

  2. Consensus strategy. The new skill recommends ConsensusStrategy::Threshold { total: Some(3), min: 2 } (2-of-3 agreement) instead of the default Equality strategy for most queries (e.g., eth_getBlockByNumber(Latest) fails with Equality since providers are often 1-2 blocks apart). Check whether the PR's examples use the default strategy and add a note if so.

  3. icp-cli compatibility bumped to >= 0.2.2. If the page references an icp-cli version requirement, update it.

Please review before merging.

@marc0olo marc0olo force-pushed the docs/guides-chain-fusion-ethereum branch from bffdf77 to 1945174 Compare April 15, 2026 10:21
@marc0olo marc0olo force-pushed the docs/guides-chain-fusion-ethereum branch from 1945174 to 3795697 Compare April 15, 2026 11:27
@marc0olo
Copy link
Copy Markdown
Member Author

Feedback addressed:

  • Fixed --with-cycles flag (doesn't exist as a general flag; --cycles requires --proxy); added verification flag on testing section
  • Removed icp deps pull/init/deploy (subcommand doesn't exist); added verification flag on local deployment
  • Added verification flag on Motoko canister:evm_rpc import syntax
  • Rephrased dfx_test_key comments to clarify it's a protocol-level key name
  • Added note recommending evm_rpc_client crate for Rust implementation
  • Added tip about ConsensusStrategy::Threshold for Latest block queries

…I guidance

- Fix deprecated Rust ECDSA import: ic_cdk::api::management_canister::ecdsa ->
  ic_cdk::management_canister; EcdsaPublicKeyArgument -> EcdsaPublicKeyArgs
- Replace dfx_test_key with test_key_1 as default (both Motoko and Rust);
  mention key_1 for production
- MultiResult/RpcResult -> MultiRpcResult with correct Ok/Err arms throughout
  all Rust snippets; use evm_rpc_types imports
- Update prose reference: MultiResult -> MultiRpcResult
- CLI testing: replace unresolved verification comment with clear guidance —
  query calls work directly, update calls require going through backend wrapper
- Remove local deployment verification comment (resolved by icp.yaml approach)
- Cargo.toml note: remove unused evm_rpc_client and ic-canister-runtime;
  keep only evm_rpc_types and ic-cdk which the examples actually use
@marc0olo
Copy link
Copy Markdown
Member Author

Review complete. All findings addressed in commit 6faab6b:

Fixed:

  • Deprecated Rust ECDSA import: ic_cdk::api::management_canister::ecdsa::*ic_cdk::management_canister::*; EcdsaPublicKeyArgumentEcdsaPublicKeyArgs
  • Key names: dfx_test_key removed; examples now use test_key_1 (default, works locally and on mainnet), with key_1 noted for production
  • MultiResult/RpcResultMultiRpcResult with correct Ok/Err arms throughout all Rust snippets; imports updated to evm_rpc_types
  • CLI testing section: removed unresolved verification comment; replaced with clear guidance — query methods work directly, update calls (which require cycles) should be tested through your backend canister's wrapper functions
  • Removed resolved local deployment verification comment
  • Cargo.toml example: removed unused evm_rpc_client and ic-canister-runtime; kept only evm_rpc_types and ic-cdk which the examples actually use

Verified:

  • All internal links valid (.md.mdx resolution confirmed); EVM RPC canister ID correct; cycle cost formula verified; Motoko/Rust API usage verified against .sources/icskills/skills/evm-rpc/ and .sources/cdk-rs/; build passes

@marc0olo
Copy link
Copy Markdown
Member Author

Feedback addressed:

  • Fixed ecdsa_public_key call: pass argument by reference (&request) and remove incorrect tuple destructuring ((response,)response) — function returns CallResult<EcdsaPublicKeyResult>, not a tuple
  • Added missing imports to get_eth_balance raw JSON-RPC snippet: replaced unused candid::{CandidType, Deserialize} with evm_rpc_types::{EthMainnetService, RpcError, RpcService}
  • Added missing imports to get_erc20_balance snippet: evm_rpc_types::{EthMainnetService, RpcError, RpcService}
  • Added missing imports to "Querying other EVM chains" snippet: evm_rpc_types::{Block, BlockTag, CustomRpcService, MultiRpcResult, RpcError, RpcService, RpcServices}
  • Updated Upstream: comment to include dfinity/cdk-rs — ic-cdk/src/management_canister.rs

@marc0olo marc0olo merged commit 4c9ee08 into main Apr 15, 2026
1 check passed
@marc0olo marc0olo deleted the docs/guides-chain-fusion-ethereum branch April 15, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant