7.0 KiB
How to Add Support for a new EVM Token
This document explains the process for adding support for a new EVM token in the SDK.
Overview
Adding support for a new EVM token requires modifying the following files:
src/utils/types/knownIds.ts- Add the new Token IDsrc/evmUtils/contractHelpers.ts- Add the token to the contract configurationsrc/stacksUtils/stxContractAddresses.ts- Add contract addresses for the corresponding token on the Stacks chain
Important Notice for Developers and AI Assistants
CRITICAL: The following values MUST be obtained from contract deployers or development team and should NEVER be generated by developers or AI tools:
- The exact
ONCHAIN_CONFIG_KEYvalue for the token (e.g.,TOKEN_NEW_TOKEN) - The contract addresses in
stxTokenContractAddresses_legacy - The token name/identifier (the actual token name like "ETH", "BTC", etc.)
These values are determined by the contract deployers and must match the deployed contract configurations.
NAMING CONVENTIONS:
KnownTokenId.EVM.TOKEN_NAMEandKnownTokenId.Stacks.TOKEN_NAMEtypically use the same name (e.g., both would be "ETH" for ETH)- However,
ONCHAIN_CONFIG_KEY.TOKEN_NAMEis NOT directly related to these names and is determined by how it's defined in the smart contract (e.g., "TOKEN_ETH" for ETH) - Always confirm the exact naming for
ONCHAIN_CONFIG_KEYwith the contract deployers, as it must match what's in the contract
Detailed Steps
1. Add the Token ID in knownIds.ts
In the src/utils/types/knownIds.ts file, add the new Token ID to the appropriate sections in the KnownTokenId namespace:
export namespace KnownTokenId {
export namespace EVM {
// Add the new EVM Token ID here - use the exact token name provided by the team
// For example, ETH for Ethereum
export const TOKEN_NAME = tokenId("evm-tokenname")
}
// If Stacks support is needed, also add it to the Stacks namespace
// Use the same token name as above
export namespace Stacks {
export const TOKEN_NAME = tokenId("stx-tokenname")
}
}
2. Update Contract Configuration in contractHelpers.ts
In the src/evmUtils/contractHelpers.ts file, you need to update the following sections:
- Add a new token key to the
ONCHAIN_CONFIG_KEYenum:
enum ONCHAIN_CONFIG_KEY {
// Other token keys...
// IMPORTANT: Use the exact key provided by the contract deployers
// This key format is usually different from the token name itself
// For example, TOKEN_ETH for Ethereum
TOKEN_KEY = "TOKEN_KEY", // This must match what's configured in the smart contract
}
- Add the new token key to the
getConfigscall in the_getOnChainConfigsImplfunction:
const configs = await readContract(client, {
abi: BridgeConfigAbi,
address: configContractAddress,
functionName: "getConfigs",
args: [
[
// Other token keys...
ONCHAIN_CONFIG_KEY.TOKEN_KEY, // Use the key added in the enum above
],
],
})
- Add the token mapping to the return object in the same function:
return {
// Other mappings...
// Note: EVMToken.TOKEN_NAME uses the same name as in KnownTokenId.EVM
// while ONCHAIN_CONFIG_KEY.TOKEN_KEY uses the contract-specific key
[EVMToken.TOKEN_NAME]: maybeAddress(configs[INDEX_POSITION]),
}
Important: The
INDEX_POSITIONshould match the position of your token key in thegetConfigsargs array. For example, if your token is the 21st item in the array, useconfigs[20](zero-indexed).
3. Add Stacks Contract Addresses in stxContractAddresses.ts
Add the corresponding contract addresses in the src/stacksUtils/stxContractAddresses.ts file:
export const stxTokenContractAddresses_legacy: Record<
// ...
> = {
// Other tokens...
// Use the same token name as in KnownTokenId.Stacks
[KnownTokenId.Stacks.TOKEN_NAME]: {
[KnownChainId.Stacks.Mainnet]: wrapContractAddress("mainnet", {
// IMPORTANT: Use the exact addresses provided by the contract deployers
deployerAddress: contractsMultisigMainnet,
contractName: "token-name", // This contract name must be obtained from the team
}),
[KnownChainId.Stacks.Testnet]: wrapContractAddress("testnet", {
// IMPORTANT: Use the exact addresses provided by the contract deployers
deployerAddress: contractsMultisigTestnet,
contractName: "token-name", // This contract name must be obtained from the team
}),
},
}
Example: Adding ETH Token Support
Here's a real example of adding support for the ETH token:
-
Adding to
knownIds.ts:export const ETH = tokenId("evm-eth") // In EVM namespace export const ETH = tokenId("stx-eth") // In Stacks namespace - same name as EVM -
Updating
contractHelpers.ts:// Add to enum - this key was provided by the contract deployers // Note that this is TOKEN_ETH, not just ETH enum ONCHAIN_CONFIG_KEY { // ...other tokens TOKEN_ETH = "TOKEN_ETH", } // Add to getConfigs call ONCHAIN_CONFIG_KEY.TOKEN_ETH, // Add to return object mapping // Here we use EVMToken.ETH (the token name), not TOKEN_ETH [EVMToken.ETH]: maybeAddress(configs[20]), -
Adding to
stxContractAddresses.ts:[KnownTokenId.Stacks.ETH]: { [KnownChainId.Stacks.Mainnet]: wrapContractAddress("mainnet", { deployerAddress: contractsMultisigMainnet, contractName: "token-eth", // This name was provided by the team }), [KnownChainId.Stacks.Testnet]: wrapContractAddress("testnet", { deployerAddress: contractsMultisigTestnet, contractName: "token-eth", // This name was provided by the team }), },
Important Considerations
- After adding a new token, ensure that all related cross-chain routing and validation logic works correctly
- Maintain consistency with array indices - ensure the index position in the
configsarray matches the position of your token in thegetConfigsargs array - If the contract address is read from on-chain configuration, make sure the on-chain contract has the correct token address configured
- After adding a new token, perform comprehensive testing to ensure all functionality works as expected
For Automated Tools (AI Assistants)
When adding a new token, follow these exact steps:
- DO NOT generate any values on your own - always ask for the official token name, ONCHAIN_CONFIG_KEY, and contract addresses
- Identify the next available index position for the token in the
getConfigscall - Add the token ID with the appropriate prefix pattern (e.g., "evm-tokenname" and "stx-tokenname")
- Add the token to all three files mentioned above
- Ensure the index position in the return mapping matches the position in the args array
- Follow the existing naming conventions for contract names as specified by the contract deployers
- Remember that KnownTokenId names typically match in EVM and Stacks namespaces, but ONCHAIN_CONFIG_KEY uses a different format defined by the contract