Cronos ID

Technical Integration Guide

Integrating with ethers.js

If your product is currently using ether.js, you only need to create a new provider with network configuration and it will be able to retrieve the domain data from blockchain.
// For testnet, instantiate a provider for name resovling.
provider = new ethers.providers.JsonRpcProvider('', {
chainId: 338,
name: 'cronos-testnet',
ensAddress: '0x16a23bFBcE9c53998c90201629E4cDB40B81B127'
// For mainnet, instantiate a provider for name resovling.
provider = new ethers.providers.JsonRpcProvider('', {
chainId: 25,
name: 'cronos-mainnet',
ensAddress: '0x7F4C61116729d5b27E5f180062Fdfbf32E9283E5'
// Resolve the name to account address
const account = await provider.resolveName("abcde5.cro")
// Perform a reverse lookup of the address, and will get the name if configured
const name = await provider.lookupAddress("YOUR ACCOUNT ADDRESS")
// Get the address of resolver contract and return a resolver instance.
const resolver = await provider.getResolver("abcde5.cro")
  • To support resolving UTF-8 (including emoji) names, the version should be 5.7.0 at least.
  • More information can be found in the ethers.js docs.

Calling Contracts Programmatically

If your project does not use ethers.js lib, you can call contracts programmatically to resolve Cronos ID domains.
Two main contracts will be used to resolve names by calling functions on-chain. You can get their ABI and addresses in the following links:
Below are some pared-down interfaces containing only the necessary methods:
interface CROID {
function resolver(bytes32 node) public virtual view returns (Resolver);
interface IResolver {
// resolve CronosID to address
// the input parameter 'node' is namehash('yourname.cro')
function addr(bytes32 node) public virtual view returns (address);
// reverse resolve wallet address to a CronosID/name
// the input parameter 'node' is namehash('myaddress.addr.reverse')
function name(bytes32 node) external view returns (string memory);
For resolution, only the Resolver function in the CROIDRegistry contract is required; other methods permit looking up owners and updating Cronos ID domain from within a contract that owns a name.
With these definitions, Solidity developers can refer to the following code to resolve or reverse-resolve on-chain:
contract MyContract {
// testnet
CROID croid = CROID(0x16a23bFBcE9c53998c90201629E4cDB40B81B127);
// mainnet
CROID croid = CROID(0x7F4C61116729d5b27E5f180062Fdfbf32E9283E5);
// resolving CROID name to account address
function resolve(bytes32 node) public view returns(address) {
IResolver resolver = croid.resolver(node);
return resolver.addr(node);
// reverse resolving wallet address to CROID name
function reverseResolve(bytes32 node) public view returns(string memory) {
IResolver resolver = croid.resolver(node);

Getting the hash of the domain

We call the hash of the domain 'node' hash, in bytes32 type. You can refer to this doc to understand how to get the hash. Please take note of the following:
Before being hashed with namehash, names are first normalized, using a process called UTS-46 normalization. This ensures that upper- and lower-case names are treated equivalently, and that invalid characters are prohibited. Anything that hashes and resolves a name must first normalize it, to ensure that all users get a consistent view.

Producing node hash off-chain

You can use ethers.js to produce node hash off-chain:
// Given CronosID 'abcde5.cro', the node hash for resolving is:
> 0x2fae4d5a9483b7ad67702f894906cfd6a4aeaa0311c7647a45a85a46337374ac
// Give wallet address '0xbb99F973EC0db97BB750e86D12aF971D161327cf'
// the node hash for reverse resovling is (Notice: without '0x' prefix):
> 0xeb1d118d3779684850b598aeda6fc8558608c815a7aba8825a3cf52d3b82c262

Getting node hash on-chain

For Solidity developers, you can get the node hash of domain or wallet address on-chain. You should add the following code to your contract:
// namehash('cro')
bytes32 constant CRO_NODE = 0x5dfacd0a0764eb7c9351dcd36f63cb5e2757014aa2592f976462be5c38ce9ca8;
function getNameNode(string memory name) public pure returns (bytes32) {
abi.encodePacked(CRO_NODE, keccak256(abi.encodePacked(name)))
// namehash('addr.reverse')
bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;
function getAddressNode(address addr) public pure returns (bytes32) {
abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))
// An optimised function to compute the sha3 of the lower-case
// hexadecimal representation of an Cronos address.
function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
assembly {
for {
let i := 40
} gt(i, 0) {
} {
i := sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr := div(addr, 0x10)
i := sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr := div(addr, 0x10)
ret := keccak256(0, 40)
The input parameter ‘name', is the Cronos ID domain without the '.cro’ suffix. e.g. if your Cronos ID domain is "abcde5.cro", the input should be "abcde5".


If you have any questions about the integration with Cronos ID Domain, drop us a message on our Discord server and we will get in touch with you!
For developers using other programming languages, we can provide language-specific examples to guide you through the integration.