Derive Universal Executor Accounts (UEAs)
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.
- 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 SolanachainId: e.g., "11155111" for Ethereum Sepoliaowner: 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:
| Chain | Namespace | Example Chain ID |
|---|---|---|
| Ethereum | eip155 | 11155111 (Sepolia) |
| Solana | solana | EtWTRABZaYq6iMfeYKouRu166VU2xqa1 (Devnet) |
| Base | eip155 | 84532 (Sepolia) |
| Arbitrum | eip155 | 421614 (Sepolia) |
| BNB Chain | eip155 | 97 (Testnet) |
| Push Chain | eip155 | 42101 (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
// 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
// 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")
);
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:
- Input: Origin wallet address + chain information
- Create Universal Account: Combine namespace, chain ID, and owner
- Deterministic Derivation: Apply cryptographic hash function
- 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:
0xABCon Ethereum ≠0xABCon 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:
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.