Hub Wallet Abstraction
Overview
The Hub Wallet Abstraction is a system that enables seamless cross-chain user interactions by creating deterministic wallet proxies on the Hub chain. This allows users from any connected chain to have a corresponding wallet on the Hub chain, effectively enabling cross-chain operations without requiring users to understand the underlying complexity.
Architecture
Core Components
WalletFactory (Beacon Proxy)
Manages the creation and tracking of user wallets
Uses CREATE3 for deterministic deployments
Implements upgradeable proxy pattern for future improvements
Maps any (chainId, userAddress) pair to a unique Hub chain wallet address
Wallet Implementation
Handles cross-chain message execution
Manages permissions through specialized hooks
Executes arbitrary contract calls on behalf of users
How It Works
Wallet Creation
function getWallet(uint256 chainId, bytes calldata user) external returns (address computedAddress) {
bytes32 salt = keccak256(abi.encodePacked(address(this), chainId, user));
computedAddress = CREATE3.getDeployed(salt);
if (computedAddress.code.length <= 0) {
this.deploy(salt);
}
return computedAddress;
}
When a user first interacts with the system, a deterministic wallet is created
The wallet address is derived from the user's origin chain ID and address
CREATE3 ensures the same wallet address is always generated for a given user
Cross-Chain Interaction
function recvMessage(
uint256 srcChainId,
bytes calldata srcAddress,
uint256 _connSn,
bytes memory _payload,
bytes[] calldata signatures
) external {
connection.verifyMessage(srcChainId, srcAddress, _connSn, _payload, signatures);
require(
address(this) == factory.getWallet(originChainId, originAddress),
"Mismatched address and caller"
);
executeCalls(payload);
}
Users send messages from their origin chain
Messages are verified through the connection contract
The wallet executes the requested actions on the Hub chain
Specialized Access
Asset Manager Hook: Allows asset manager to execute on behalf of the user
XToken Manager Hook: Allows XToken manager to execute on behalf of the user
Hashed Calls
In order to support spoke chains with limited call data size, we support hashed calls.
When a user sends a message to the Hub chain, the message of length 32 bytes it will be treated as keccak256 hashed data and stored in the wallet.
When the user wants to execute the stored call, they can call the executeStored
function with the same data. This will generallay be handled by the relayer.
This allows the user to store a call on the Hub chain and execute it later on the spoke chain.
Key Features
Deterministic Addressing
Every user gets a predictable wallet address on the Hub chain
No need for explicit wallet deployment transactions
Gas-efficient through CREATE3
Upgradeable Architecture
Beacon proxy pattern allows wallet implementation upgrades
All user wallets can be upgraded simultaneously
Maintains consistent addresses across upgrades
Flexible Execution
Supports arbitrary contract calls
Batched transactions through ContractCall structs
Secure permission system for different operation types
Use Cases
Example: Cross-Chain Money Market Interaction
User initiates action from their origin chain
Message is verified and routed to their Hub wallet
Wallet executes complex operations (e.g., deposit, borrow, withdraw)
Results can be bridged back to any desired chain
Future Extensions
The system is designed to support future enhancements such as:
Multi-wallet linking across chains
Customizable security parameters
Signature-based operations without cross-chain messages
Rate limiting and additional security features
Adding more specialized hooks for systems such as LayerZero
Security Considerations
All cross-chain messages must be properly verified
Only authorized contracts (AssetManager) can access specialized hooks
Wallet addresses are deterministically generated to prevent conflicts
Upgrades are controlled by the factory owner through UUPS pattern
Asset Manager Integration Showcase
How Asset Manager Access Works
Cross-Chain Asset Transfer Reception
function recvMessage(
uint256 nonce,
uint256 srcChainId,
bytes calldata fromAddress,
bytes memory payload,
bytes[] memory signatures
) external {
// Verify the sender is the authorized asset manager for the source chain
require(keccak256(fromAddress) == keccak256(spokeAssetManager[srcChainId]));
// Verify the cross-chain message
connection.(srcChainId, fromAddress, noncepayload, signatures);
Transfer memory _transfer = payload.decode();
// Mint tokens to the recipient
address token = assets[srcChainId][_transfer.token];
IAssetToken(token).mintTo(_transfer.to.toAddress(), _transfer.amount);
// If additional actions are needed, call the user's wallet
if (_transfer.data.length > 0) {
address wallet = walletFactory.getWallet(srcChainId, _transfer.from);
IWallet(wallet).assetManagerHook(_transfer.data);
}
}
Wallet Hook Execution
function assetManagerHook(bytes memory data) external {
// Only the authorized AssetManager can call this function
require(msg.sender == assetManager, "Only AssetManager is allowed");
// Execute the calls described in the data
executeCalls(data);
}
Asset Manager Flow
Initial Transfer
User initiates a cross-chain transfer from the source chain
Transfer includes optional additional actions (encoded in
data
)
Hub Chain Processing
AssetManager receives and verifies the cross-chain message
Mints corresponding tokens on the Hub chain
If additional actions are specified:
Locates the user's wallet using WalletFactory
Calls the wallet's assetManagerHook with the specified actions
Security Measures
Only the authorized AssetManager contract can call the wallet's hook
Messages must come from authorized spoke AssetManagers
All cross-chain messages are verified through the connection contract
Example Use Case: Transfer and Stake
// Example of transfer data that includes staking action
Transfer {
token: "0x...", // Source chain token address
from: userAddress,
to: hubWalletAddress,
amount: 1000,
data: abi.encode([
ContractCall({
addr: STAKING_CONTRACT,
value: 0,
data: abi.encodeWithSignature("stake(uint256)", 1000)
})
])
}
This transfer would:
Move tokens from the source chain to the Hub chain
Mint tokens to the user's Hub wallet
Automatically stake the tokens through the wallet's assetManagerHook
Security Considerations
Only the designated AssetManager contract can invoke the assetManagerHook
Cross-chain messages must come from authorized spoke AssetManagers
All operations are executed in the context of the user's wallet
The hook system prevents unauthorized access to wallet functions
Asset transfers and subsequent actions are atomic (they either all succeed or all fail)
Last updated