Skip to main content

Derive Universal Executor Accounts (UEAs)

10 mins

In this tutorial, you'll learn how to derive Universal Executor Accounts (UEAs) from any wallet address on any blockchain. This is the foundational concept that enables Push Chain's universal execution model.

By the end of this tutorial, you'll be able to:

  • ✅ Understand how UEAs map origin wallets to Push Chain addresses
  • ✅ Derive UEA addresses from any wallet (Ethereum, Solana, etc.)
  • ✅ Query UEAs programmatically using the SDK
  • ✅ Use the UEAFactory contract to derive UEAs on-chain

Understanding Universal Executor Accounts (UEAs)

A Universal Executor Account (UEA) is a deterministic smart account on Push Chain, derived from an origin wallet (chain namespace + chain id + owner), that serves as the execution account for that origin wallet on Push Chain.

Common Misconceptions
  • A UEA is not a new wallet on the origin chain
  • No private keys are created or stored on Push Chain
  • UEA addresses are deterministic, but the smart account is deployed lazily on first use

Key Concepts

Origin Wallet → UEA Mapping

  • Every wallet on every chain has a unique, deterministic UEA on Push Chain
  • Same origin address always produces the same UEA
  • The UEA is the execution surface for all transactions on Push Chain

Example:

Ethereum Wallet: 0xABC...123
↓ (deterministic derivation)
Push Chain UEA: 0x456...789

Solana Wallet: 7xKX...ABC
↓ (deterministic derivation)
Push Chain UEA: 0x789...DEF

Why UEAs Matter

Traditional Multi-Chain Problem:

  • Users need different wallets for different chains
  • Each chain requires separate gas tokens
  • No unified identity across chains

Push Chain Solution with UEAs:

  • One origin wallet → One UEA on Push Chain
  • UEA is controlled by the origin wallet of the user
  • The UEA executes transactions on behalf of the origin wallet
  • Users interact from their preferred chain seamlessly

Deriving UEAs with the SDK

The Push Chain SDK provides utilities to derive UEAs from any wallet address.

Basic UEA Derivation

import { PushChain } from '@pushchain/core';

// Convert origin address to Universal Account
const account = PushChain.utils.account.toUniversal(
'0xYourEthereumAddress',
{
chain: PushChain.CONSTANTS.CHAIN.ETHEREUM_SEPOLIA
}
);

// Derive the UEA address
const executorAddress = await PushChain.utils.account.convertOriginToExecutor(account);

console.log('UEA Address:', executorAddress.address);
// Output: 0x... (deterministic Push Chain address)

Understanding the Process

Step 1: Create Universal Account

const account = PushChain.utils.account.toUniversal(originAddress, { chain });

This creates a UniversalAccount object containing:

  • chainNamespace: e.g., "eip155" for EVM chains, "solana" for Solana
  • chainId: e.g., "11155111" for Ethereum Sepolia
  • owner: The origin wallet address

Step 2: Convert to Executor Address

const executorAddress = await PushChain.utils.account.convertOriginToExecutor(account);

This performs the deterministic derivation to get the UEA address on Push Chain.

Supported Chains

The SDK supports UEA derivation for supported chains:

ChainNamespaceExample Chain ID
Ethereumeip15511155111 (Sepolia)
SolanasolanaEtWTRABZaYq6iMfeYKouRu166VU2xqa1 (Devnet)
Baseeip15584532 (Sepolia)
Arbitrumeip155421614 (Sepolia)
BNB Chaineip15597 (Testnet)
Push Chaineip15542101 (Testnet)

To get a list of all supported chains, see the Get Supported Chains utility function.

Deriving UEAs in Smart Contracts

You can also derive UEAs directly in your Solidity contracts using the UEAFactory precompile.

UEAFactory Contract

The UEAFactory is deployed at a fixed address on Push Chain:

0x00000000000000000000000000000000000000eA

Interface

IUEAFactory Interface
IUEAFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

struct UniversalAccountId {
string chainNamespace;
string chainId;
bytes owner;
}

interface IUEAFactory {
function getUEAForOrigin(
UniversalAccountId memory account
) external view returns (address uea, bool isDeployed);

function getOriginForUEA(
address uea
) external view returns (UniversalAccountId memory, bool);
}

Example Contract

UEA Lookup Contract
UEALookup.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import "push-chain-core-contracts/src/Interfaces/IUEAFactory.sol";

