Documentation Index Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
Use this file to discover all available pages before exploring further.
The x/erc20 module from cosmos/evm enables bidirectional conversion between Cosmos SDK coins and ERC20 tokens within the EVM runtime.
Parameters
The module parameters control token conversion and registration (source ):
Parameter Type Default Description enable_erc20bool trueEnable token conversions globally permissionless_registrationbool falseAllow anyone to register ERC20 tokens
Parameter Details
Master switch for token conversions:
true: All conversions enabled (default)
false: Disables all conversions, registration still works
Use for emergency pause or maintenance
Show permissionless_registration
Controls who can register new ERC20 tokens:
false: Only governance can register (default, recommended)
true: Anyone can register via MsgRegisterERC20
Permissionless risks: spam tokens, malicious contracts
State
The module maintains token pair mappings and allowances (source ):
Object Key Value Description TokenPair0x01 + IDTokenPairToken pair configuration TokenPairByERC200x02 + addressIDLookup by ERC20 address TokenPairByDenom0x03 + denomIDLookup by denomination Allowance0x04 + hashAllowanceERC20 allowances NativePrecompiles0x05 + addressboolNative precompile registry DynamicPrecompiles0x06 + addressboolDynamic precompile registry
Token Pair Structure
type TokenPair struct {
Erc20Address string // Hex address of ERC20 contract
Denom string // Cosmos coin denomination
Enabled bool // Conversion enable status
ContractOwner Owner // OWNER_MODULE or OWNER_EXTERNAL
}
Token Pair Registration
Registration Methods
Automatic Registration (IBC Tokens)
IBC tokens (denoms starting with “ibc/”) are automatically registered on first receipt
No governance proposal or user action required
Creates ERC20 precompile at deterministic address
Permissionless Registration (ERC20 Contracts)
When permissionless_registration parameter is true
Any user can register existing ERC20 contracts via MsgRegisterERC20
Useful for integrating existing ERC20 tokens
Governance Registration
Always available regardless of parameter settings
Can register any ERC20 contract or create new token pairs
Required when permissionless_registration is false
Messages
MsgRegisterERC20
Register existing ERC20 contracts for conversion (source ):
message MsgRegisterERC20 {
string signer = 1 ;
repeated string erc20addresses = 2 ;
}
Requirements:
permissionless_registration enabled OR sender is governance authority
Valid ERC20 contract at address
Contract not already registered
Contract implements standard ERC20 interface
MsgConvertCoin
Convert Cosmos coins to ERC20 tokens:
message MsgConvertCoin {
Coin coin = 1 ; // Amount and denom to convert
string receiver = 2 ; // Hex address to receive ERC20
string sender = 3 ; // Bech32 address of sender
}
Validation:
Token pair exists and enabled
Sender has sufficient balance
Valid receiver address
MsgConvertERC20
Convert ERC20 tokens to Cosmos coins:
message MsgConvertERC20 {
string contract_address = 1 ; // ERC20 contract
string amount = 2 ; // Amount to convert
string receiver = 3 ; // Bech32 address
string sender = 4 ; // Hex address of sender
}
Validation:
Token pair exists and enabled
Sender has sufficient ERC20 balance
Valid receiver address
MsgToggleConversion
Enable/disable conversions for a token pair (governance only):
message MsgToggleConversion {
string authority = 1 ; // Must be governance account
string token = 2 ; // Address or denom
}
MsgUpdateParams
Update module parameters (governance only):
message MsgUpdateParams {
string authority = 1 ; // Must be governance account
Params params = 2 ; // New parameters
}
Conversion Flows
Native Coin → ERC20
Steps:
Validate token pair enabled
Transfer coins to module account
Mint equivalent ERC20 to receiver
Emit conversion event
ERC20 → Native Coin
Steps:
Validate token pair enabled
For module-owned: burn ERC20
For external: transfer to module
Release native coins from escrow
Emit conversion event
Precompile System
Native Precompiles
Automatically created for Cosmos coins at deterministic addresses:
// Address derivation
address = keccak256 ( "erc20|<denom>" )[: 20 ]
Interface:
interface IERC20 {
function totalSupply () external view returns ( uint256 );
function balanceOf ( address account ) external view returns ( uint256 );
function transfer ( address recipient , uint256 amount ) external returns ( bool );
function allowance ( address owner , address spender ) external view returns ( uint256 );
function approve ( address spender , uint256 amount ) external returns ( bool );
function transferFrom ( address sender , address recipient , uint256 amount ) external returns ( bool );
}
Dynamic Precompiles (WERC20)
Optional wrapped interface for registered tokens:
interface IWERC20 is IERC20 {
function deposit () external payable ;
function withdraw ( uint256 amount ) external ;
}
IBC Integration
IBC Middleware v1
Standard IBC transfer integration (source ):
// Automatic registration and conversion on receive
OnRecvPacket (packet) {
// Auto-register new IBC tokens (with "ibc/" prefix)
if ! tokenPairExists && hasPrefix (denom, "ibc/" ) {
RegisterERC20Extension (denom)
}
// Auto-convert to ERC20 for Ethereum addresses
if isEthereumAddress (receiver) {
convertToERC20 (voucher, receiver)
}
}
// Automatic conversion on acknowledgment
OnAcknowledgementPacket (packet, ack) {
if wasConverted {
convertBackToCosmos (refund)
}
}
Automatic Registration:
IBC tokens (denoms starting with “ibc/”) are automatically registered on first receipt
Factory tokens (denoms starting with “factory/”) are skipped
Native chain tokens require explicit registration
IBC Middleware v2
Enhanced IBC v2 support (source ):
New packet format support
Improved error handling
Multi-hop awareness
Backward compatibility
Events
Registration Events
Event Attributes When Emitted register_erc20erc20_address, cosmos_coinToken pair registered toggle_token_conversionerc20_address, cosmos_coinConversion toggled
Conversion Events
Event Attributes When Emitted convert_coinsender, receiver, amount, cosmos_coin, erc20_tokenCoin → ERC20 convert_erc20sender, receiver, amount, cosmos_coin, erc20_tokenERC20 → Coin
IBC Events
Event Attributes When Emitted ibc_transfer_conversionsender, receiver, denom, amountAuto-conversion during IBC
Queries
gRPC
service Query {
// Get module parameters
rpc Params ( QueryParamsRequest ) returns ( QueryParamsResponse );
// Get all token pairs
rpc TokenPairs ( QueryTokenPairsRequest ) returns ( QueryTokenPairsResponse );
// Get specific token pair
rpc TokenPair ( QueryTokenPairRequest ) returns ( QueryTokenPairResponse );
}
CLI
Query-Params
Query-Token-Pairs
Convert-Tokens
Register-Token
# Query module parameters
evmd query erc20 params
Integration Examples
DeFi Protocol Integration
// Using precompiled ERC20 interface for IBC tokens
const ibcToken = new ethers. Contract (
"0x80b5a32e4f032b2a058b4f29ec95eefeeb87adcd" , // Precompile address
ERC20_ABI ,
signer
);
// Standard ERC20 operations work seamlessly
await ibcToken. approve (dexRouter, amount);
await dexRouter. swapExactTokensForTokens ( ... );
Automatic IBC Conversion
// IBC transfer automatically converts to ERC20
const packet = {
sender: "cosmos1..." ,
receiver: "0x..." , // EVM address triggers conversion
token: { denom: "test" , amount: "1000000" }
};
// Token arrives as ERC20 in receiver's EVM account
Manual Conversion Flow
// Convert native to ERC20
await client. signAndBroadcast (address, [
{
typeUrl: "/cosmos.evm.erc20.v1.MsgConvertCoin" ,
value: {
coin: { denom: "test" , amount: "1000000" },
receiver: "0xEthereumAddress" ,
sender: "cosmos1..."
}
}
]);
Best Practices
Chain Integration
Token Registration Review
Audit contracts before registration
Verify standard compliance
Check for malicious behavior
Precompile Configuration
Enable precompiles for frequently used tokens
Monitor gas consumption
Set appropriate gas costs
IBC Setup
Configure middleware stack correctly
Test auto-conversion flows
Monitor conversion events
Security Considerations
Contract Validation
// Verify standard interface
IERC20 (token). totalSupply ();
IERC20 (token). balanceOf ( address ( this ));
Event Monitoring
Track conversion events
Monitor for unusual patterns
Alert on large conversions
Emergency Response
Disable conversions via governance
Toggle specific token pairs
Have incident response plan
Troubleshooting
Common Issues
Issue Cause Solution ”token pair not found” Token not registered Register via governance ”token pair disabled” Conversions toggled off Enable via governance ”insufficient balance” Low balance for conversion Check balance in correct format ”invalid recipient” Wrong address format Use hex for EVM, bech32 for Cosmos ”module disabled” enable_erc20 = false Enable via governance
Debug Commands
# Check if token is registered
evmd query erc20 token-pair test
# Check module parameters
evmd query erc20 params
# Check account balance (both formats)
evmd query bank balances cosmos1...
evmd query vm balance 0x...
References
Source Code