LogoLogo
  • Welcome
    • About ENI
  • Getting Started
    • Quickstart
      • Account Structure
      • Token Standards
      • Gas
    • Divergence from Ethereum
    • Transactions
      • Creating Transaction
    • Governance
      • Proposals
    • Oracles
  • Build
    • Setup and Installation
    • Smart Contracts
      • EVM (General)
      • EVM (CLI)
      • Querying State
    • Frontend Development
      • Overview
      • How to Deploy Your First dApp
    • Ecosystem
      • Tools and Resources
      • Resources
  • Node
    • Getting Started
    • Node Operators Guide
    • Validator Operations Guide
    • Advanced Configuration & Monitoring
    • Technical Reference
  • Reference
    • Overview
    • enid
    • CLI
      • enid add-genesis-account
      • enid blocktest
      • enid collect-gentxs
      • enid compact
      • enid config
      • enid debug
      • enid export
      • enid gentx
      • enid help
      • enid init
      • enid keys
        • enid keys delete
        • enid keys add
        • enid keys export
        • enid keys import
        • enid keys list
        • enid keys mnemonic
        • enid keys parse
        • enid keys show
      • enid latest_version
      • enid migrate
      • enid prune
      • enid query
        • enid query accesscontrol
        • enid query upgrade
        • enid query account
        • enid query auth
        • enid query bank
        • enid query block
        • enid query authz
        • enid query distribution
        • enid query epoch
        • enid query evidence
        • enid query evm
        • enid query feegrant
        • enid query ibc-transfer
        • enid query gov
        • enid query ibc
        • enid query mint
        • enid query oracle
        • enid query params
        • enid query slashing
        • enid query staking
        • enid query tendermint-validator-set
        • enid query tokenfactory
        • enid query tx
        • enid query txs
      • enid rollback
      • enid start
      • enid status
      • enid tendermint
      • enid tools
      • enid tx
      • enid validate-genesis
      • enid version
Powered by GitBook
On this page
  • How Accounts Work on ENI
  • Key Points
  • Query Linked Addresses
  • Conclusion
  1. Getting Started
  2. Quickstart

Account Structure

On ENI, accounts are represented by two address formats:

  • ENI native Bech32 (eni...)

  • EVM-compatible Hex (0x...)

Both addresses for a single account are derived from the same public key, but the chain can only determine their association after the public key is known.


How Accounts Work on ENI

Automatic Linking

  • When an account broadcasts a transaction (e.g., sending tokens), its public key is recorded on-chain.

  • Once the public key is known, the EVM address and Bech32 address are linked automatically.

  • This ensures balances and transactions are accessible across both address formats.

Manual Association

If the account has not broadcasted any transaction yet:

  • Use the eni_associate function to manually record the public key on-chain.

  • This is a gasless operation as long as the account has at least 1 wei.

Why is the public key required? The public key enables the chain to derive and validate both the Bech32 and EVM addresses. Without it, the chain cannot determine the relationship between these two addresses.


Key Points

Before Linking

  • Bech32 (eni...) and EVM (0x...) addresses are treated as independent accounts.

  • They have separate balances before linking.

  • Any native tokens received by the EVM address will be stored in a temporary native address until the accounts are linked. After linking, these tokens will be transferred to the linked address.

  • Certain types of transactions will be unavailable (see below).

After Linking

  • Balances are reflected consistently across both addresses.

  • Applications can query either address format seamlessly.


Wallet Linking and Transfer Restrictions

Before wallet linking, certain operations cannot be performed:

  • Transferring CW tokens (such as CW20/721/1155) from non-EVM wallets to unlinked EVM addresses is not allowed.

  • Transferring ERC tokens (such as ERC20/721/1155) from EVM wallets to unlinked ENI native addresses is not allowed.


Query Linked Addresses

Fetch EVM Address for ENI Address

curl -X POST $ENIEVM -H "Content-Type: application/json" -d \
'{"jsonrpc": "2.0", "method": "eni_getEVMAddress", "params": ["<eniAddress>"], "id": 1}'

Example Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x4e1ae6017997128D421074FbE..."
}

Failure Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
    "message": "failed to find EVM address for eni1wev8ptz..."
  }
}

Fetch Bech32 Address for an EVM Address

curl -X POST $ENIEVM -H "Content-Type: application/json" -d \
'{"jsonrpc": "2.0", "method": "eni_getEniAddress", "params": ["<hexAddress>"], "id": 1}'

Example Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "eni1wev8ptzj27aueu04wg..."
}

Manual Association Using eni_associate

If no transaction has been broadcasted, use this command to manually associate the addresses:

enid tx evm associate-address [optional priv key hex] --rpc=<url> --from=<sender> [flags]

Note: The account must have at least 1 wei to perform this operation.


Deriving Addresses from Public Key

ENI Address Derivation

ENI native addresses are derived from the public key using the following steps:

  1. Hash the public key using the Keccak256 algorithm.

  2. Extract the first 20 bytes of the resulting hash.

  3. Encode the extracted bytes in Bech32 format with the "eni" prefix.

Example implementation:

import { bech32 } from 'bech32';
import { keccak256 } from 'ethereumjs-util';

export function deriveEniAddress(publicKey: Buffer): string {
  const hash = keccak256(publicKey);
  const words = bech32.toWords(hash.slice(0, 20));
  return bech32.encode('eni', words);
}

EVM Address Derivation

The EVM-compatible address is derived as follows:

  1. Hash the public key using the Keccak256 algorithm.

  2. Extract the last 20 bytes of the resulting hash.

  3. Prefix the extracted bytes with 0x to obtain the EVM address.

Example implementation:

import { keccak256 } from 'ethereumjs-util';

export function deriveEVMAddress(publicKey: Buffer): string {
  const hash = keccak256(publicKey);
  return `0x${hash.slice(-20).toString('hex')}`;
}

Summary

  • Public Key Hash:Both address derivations rely on the Keccak256 hashing algorithm.

  • ENI Address:

    • Extracts the first 20 bytes of the hash.

    • Encodes these bytes into Bech32 format with the "eni" prefix.

  • EVM Address:

    • Extracts the last 20 bytes of the hash.

    • Formats these bytes as Hex with the "0x" prefix.

Why This Works

Keccak256 hashing ensures that the process of deriving both address formats from the same public key is consistent and verifiable.

This mechanism enables a single account to remain compatible in both ENI native and EVM environments.


Conclusion

  • Accounts are automatically linked when a transaction is broadcasted or can be manually associated using eni_associate.

  • Both address formats share the same public key.

  • Linking ensures that dApps and tools can consistently access balances between the two address formats.


Next Steps

For a detailed technical explanation on how to perform account linking, please refer to the Wallet Linking section.

PreviousQuickstartNextToken Standards

Last updated 2 months ago