contract UEALookup {
IUEAFactory constant FACTORY =
IUEAFactory(0x00000000000000000000000000000000000000eA);

// Get UEA address for any origin wallet
function getUEAForUser(
string memory chainNamespace,
string memory chainId,
bytes memory owner
) public view returns (address uea, bool isDeployed) {
UniversalAccountId memory account = UniversalAccountId({
chainNamespace: chainNamespace,
chainId: chainId,
owner: owner
});

return FACTORY.getUEAForOrigin(account);
}

// Get origin wallet info from UEA address
function getOriginForUEA(address ueaAddress)
public view returns (
string memory chainNamespace,
string memory chainId,
bytes memory owner,
bool exists
)
{
(UniversalAccountId memory account, bool found) =
FACTORY.getOriginForUEA(ueaAddress);

return (
account.chainNamespace,
account.chainId,
account.owner,
found
);
}

// Check if a UEA is deployed
function isUEADeployed(
string memory chainNamespace,
string memory chainId,
bytes memory owner
) public view returns (bool) {
UniversalAccountId memory account = UniversalAccountId({
chainNamespace: chainNamespace,
chainId: chainId,
owner: owner
});

(, bool deployed) = FACTORY.getUEAForOrigin(account);
return deployed;
}
}

Key Methods:

  • getUEAForOrigin() - Get the UEA address for any origin wallet

    • Returns the UEA address and whether it's been deployed
    • Works for any chain (Ethereum, Solana, etc.)
  • getOriginForUEA() - Reverse lookup: get origin wallet from UEA

    • Returns the chain namespace, chain ID, and owner address
    • Useful for verifying the origin of a transaction

Usage Example

// Get UEA for an Ethereum Sepolia wallet
(address uea, bool deployed) = getUEAForUser(
"eip155",
"11155111",
abi.encodePacked(0xYourEthereumAddress)
);

// Get UEA for a Solana wallet
(address solanaUEA, bool deployed) = getUEAForUser(
"solana",
"EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
abi.encodePacked("Base58SolanaAddress")
);
Derivation Note

For Solana wallets, owner must be the raw public key bytes (decoded from base58), not the base58 string.

Understanding UEA Derivation

The Derivation Process

Step-by-step:

  1. Input: Origin wallet address + chain information
  2. Create Universal Account: Combine namespace, chain ID, and owner
  3. Deterministic Derivation: Apply cryptographic hash function
  4. Output: UEA address on Push Chain

Key Properties

Deterministic

  • Same input always produces same output
  • Can be computed off-chain before any transaction
  • No registration or setup required

Unique

  • Each origin wallet has exactly one UEA
  • Different chains produce different UEAs for the same address
  • Example: 0xABC on Ethereum ≠ 0xABC on Base

Bidirectional

  • Can derive UEA from origin wallet
  • Can query origin wallet from UEA (using getOriginForUEA)

Use Cases

1. Airdrop Systems

Derive UEAs for all recipients to create a universal airdrop:

const recipients = [
{ address: '0xEth...', chain: ETHEREUM_SEPOLIA },
{ address: '7xSol...', chain: SOLANA_DEVNET },
];

const ueas = await Promise.all(
recipients.map(async (r) => {
const account = PushChain.utils.account.toUniversal(r.address, { chain: r.chain });
return await PushChain.utils.account.convertOriginToExecutor(account);
})
);

2. Cross-Chain Identity

Verify a user's identity across chains:

function verifyUser(address uea) public view returns (bool) {
(UniversalAccountId memory origin, bool exists) =
FACTORY.getOriginForUEA(uea);

return exists && isAllowedChain(origin.chainNamespace);
}

3. Universal Allowlists

Create allowlists that work across all chains:

mapping(address => bool) public allowlist;

function addToAllowlist(
string memory chainNamespace,
string memory chainId,
bytes memory owner
) external onlyOwner {
(address uea, ) = FACTORY.getUEAForOrigin(
UniversalAccountId(chainNamespace, chainId, owner)
);
allowlist[uea] = true;
}

Live Playground

Try deriving UEAs from any wallet address in real-time:

REACT PLAYGROUND
LIVE APP PREVIEW

Source Code

What We Achieved

In this tutorial, we explored Universal Executor Accounts:

  • Understood UEAs - How origin wallets map to Push Chain addresses
  • Derived UEAs - Used the SDK to compute UEAs from any wallet
  • On-Chain Queries - Used UEAFactory to derive UEAs in smart contracts
  • Practical Applications - Saw how UEAs enable universal systems

Key Takeaways

1. One Wallet, One UEA

  • Every wallet on every chain has a unique UEA on Push Chain
  • The mapping is deterministic and permanent
  • No setup or registration required

2. Universal Identity

  • UEAs provide a unified identity across all chains
  • Users interact from their preferred chain
  • Developers build once, reach everyone

3. Powerful Primitives

  • UEAs enable universal airdrops, allowlists, and more
  • On-chain derivation with UEAFactory
  • Off-chain computation with the SDK

What's Next?

Now that you understand how Universal Executor Accounts (UEAs) are derived, you can start building real universal systems on Push Chain.

  • Build a Universal Airdrop
    Deploy once on Push Chain and let users from any chain claim tokens using their existing wallet.

  • Contract Helpers
    Go deeper with advanced UEA patterns, including on-chain derivation, reverse lookups, and contract-level integrations.