> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How the local prover works

> Same-chain intent fulfillment without cross-chain messaging

The Local Prover handles same-chain intent fulfillment where both intent creation and execution occur on the same blockchain. Unlike cross-chain provers, it requires no message passing infrastructure.

## Architecture

```mermaid theme={null}
sequenceDiagram
    participant App
    participant Portal as Portal (Same Chain)
    participant LP as LocalProver
    participant Vault

    App->>Portal: Publish intent (destination = current chain)
    App->>Vault: Fund vault (ERC-20 transfer)
    Note over App,Vault: No contract interaction - just a transfer
    Portal->>Portal: Solver fulfills intent
    Portal->>LP: Read claimant (instant)
    Vault->>Portal: Release rewards to solver
```

## Purpose

Local Prover enables intents to be fulfilled on their origin chain:

* No cross-chain messaging required
* Zero additional fees beyond gas
* Instant proof availability
* Useful for same-chain swaps, transfers, or operations

## Orchestration Mode

Beyond same-chain convenience, the Local Prover enables a fundamentally different execution model: **orchestration**. In orchestration mode, the user's own funds move through underlying infrastructure, no solver capital required.

This is powered by `flashFulfill`, a flash-loan-style operation that fulfills an intent using the vault's own funds within a single atomic transaction. The vault's contents are used directly to execute the desired action on the destination, with no counterparty and no cross-chain message.

In Eco Routes, this same-chain self-solve capability is offered as **Flash Intents**, a configurable intents mode that settles same-chain stablecoin orders atomically using the user's own funds.

**Settlement vs. Orchestration:**

* **Settlement**: A solver provides its own inventory to deliver the user's requested outcome. Zero slippage.
* **Orchestration**: User funds move through infrastructure at the cost of gas alone. Zero solver capital required.

The Local Prover and `flashFulfill` make the system available even when no solver is online, creating a high-availability fallback:

| **Tier** | **Condition**                          | **Mode**                    | **Capital Required** |
| -------- | -------------------------------------- | --------------------------- | -------------------- |
| 1        | Solver available, better pricing       | Settlement                  | Solver capital       |
| 2        | Solver available, no pricing advantage | Orchestration               | Gas only             |
| 3        | No solver available                    | Self-solve via local intent | Gas only             |

All three tiers use the same Portal, vaults, and API. System availability equals chain availability, not solver availability.

## Configuration

```solidity theme={null}
constructor(address inbox)
```

**Parameters:**

* `inbox`: Portal contract address

**Initialization:**

* Stores Portal reference as immutable
* Records chain ID for proof data validation
* Validates chain ID fits in uint64

## How It Works

### Immediate Proof Creation

Unlike cross-chain provers, the Local Prover doesn't create proofs. It reads them:

1. Intent fulfilled on Portal → claimant stored in `Portal.claimants` mapping
2. `provenIntents()` queries Portal's claimant mapping directly
3. Returns proof data with current chain ID and claimant address

### Proof Lookup

```solidity theme={null}
function provenIntents(bytes32 intentHash) 
    public view returns (ProofData memory)
```

**Returns:**

* `claimant`: Address that fulfilled the intent (converted from bytes32)
* `destination`: Current chain ID

**If not fulfilled:**

* Returns `ProofData(address(0), 0)`

### No-Op Functions

#### prove()

```solidity theme={null}
function prove(
    address sender,
    uint64 sourceChainId,
    bytes calldata encodedProofs,
    bytes calldata data
) external payable
```

**Intentionally empty** - no action needed because:

* Claimant already stored by Portal during fulfillment
* No cross-chain message to send
* Proof is immediately available

**Can be called** without reverting to support `fulfillAndProve()` pattern.

#### challengeIntentProof()

```solidity theme={null}
function challengeIntentProof(
    uint64 destination,
    bytes32 routeHash,
    bytes32 rewardHash
) external pure
```

**Intentionally empty** - challenges not applicable because:

* Same-chain intents cannot be proven on wrong chain
* No cross-chain discrepancy possible

## Usage Patterns

### Creating Same-Chain Intent

```solidity theme={null}
Intent memory intent = Intent({
    destination: block.chainid,  // Same as current chain
    route: Route({
        portal: address(portal),
        // ... other route params
    }),
    reward: Reward({
        prover: address(localProver),  // Use LocalProver
        // ... other reward params
    })
});

portal.publishAndFund{value: amount}(intent, false);
```

### Fulfilling Same-Chain Intent

```solidity theme={null}
// Fulfill without proving
portal.fulfill{value: route.nativeAmount}(
    intentHash,
    route,
    rewardHash,
    claimant
);

// OR fulfill and prove (prove is no-op but doesn't revert)
portal.fulfillAndProve{value: route.nativeAmount}(
    intentHash,
    route,
    rewardHash,
    claimant,
    address(localProver),
    uint64(block.chainid),
    "" // Empty data
);
```

