Skip to main content
The Portal is the single contract you interact with on every chain. It handles intent publishing, fulfillment, reward claiming, and ERC-7683 compatibility. It holds no funds between transactions, all rewards sit in deterministically-deployed per-intent vaults.

Architecture

The Portal does not hold funds between transactions. All rewards are escrowed in deterministically-deployed vault contracts.

Intent Lifecycle

1. Publishing (Source Chain)

Users create intents specifying execution instructions for the destination chain and rewards for solvers. Direct Publishing:
Creates an intent without funding. Emits IntentPublished event. Atomic Publishing with Funding:
Creates and funds an intent in a single transaction. Universal Format Publishing:
Cross-VM compatible publishing using bytes format for route data.

2. Funding (Source Chain)

Intents can be funded separately after creation:
Funding for Others:
Uses permit contracts for gasless token approvals. Cannot be used for intents with native token rewards.

3. Fulfillment (Destination Chain)

Solvers execute intent instructions on the destination chain:
Parameters:
  • intentHash: Unique identifier of the intent
  • route: Execution instructions and token requirements
  • rewardHash: Hash of reward structure for verification
  • claimant: Cross-VM compatible identifier for reward recipient (bytes32)
Atomic Fulfillment with Proving:
Executes intent and initiates cross-chain proof in one transaction. ⚠️ Important: sourceChainDomainID is NOT the chain ID. Each bridge uses its own domain ID system:
  • Hyperlane: Custom domain IDs
  • LayerZero: Endpoint IDs
Consult the bridge provider’s documentation for correct domain IDs.

4. Proving (Destination Chain)

Generate proofs for fulfilled intents:
Sends cross-chain message to source chain verifying intent execution. Can batch multiple intents for gas efficiency.

5. Claiming Rewards (Source Chain)

After proof verification, solvers claim rewards:
Transfers rewards from vault to the claimant address specified during fulfillment. Batch Withdrawal:
Efficiently claim multiple rewards in one transaction.

6. Refunds (Source Chain)

Creators can reclaim rewards after expiry:
Only succeeds if:
  • Intent has expired (block.timestamp >= reward.deadline)
  • Intent was not fulfilled on the correct destination chain

ERC-7683 Compatibility

The Portal implements both ERC-7683 origin and destination settler interfaces.

Origin Functions

Direct Order Opening:
Creates and funds an intent from an onchain order structure. Gasless Order Opening:
Creates an intent using EIP-712 signature. Validates:
  • Signature matches order.user
  • openDeadline not passed
  • originSettler matches contract address
  • originChainId matches current chain
Order Resolution:
Converts Eco orders into ERC-7683 standard format.

Destination Functions

ERC-7683 Fulfillment:
Parameters:
  • orderId: Intent hash from origin chain
  • originData: Encoded (bytes route, bytes32 rewardHash)
  • fillerData: Encoded (address prover, uint64 source, bytes32 claimant, bytes proverData)
Decodes data and calls fulfillAndProve() internally.

Vault System

The Portal uses deterministic CREATE2 deployment for intent vaults.

Computing Vault Address

Returns the deterministic vault address without deployment.

Vault States

Vaults track intent lifecycle through status enum:
  • Initial: Intent created but not funded
  • Funded: Fully funded and ready for fulfillment
  • Withdrawn: Rewards claimed by solver
  • Refunded: Rewards returned to creator

Funding Validation

Checks if vault contains sufficient tokens and native currency.

Token Recovery

Recover tokens mistakenly sent to vaults:
Restrictions:
  • Cannot recover zero address
  • Cannot recover any token in reward.tokens
  • Intent must have zero native rewards OR already be claimed/refunded

Intent Hashing

The Portal uses a deterministic hashing scheme:
Formula:
This allows verification on destination chains without transmitting full intent data.

Execution Model

Source Chain Execution

The Portal transfers tokens from users to vaults:
  1. Native tokens via payable function calls
  2. ERC20 tokens via SafeERC20.safeTransferFrom
  3. Excess ETH refunded automatically

Destination Chain Execution

The Portal delegates call execution to an Executor contract:
  1. Transfers tokens from solver to Executor
  2. Executor performs calls with delegated tokens
  3. Executor has no persistent state between transactions
This isolation ensures:
  • Portal storage is protected during arbitrary calls
  • Failed calls don’t corrupt Portal state
  • Executor can be upgraded independently

Security Features

Replay Protection

  • Intent hashes are unique (include salt in route)
  • Fulfilled intents cannot be fulfilled again
  • Withdrawn/refunded intents cannot be withdrawn/refunded again
  • ERC-7683 gasless orders use nonces

Validation

Publishing:
  • Cannot republish withdrawn/refunded intents
  • Validates reward structure consistency
Fulfillment:
  • Verifies intent hash matches route and reward
  • Checks portal address in route matches contract
  • Validates deadline hasn’t passed
  • Prevents zero claimant address
  • Requires minimum native token amount
Withdrawal:
  • Validates intent is proven on correct destination
  • Challenges proofs for incorrect destinations
  • Prevents withdrawal before proof
Refund:
  • Only after deadline expiry
  • Only if not proven on correct destination
  • Prevents refund of claimed intents

Reentrancy Protection

All external calls are made through:
  • SafeERC20 for token transfers
  • Isolated Executor for user-specified calls
  • State updates before external interactions

Cross-VM Compatibility

The Portal supports both EVM and non-EVM chains:

Address Conversion

Claimant Identifiers

On destination chains, claimants are stored as bytes32:
This supports:
  • EVM addresses (20 bytes, left-padded)
  • Solana addresses (32 bytes)
  • Other blockchain address formats

Events

IntentPublished

IntentFunded

IntentFulfilled

IntentProven

IntentWithdrawn

IntentRefunded

IntentTokenRecovered

Open (ERC-7683)

OrderFilled (ERC-7683)

Error Handling

  • ArrayLengthMismatch(): Array parameters have mismatched lengths
  • ChainIdTooLarge(uint256): Chain ID exceeds uint64 maximum
  • InsufficientFunds(bytes32): Incomplete funding when partial not allowed
  • InsufficientNativeAmount(uint256, uint256): Insufficient native tokens for execution
  • IntentAlreadyExists(bytes32): Cannot republish existing intent
  • IntentAlreadyFulfilled(bytes32): Intent already fulfilled
  • IntentExpired(): Past route deadline
  • IntentNotClaimed(bytes32): Cannot refund claimed intent
  • IntentNotFulfilled(bytes32): Intent not in fulfilled state
  • InvalidClaimant(): Zero address claimant
  • InvalidHash(bytes32): Computed hash doesn’t match provided hash
  • InvalidOriginChainId(uint256, uint256): Chain ID mismatch in ERC-7683 order
  • InvalidOriginSettler(address, address): Settler address mismatch in ERC-7683 order
  • InvalidPortal(address): Route portal doesn’t match contract
  • InvalidRecoverToken(address): Cannot recover specified token
  • InvalidSignature(): EIP-712 signature verification failed
  • InvalidStatusForFunding(Status): Cannot fund withdrawn/refunded intent
  • InvalidStatusForRefund(Status, uint256, uint256): Invalid refund conditions
  • InvalidStatusForWithdrawal(Status): Cannot withdraw non-funded intent
  • OpenDeadlinePassed(): ERC-7683 order opening deadline exceeded
  • TypeSignatureMismatch(): ERC-7683 orderDataType mismatch
  • ZeroClaimant(): Claimant cannot be zero

Integration Examples

Creating and Funding an Intent

Fulfilling on Destination

Claiming Rewards

Batch Operations