Edit this page

Delegating Meta Transactions

Both CNS and UNS smart contracts have meta-transaction support, which allows you to delegate transactions to another party. Generally, meta-transactions allow members to sign messages to control their domains that are then submitted to the registry by a different party. This enables Unstoppable to submit transactions on behalf of members so that the member can still manage their domains in a self-custodial capacity without any gas.

Meta-transactions work by having members sign function calls along with a nonce. They then send that signed function call over to a different party. That party calls the meta-transaction-enabled function on the Registry in UNS or Resolver in CNS. The meta-transaction method then checks the permission for a domain against the address recovered from the signed message sent to the function, unlike the base method that checks it against the submitter of the transaction e.g. msg.sender.


UNS provides an interface that defines its meta-transactions function signatures and how to trigger them. The source code can be found in IForwarder.sol.

Example meta-transaction flow

Example meta-transaction flow

For UNS and CNS, the meta-transaction versions of Registry functions are included in the registry. The source code for signature validation can be found in UNSRegistryForwarder.sol and CNSRegistryForwarder.sol.

Token Nonce

Meta transaction methods are bound to names via their nonce (instead of Account nonce of traditional transactions). It protects from Double-spending in the same way as an account-based nonce in traditional transactions.

The example below shows how replay attacks can be used to exploit domains:

Replay attacks without nonces

Replay attacks without nonces

A nonce is simply a transaction counter for each token. This prevents replay attacks where a transfer of a token from A to B can be replayed by B over and over to continually revert the state of the name back to a previous state. This counter increments by 1 each time a state transition happens to a token. Token-based nonces can be used to prevent misordering of transactions in a more general sense as well. This prevents front running non-fungible assets and enables secure transaction batching.

Valid and invalid transactions with nonces

Valid and invalid transactions with nonces

Meta Transaction Signature Generation

A meta transaction requires 2 signatures: one passed as a method argument and one classical. A classical signature is generated in a standard way. A meta signature requires a domain owner (or a person approved by the owner) to sign a special message formed from:

  • A domain based meta-transaction nonce
  • A Function Selector of the original method
  • The original method parameters (the one without signature)

UNS Signature Generation

UNS Example for a reset method call for a domain:

const domain = 'example.crypto';
const methodName = 'reset';
const methodParams = ['uint256'];
const contractAddress = '0x049aba7510f45BA5b64ea9E658E342F904DB358D';
// can be different or the same as contractAddress
const controllerContractAddress = '0x049aba7510f45BA5b64ea9E658E342F904DB358D';
const tokenId = namehash(domain);

function generateMessageToSign(
  contractAddress: string,
  signatureContract: string,
  methodName: string,
  methodParams: string[],
  tokenId: string,
  params: any[],
) {
  return solidityKeccak256(
    ['bytes32', 'address', 'uint256'],
        [encodeContractInterface(contractAddress, method, methodParams, params)],
      ethCallRpc(controllerContractAddress, 'nonceOf', tokenId),

const message = generateMessageToSign(

Functions Reference:

  • namehashNamehashing function algorithm implementation
  • ethCallRpc — Ethereum eth_call JSON RPC implementation
  • encodeContractInterfaceSolidity ABI interface parameters encoder
  • solidityKeccak256Solidity ABI parameters encoder