Convert Ethereum (H160) Address to Substrate (SS58)
This tutorial demonstrates how to convert between Ethereum (H160) and Substrate (SS58) addresses. This is useful for moving across the boundary between EVM wallets and Subtensor Wallets on the Bittensor blockchain.
In what follows, we'll create a wallet in Metamask and convert it's public key to ss58 format in order to target it with a balance transfer using BTCLI.
Procedure
Create Wallet with MetaMask
- Install Metamask wallet browser extension, if you haven't already.
- Create a new account or import an existing one.
- Add the Bittensor EVM network to MetaMask:
- Network Name: Bittensor EVM
- RPC URL: https://test.chain.opentensor.ai
- Chain ID: 945
- Currency Symbol: TAO
- Block Explorer URL: test.chain.opentensor.ai
- Click Save.
- Click Switch network.
Install the EVM Examples repo
- Clone the Opentensor EVM-Bittensor GitHub repo:
git clone https://github.com/opentensor/evm-bittensor.git
- Navigate to
evm-bittensor
directory:cd evm-bittensor
- Install the dependencies:
npm install
Set your config
Convert Address for Bittensor
Run the conversion script, replacing ethereumAddress
with your address:
node convert-address.js
Note down the SS58 address output by the script - this is your wallet's Subtensor address on the Bittensor network.
Transfer TAO to EVM Wallet
Use btcli
to transfer TAO to your SS58 address. Here we will use test network.
btcli wallet transfer --destination <your ss58 address> --network test
Verify Balance in MetaMask
- Open MetaMask
- Ensure you're connected to the Bittensor EVM network
- Your TAO balance should now be visible in MetaMask
- You can now use this wallet for EVM transactions on Bittensor
Conversion Script
Below is the code used above for the conversion.
Source code:
//convert-address.js
const { convertH160ToSS58 } = require('./address-mapping.js');
async function main() {
const ethereumAddress = "0xbdA293c21DfCaDDAeB9aa8b98455d42325599d23";
const ss58Address = convertH160ToSS58(ethereumAddress);
console.log(`ss58 mirror: ${ss58Address}`);
}
main().catch(console.error);
// address-mapping.js
function convertH160ToSS58(ethAddress) {
const prefix = 'evm:';
const prefixBytes = new TextEncoder().encode(prefix);
const addressBytes = hexToU8a(ethAddress.startsWith('0x') ? ethAddress : `0x${ethAddress}`);
const combined = new Uint8Array(prefixBytes.length + addressBytes.length);
// Concatenate prefix and Ethereum address
combined.set(prefixBytes);
combined.set(addressBytes, prefixBytes.length);
// Hash the combined data (the public key)
const hash = blake2AsU8a(combined);
// Convert the hash to SS58 format
const ss58Address = encodeAddress(hash, 42); // Network ID 42 for Bittensor
return ss58Address;
}