This document describes the on-chain side of Flashix: how the trusted signal is verified, how flashloans are issued, how trades execute atomically, and how execution evidence is emitted for later settlement and audit.
The Solidity sources live in contracts/contracts/ and the generated ABI and deployment artifacts live under contracts/.
Source: contracts/contracts/SignalValidator.sol
SignalValidator is the trust gate between 0G Compute and execution.
What it does:
- Accepts a structured
ArbitrageSignal. - Reconstructs the canonical signal hash with
abi.encode(...). - Applies the Ethereum signed-message prefix.
- Recovers the signer from
(v, r, s). - Checks the recovered signer against the trusted TEE address.
- Rejects expired or already-used signals.
- Marks a signal as used to prevent replay.
Important state:
trustedSignerstores the current verified TEE address.usedSignalstracks opportunity IDs that have already been consumed.chainIdis stored for domain separation.
Important events:
SignalVerifiedSignalUsedTrustedSignerUpdated
Failure modes:
InvalidSignaturewhen the recovered signer does not match the trusted address.SignalExpiredwhen the deadline has passed.SignalAlreadyUsedwhen the opportunity ID was already consumed.InvalidOpportunityIdwhen the signal is empty.
Source: contracts/contracts/LendingPool.sol
LendingPool is the ERC-3156 flashloan provider used to source capital for arbitrage execution.
What it does:
- Maintains token liquidity for supported assets.
- Calculates the fee for each flashloan.
- Transfers the borrowed token to the borrower.
- Calls the borrower callback.
- Verifies repayment plus fees before completing the transaction.
- Tracks accumulated fees for later withdrawal.
Important state:
supportedTokensmarks which ERC-20 tokens can be borrowed.accumulatedFeesstores collected fees per token.
Important configuration:
FEE_BPSis currently 9 basis points.- The constructor enables example stablecoins by default, but the token list should be adjusted for the deployment network.
Failure modes:
UnsupportedTokenif the asset is not whitelisted.InsufficientLiquidityif the requested amount exceeds available capital.InsufficientRepaymentif the callback does not restore the pool balance.InvalidFlashLoanReturnif the borrower callback does not return the expected hash.
Source: contracts/contracts/ArbitrageExecutor.sol
ArbitrageExecutor coordinates the full arbitrage lifecycle once a signal has been verified.
What it does:
- Receives the flashloan callback from
LendingPool. - Validates that the calling pool and validator are configured.
- Decodes the execution signal and optional trace ID.
- Checks that both DEX routers are approved.
- Executes the arbitrage path.
- Measures realized profit.
- Repays the loan plus fee.
- Sends remaining profit to the configured recipient.
- Emits execution and trace events for the UI and settlement layer.
Important state:
lendingPoolis the configured flashloan source.signalValidatoris the on-chain verification contract.profitRecipientreceives realized profit.approvedRoutersis the allowlist for DEX endpoints.traceIdsByOpportunitybinds a signal ID to a reasoning trace.
Important events:
ArbitrageExecutedTraceLinkedRouterApprovalUpdatedProfitRecipientUpdatedLendingPoolUpdatedSignalValidatorUpdated
Failure modes:
SignalVerificationFailedif the signal is not accepted.SignalExpiredif the execution deadline has passed.UnapprovedRouterif either DEX address is not on the allowlist.InsufficientProfitif realized profit falls below the threshold.LendingPoolNotConfiguredorSignalValidatorNotConfiguredwhen setup is incomplete.
The on-chain flow is intentionally simple and strict:
- The TEE signs a canonical signal off-chain.
- The agent packages the signal for execution.
ArbitrageExecutorreceives the flashloan callback.SignalValidatorverifies the signal and marks it used.- The executor checks that both routers are approved.
- The trade path executes.
- The executor measures realized profit.
- The loan principal and fee are repaid.
- Profit is forwarded to the recipient.
- Events are emitted for audit and settlement.
This path is atomic: if a validation step, repayment step, or router check fails, the whole transaction reverts.
The contract verification path mirrors the Python encoder exactly.
The contract reconstructs the hash from:
opportunityIddexAdexBborrowTokenborrowAmountminProfitdeadlinechainId
It then applies the Ethereum signed-message prefix and recovers the signer using ECDSA. This is the critical compatibility point with compute/signal_encoder.py.
LendingPool.flashLoan() performs the following checks:
- token must be supported
- requested amount must fit within available liquidity
- callback must return the expected ERC-3156 hash
- post-callback balance must cover the borrowed amount plus fee
ArbitrageExecutor.onFlashLoan() then:
- validates the caller
- validates configuration
- checks router allowlisting
- executes the trade
- checks realized profit
- repays the pool
- sends profit onward
These steps give Flashix a clean borrow/execute/repay boundary that the settlement and monitoring layers can reason about.
The deployment artifacts under contracts/ should be treated as the source of truth for the currently deployed network state.
Key points:
- Deployment manifests live under
contracts/deployments/. - TypeChain and ABI outputs are generated under
contracts/typechain-types/andcontracts/abi/. - The Hardhat workspace must match the target chain configuration before any verification or replay testing.
Before deploying or re-running the contracts:
- Confirm the trusted signer address.
- Confirm the token addresses for the target chain.
- Confirm the router allowlist.
- Confirm the pool liquidity.
- Confirm the expected chain ID.
- Replay protection comes from
usedSignalsinSignalValidator. - Execution safety comes from the flashloan callback and repayment checks.
- Router allowlisting prevents arbitrary DEX usage.
- The
PausableandOwnableinheritance in the execution contracts support emergency control and administrative updates. - The execution receipt is emitted as an event, which keeps the proof trail auditable without requiring the UI to infer state from heuristics.
The frontend surfaces this contract behavior in the execution and compute views:
- The Compute page shows the linked request, validation state, and proof artifact.
- The Execution page shows the on-chain proof card and explorer links.
- The Settlement page uses the execution outcome to summarize realized PnL and exports.