- Intents Contract (Hub) - The central coordinator that:
- Manages intent creation and lifecycle
- Handles settlement of trades
- Coordinates cross-chain communication
- Maintains the source of truth for all intents
- IntentFiller Contract (Spokes) - Deployed on spoke chains to:
- Enable local fulfillment of intents
- Lock solver funds during cross-chain settlement
- Relay fill confirmations back to the hub
Core Architecture
Centralized Settlement
All intent logic and final settlement occurs on the hub chain. This design choice provides several benefits:- Single source of truth for intent status
- Simplified accounting and settlement
- Reduced cross-chain complexity
- Atomic execution of trades
Spoke Chain Role
Spoke chains serve as execution venues that:- Allow solvers to fill intents directly on destination chains
- Provide faster user experience by avoiding cross-chain delays
- Act as temporary fund escrow for cross-chain settlements
- Do not maintain any intent state - they only facilitate fills
Flow Example
- User creates intent on hub chain
- Solver sees intent and locks funds on spoke chain
- Spoke chain notifies hub of the fill attempt
- Hub validates and settles the trade
- Hub notifies spoke to release funds to user
- Solver receives payment on hub chain
Intents System - Data Structures and Events
Intent Structure
The coreIntent structure represents a user’s trading desire with the following fields:
Events
Intent Lifecycle Events
Supporting Structures
IntentState
Tracks the current state of an intent:PendingIntentState
Tracks cross-chain fills in progress:ExternalFill
Records details of cross-chain fills:Payout
Tracks pending payments to solvers:Intents System - Function Interface
Hub Chain (Intents Contract)
Intent Management
intent: The complete intent specification- Emits:
IntentCreated - Requirements:
inputAmountmust be > 0- Input tokens must be approved to contract
intent: The intent to cancel- Emits:
IntentCancelled - Requirements:
- Intent must exist
- Caller must be creator OR deadline must have passed
- No pending fills can exist
Fill Operations
intent: The intent to fill_inputAmount: Amount of input tokens to consume_outputAmount: Amount of output tokens to provide_externalFillId: ID for cross-chain fills (0 for hub-chain)- Requirements:
- Intent must exist and not be pending payment
- Fill amount must be valid
- Output amount must meet minimum requirements
- Solver restrictions must be met
- Similar to
fillIntentbut creates intent if it doesn’t exist - Marks intent as pending payment
- Used for optimistic filling scenarios
Administrative Functions
chainID: Chain ID of the spokespokeAddress: Address of the IntentFiller contract on spoke chain
solver: Address of the solverwhitelisted: Whether solver is approved
Spoke Chain (IntentFiller Contract)
This section will be implemented by the spoke chain and thus wont be exactly the same as the EVM implementation.Fill Data Structure
TheFill struct is the core data structure used to represent fill attempts on spoke chains:
Field Details:
fillID:- Unique identifier generated by the solver
- Used to track the fill across chains
- Must be unique per intent-solver combination
- Used to prevent double-fills
intentHash:- The keccak256 hash of the original intent from the hub
- Stored in bytes format for cross-chain compatibility
- Used to link the fill to the original intent
solver:- Address of the solving entity in bytes format
- Will receive payment on the hub chain upon successful fill
- Cross-chain format allows for different address formats across chains
receiver:- Destination address for the filled tokens
- Matches the
dstAddressfrom the original intent - Stored in bytes for cross-chain compatibility
token:- Address of the token being transferred
- Stored in bytes format for cross-chain compatibility
- Can be the zero address (represented in bytes) for native currency
amount:- Quantity of tokens being transferred
Fill Operations
fill: Fill details including amount and recipient- Requirements:
- For native token, msg.value must match fill amount
- For ERC20, tokens must be transferred to contract
fill: Fill to cancel- Requirements:
- Fill must exist
- Caller must be original filler
Token Management and Cross-Chain Asset Handling
Native Token Support
The Intents system supports native tokens (ETH) as both input and output tokens. Native tokens are represented by the zero address (address(0)) in the system.
Native Token Usage
-
As Input Token:
- When creating an intent with native token as input, the user must send the correct amount of ETH with the transaction
- The amount must include both the input amount and any fees
- Example:
-
As Output Token:
- When filling an intent with native token as output, the solver must send the correct amount of ETH with the transaction
- The native token can only be sent to the hub chain (no cross-chain native token transfers)
- Example:
Native Token Restrictions
- Cross-Chain Limitations:
- Native tokens can only be used on the hub chain
- Cross-chain transfers of native tokens are not supported
- When using native tokens, the
dstChainmust be set to the hub chain ID
- Fee Handling:
- Fees in native tokens work the same way as ERC20 tokens
- The total amount sent must include both the input amount and the fee
- Fees are distributed proportionally for partial fills
Examples
- Native to ERC20 Intent:
- ERC20 to Native Intent:
Token Mapping System
The system uses theAssetManager contract to maintain mappings between tokens across different chains. Each token has:
- A home chain (where it originates)
- A address on each chain where it exists
- A relationship with the hub chain representation
Token Transfer Logic
The hub’ssendToken function handles all token transfers when filling an intent based on destination chain configuration:
Transfer Cases
- To Hub Chain (dstChainID == HUB_CHAIN_ID):
When the dst in the intent is set to the hub chain, the token is transferred directly to the user. - To Non-Home Chain (dstChainID != chainID):
If the intent is done to a different chain than the token’s home chain, the token is transferred to a wallet abstraction on the hub chain for that specific user. - To Home Chain (dstChainID == chainID):
If the intent is done to the token’s home chain, the token is transferred directly to the user via the AssetManager.
Token Flow Example
For a cross-chain intent where:- Input token is native to Chain A
- Output token is native to Chain B
- Intent is created and settled on Hub Chain
- User sends tokens from Chain A to Hub
- Solver fills the intent on the Hub Chain
- Hub uses AssetManager to bridge directly to Chain B
- Solver receives payment on Hub chain
External Fill token mappings
While all intents created needs to be between tokens represented on the hub chain, when filling externally the solver must fill the correct token representation on the spoke chain. Which can be queried from the asset manager.Fee System
Overview
The Intents system supports a flexible fee mechanism that allows for partner fees to be collected during intent execution. Fees are specified in the intent’s data field and are handled automatically during the fill process.Fee Data Structure
Fees are encoded in the intent’s data field using the following structure:Fee Encoding
Fees are encoded in the intent’s data field with a type identifier:Fee Collection Process
During Intent Creation
- User must approve the contract for
inputAmount + fee - The full amount (including fee) is transferred to the contract
- The fee data is stored in the contract’s state
During Fill Operations
- For full fills:
- The fee is sent to the fee receiver
- The remaining amount is sent to the solver
- For partial fills:
- The fee is proportionally split
- The filled portion’s fee is sent to the fee receiver
- The remaining fee is returned to the creator upon cancellation
During Cancellation
- If the intent is cancelled before any fills:
- The full fee is returned to the creator
- If the intent is partially filled:
- The filled portion’s fee is sent to the fee receiver
- The remaining fee is returned to the creator
Fee Examples
Full Fill
Partial Fill (50%)
Cancellation
Important Considerations
- Fees are always denominated in the input token
- The fee amount must be approved along with the input amount
- Fees are handled automatically by the contract
- Partial fills result in proportional fee distribution
- Cancellation returns any unclaimed fees to the creator