I'm trying to bind a H160 address with a H256 address, if we assume this function:

fn bind(origin: OriginFor<T>, address: H160 , signature: [u8; 130]) -> Result<(), Error<T>>{
    // check the signature belonging to an address
    ensure!(check_signature(address, signature), Error<T>);

    // bind the sender with the address
    create_account(sender, address);


Is this function available in Substrate? Or do you have any advice on how to do the bind function?

  • 2
    The "bind" function you want to create seems very similar to what the Proxy account system does. Have to looked at that code to see how it works?
    – Shawn Tabrizi
    Commented Mar 17, 2022 at 14:10
  • It's not really clear what you're asking, it would help to get context on what you're trying to achieve. The H160 format is just the first 20 bytes of the H256 address. The function you're proposing should probably be taking some H256 address and then making the conversion to H160 by truncating it. Commented Mar 25, 2022 at 14:05
  • In acala they provide a mapping pallete wiki.acala.network/build/development-guide/smart-contracts/…
    – katapulte
    Commented Aug 17, 2022 at 17:34

3 Answers 3


H160 has a few flavors that you might pursue in the context of a Substrate chain:

  • If you are looking to map H160 Ethereum addresses to, say, SR25519 that is most common in Substrate chains, it is good to see the implementation in Frontier as a reference. Here a truncated hash scheme is used (H256 -> H160 by taking the first 160 (LE) bytes in the address). There are some tools to inspect truncated vs. Ethereum converted (ECDSA <-> SR25519) addresses in the frontier node template.

  • Another important example is to use H160 addresses as the base for accounting in you chain, this is exemplified in Moonbeam's Unified Accounts


because this PR was merged, Frontier now also supports Moonbeam's Unified Accounts (aka AccountId20)


I have one regular accountid32 on one parachain and I want to convert the address to a moonbeam/evm/accountid20 address, is this a proper implementation to convert accountid32 > accountid20?

import { addressToEvm } from "@polkadot/util-crypto";
import { decodeAddress, encodeAddress } from '@polkadot/keyring';
import { Keyring } from '@polkadot/keyring';

function get_test_account() {

    const e0 = new Keyring({ type: 'sr25519' });
    const account = e0.addFromUri('seed here');

    return account;

export const u8aToHex = (bytes: number[] | Uint8Array): string => {
  const arr = bytes instanceof Uint8Array ? Array.from(bytes) : bytes
  return '0x' + arr.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');

async function main(){
      const sender = get_test_account(); // load ss58 regular account
       console.log(`Substrate address:`, sender.address);
       const byteArray = addressToEvm(sender.address); // take the accountid32 address and convert it to a evm address uint8 array
       console.log(`Raw Evm address:`, byteArray);

  console.log(`evm address:`, u8aToHex(byteArray)); // convert the u8 to hex to display the address 


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.