Both patterns work identically. `prove()` is a no-op.

### Claiming Rewards

```solidity theme={null}
// Check if intent is proven (fulfilled)
IProver.ProofData memory proof = localProver.provenIntents(intentHash);
require(proof.claimant != address(0), "Not fulfilled");

// Withdraw rewards
portal.withdraw(
    uint64(block.chainid),
    routeHash,
    reward
);
```

## Fee Structure

**Zero additional fees:**

* No cross-chain messaging costs
* No bridge fees
* Only standard gas costs for fulfillment and withdrawal

## When to Use Local Prover

### Ideal Use Cases

**Same-Chain Operations:**

* Token swaps on same chain
* Transfers between accounts
* DeFi operations on single chain
* Testing and development

**Advantages:**

* Instant settlement (no message delays)
* Zero bridging costs
* Simpler integration
* No external dependencies

### Not Suitable For

* Cross-chain transfers
* Multi-chain operations
* Bridging assets between chains

For cross-chain intents, use:

* [HyperProver](/routes/architecture/provers/hyperlane) (Hyperlane)
* [LayerZeroProver](/routes/architecture/provers/layerzero) (LayerZero)
* [PolymerProver](/routes/architecture/provers/polymer) (Polymer IBC)
* [CCTP Prover](/routes/architecture/provers/cctp) (Circle attestation)

## Integration Example

```solidity theme={null}
// Deploy Local Prover
LocalProver localProver = new LocalProver(address(portal));

// Create same-chain intent
Intent memory intent = Intent({
    destination: uint64(block.chainid),
    route: Route({
        salt: keccak256(abi.encode(user, nonce)),
        deadline: block.timestamp + 1 hours,
        portal: address(portal),
        nativeAmount: 0,
        tokens: tokenAmounts,
        calls: calls
    }),
    reward: Reward({
        creator: msg.sender,
        prover: address(localProver),
        deadline: block.timestamp + 1 hours,
        nativeAmount: 0.01 ether,
        tokens: rewardTokens
    })
});

// Publish and fund
portal.publishAndFund{value: 0.01 ether}(intent, false);

// Solver fulfills
portal.fulfill{value: route.nativeAmount}(
    intentHash,
    route,
    rewardHash,
    bytes32(uint256(uint160(solverAddress)))
);

// Solver claims rewards immediately
portal.withdraw(
    uint64(block.chainid),
    routeHash,
    reward
);
```

## Comparison with Cross-Chain Provers

| Feature                | LocalProver     | Cross-Chain Provers     |
| ---------------------- | --------------- | ----------------------- |
| **Proof Availability** | Immediate       | After message delivery  |
| **Additional Fees**    | None            | \$5-50 per message      |
| **Message Delays**     | None            | Seconds to minutes      |
| **Infrastructure**     | None required   | Bridge dependencies     |
| **Complexity**         | Minimal         | Domain IDs, hooks, etc. |
| **Use Case**           | Same chain only | Cross-chain operations  |

## Best Practices

### Intent Creation

**Set destination correctly:**

```solidity theme={null}
destination: uint64(block.chainid)  // Must match current chain
```

**Use Local Prover:**

```solidity theme={null}
prover: address(localProver)  // Not a cross-chain prover
```

### Fulfillment

**Either pattern works:**

```solidity theme={null}
// Simple: fulfill only
portal.fulfill(intentHash, route, rewardHash, claimant);

// With prove (no-op): works with fulfillAndProve
portal.fulfillAndProve(
    intentHash, route, rewardHash, claimant,
    address(localProver), uint64(block.chainid), ""
);
```

### Validation

**Check destination matches:**

```solidity theme={null}
require(
    intent.destination == block.chainid,
    "Not same-chain intent"
);
```

**Verify prover is LocalProver:**

```solidity theme={null}
require(
    intent.reward.prover == address(localProver),
    "Wrong prover"
);
```

## Error Handling

* `ChainIdTooLarge(uint256)`: Chain ID exceeds uint64.max during construction

**Note:** LocalProver functions (`prove`, `challengeIntentProof`) never revert. They are intentionally no-ops.

## Technical Notes

### Why prove() is Empty

The `prove()` function is empty because:

1. Portal stores claimant in `claimants` mapping during fulfillment
2. `provenIntents()` queries this mapping directly
3. No cross-chain message needed
4. Proof is instantly available

### Why No Fees

No fees because:

* No cross-chain message to send
* No bridge infrastructure to pay
* No external services required
* Only standard EVM gas costs

### Claimant Storage

```solidity theme={null}
// Portal stores during fulfill()
claimants[intentHash] = claimant;

// LocalProver reads it
bytes32 claimant = _PORTAL.claimants(intentHash);
```

Direct storage access eliminates need for proving.

## Constant

```solidity theme={null}
function getProofType() external pure returns (string memory) {
    return "Same chain";
}
```

Identifies this prover handles same-chain intents.
