EVM Adapter Proxy
The EVM Adapter Proxy is a crucial component in the ICP-EVM Proxy project. It serves as a bridge between the Internet Computer Protocol (ICP) and EVM-compatible systems, enabling interoperability and data translation.
Important Considerations
This component is a proof of concept (PoC) and is not designed for production use. Its main purpose is to demonstrate the feasibility of integration between ICP and EVM-compatible systems.
DEX Client Integration
The DEX client integration in this proxy is implemented solely for demonstration and testing purposes in this PoC. It provides a simplified interface to interact with basic DEX operations.
Main Functions
- Log Retrieval: Fetches ICRC-3 compatible logs from the Logger Canister on the Internet Computer.
- Log Translation: Converts ICRC-3 logs into EVM-compatible event logs.
- EVM RPC Compatibility: Exposes EVM RPC compatible methods, allowing interaction with ICP canisters using familiar Ethereum tooling.
Implementation
The EVM Adapter Proxy is implemented in Go and consists of several main components:
- A structure to hold necessary configuration and state.
- Functions to fetch logs from the Logger Canister.
- Functions to translate ICRC-3 logs to EVM-compatible logs.
- An HTTP server to handle incoming RPC requests.
Log Translation Process
The log translation process involves mapping ICRC-3 log fields to their EVM equivalents. This includes:
- Converting canister IDs to Ethereum-style addresses.
- Mapping event types to appropriate topic hashes.
- Formatting log data to match EVM expectations.
EVM RPC Compatibility
The EVM Adapter Proxy implements a subset of Ethereum JSON-RPC methods to provide compatibility with Ethereum tooling. Some key methods include:
Standard Ethereum Methods
eth_chainId
: Returns the chain ID.eth_blockNumber
: Returns the number of the most recent block.eth_getBlockByNumber
: Retrieves a block by its number.eth_getBlockByHash
: Retrieves a block by its hash.eth_getLogs
: Retrieves logs that match the specified filter criteria.eth_accounts
: Returns a list of account addresses.net_version
: Returns the current network version.net_listening
: Indicates whether the client is actively listening for network connections.net_peerCount
: Returns the number of peers currently connected to the client.web3_clientVersion
: Returns the current client version.web3_sha3
: Returns the Keccak-256 hash of the given input.
DEX-Specific Methods
eth_getCurrencyPairs
: Returns all available currency pairs from the DEX.eth_mintTokens
: Creates new tokens for a specified recipient.eth_burnTokens
: Destroys tokens from an owner's balance.
These methods allow Ethereum tools and libraries to interact with ICP canisters as if they were EVM-compatible smart contracts.
Example Usage
Standard Methods
# Get Chain ID
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
http://localhost:3030/rpc/v1
# Get Latest Block
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://localhost:3030/rpc/v1
DEX Methods
# Get Currency Pairs
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_getCurrencyPairs","params":[],"id":1}' \
http://localhost:3030/rpc/v1
# Mint Tokens
curl -X POST -H "Content-Type: application/json" \
--data '{
"jsonrpc":"2.0",
"method":"eth_mintTokens",
"params":[{
"currency": "ICP",
"amount": "0x5f5e100",
"recipient": "0x2vxsx-fae"
}],
"id":1
}' \
http://localhost:3030/rpc/v1
# Burn Tokens
curl -X POST -H "Content-Type: application/json" \
--data '{
"jsonrpc":"2.0",
"method":"eth_burnTokens",
"params":[{
"currency": "ICP",
"amount": "0x2faf080",
"owner": "0x2vxsx-fae"
}],
"id":1
}' \
http://localhost:3030/rpc/v1
Note: For this PoC, Ethereum addresses should be formatted as "0x<full_icp_principal>". For example, if your ICP principal is "2vxsx-fae", use "0x2vxsx-fae" as the Ethereum address. The proxy will simply remove the "0x" prefix to get the ICP principal.
Integration with Other Components
- Logger Canister: The EVM Adapter Proxy retrieves logs from the Logger Canister on the Internet Computer.
- DEX Canister: Provides access to DEX functionality through EVM-compatible methods.
- SubQuery Indexer: Translated logs are made available to the SubQuery Indexer for further processing and indexing.
For more details on the interaction between components, refer to the project overview and other component-specific documentation.
Technical Details
Client Generation
The proxy uses automatically generated clients for both Logger and DEX canisters. These clients are generated using the Makefile command:
# Generate both Logger and DEX clients
make generate-client
This command internally uses the goic
tool to generate Go clients from the Candid interface definitions. The process is defined in Makefile.local.mk
The generated clients provide type-safe interfaces for interacting with the canisters.
Configuration
The proxy requires configuration for both Logger and DEX canister IDs in config.yaml
:
icp:
loggerCanisterId: "ydpfi-uiaaa-aaaal-qjupa-cai"
dexCanisterId: "7eo5f-eqaaa-aaaam-adqoq-cai"
nodeUrl: "https://ic0.app"
Development Workflow
-
After any changes to canister interfaces:
make generate-client # Regenerate Go clients
-
Build and run the proxy:
make build
./output/poc-icp-icrc3-evm-adapter start -c config.yaml