Purpose
The Executor serves as a security boundary for intent execution: Without Executor:Architecture
- One executor per Portal deployment
- Stateless (no storage between transactions)
- Only Portal can trigger execution
- Receives tokens from solver before execution
- Returns unused tokens/ETH to solver after execution
Access Control
- Direct execution of arbitrary calls
- Bypassing intent validation
- Unauthorized token access
Execution Flow
Call Execution
- Portal validates intent and transfers tokens to executor
- Portal calls executor with intent’s call array
- Executor validates and executes each call sequentially
- Executor returns results to Portal
- Portal refunds unused ETH to solver
Single Call
- Target: Contract address to call
- Value: Native token amount to send
- Data: Encoded function call data
- Checks if call targets EOA with calldata (security check)
- Uses low-level
call()
for execution - Reverts entire transaction if any call fails
Security Features
EOA Protection
- EOAs cannot execute code, so calldata is meaningless
- Calldata to EOA might indicate misconfiguration
- Prevents potential phishing where calldata appears to be a function call
- Native token transfers to EOAs (zero calldata)
- Calls to contracts (non-zero code length)
- Calls to EOAs with calldata (suspicious pattern)
Storage Isolation
The Executor has no state variables exceptimmutable portal
:
- Cannot be manipulated through reentrancy
- No persistent state to corrupt
- Fresh execution context for each intent
Atomic Execution
All calls execute atomically:- If any call fails, entire transaction reverts
- No partial execution of intent
- Solver either succeeds completely or loses only gas
Token Handling
Token Flow
Native Tokens
The Executor accepts ETH via:route.nativeAmount
to Executor before execution:
ERC20 Tokens
Portal transfers ERC20s to Executor before execution:Call Structure
Example Calls
Token Swap:Error Handling
CallToEOA
- Remove calldata for simple transfers
- Use correct contract address if calling contract
- Verify target address is not an EOA
CallFailed
- Full call data (target, value, data)
- Revert reason from failed call
- Insufficient token balance in executor
- Reverted function on target contract
- Out of gas
- Invalid function selector
NonPortalCaller
- Only Portal can call executor
- Use Portal’s fulfill methods instead of direct executor calls
Execution Patterns
Simple Transfer
Intent that sends tokens to recipient:Swap and Transfer
Intent that swaps tokens and sends result:Multi-Step DeFi
Intent executing complex DeFi operations:Gas Considerations
Per-Call Overhead
Each call incurs:- Call validation: ~2,000 gas (EOA check)
- Low-level call: ~2,600 gas base + execution
- Result handling: ~1,000 gas
Batch Optimization
Multiple calls in one intent are more efficient than separate intents:- Shared validation costs
- Single token transfer from solver
- Atomic execution reduces failure risk
Failed Call Costs
When a call fails:- Gas consumed up to failure point
- Full transaction reverts (no state changes)
- Solver pays gas but receives no reward
Integration Patterns
For Intent Creators
Encoding Calls:For Solvers
Pre-Execution Validation:Security Best Practices
For Intent Creators
- Test Thoroughly: Simulate all calls before publishing intent
- Minimal Privileges: Only include necessary calls in route
- Verify Targets: Ensure all target addresses are correct contracts
- Amount Validation: Verify all token amounts and values are correct
- Deadline Safety: Set appropriate route deadline for execution window
For Solvers
- Validate Before Fulfilling: Simulate execution to avoid wasted gas
- Check Token Balances: Ensure sufficient tokens to provide route amounts
- Gas Estimation: Estimate execution costs accurately
- Slippage Protection: Account for price changes in DEX calls
- Revert Analysis: Understand why calls might fail before executing
For Protocol Integrators
- Immutable Executor: Executor address never changes per Portal
- No Direct Calls: Never call executor directly, always through Portal
- Result Handling: Process execution results appropriately
- Error Recovery: Handle call failures gracefully in UI/SDK
Limitations
No Persistent State
Executor cannot:- Store data between transactions
- Accumulate tokens across intents
- Maintain allowances or permissions
No Token Retention
After execution:- All tokens should be transferred to final destinations
- Executor should have zero balance
- Any remaining tokens are stuck until next execution
Sequential Execution
Calls execute in order:- Cannot parallelize
- Later calls depend on earlier ones
- Any failure reverts all