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

# Verify on EVM

> Verify a Molpha payload in your Solidity contract with one view call.

A consumer contract receives a `DataUpdate` + `SchnorrSignature` in calldata, verifies it against the Molpha Verifier, and acts on the value in the same transaction.

## Build the calldata

`buildEvmVerifierArgs` maps a gateway `DataUpdateResult` onto the on-chain structs with zero runtime dependency on ethers/viem:

```text theme={null}
gateway DataUpdateResult       →  IVerifier.DataUpdate
  feedId, registryVersion,          feedId, registryVersion,
  signaturesRequired,              signaturesRequired,
  valuePacked, timestamp           value, canonicalTimestamp

                               →  IVerifier.SchnorrSignature
  s                                signature
  commitmentAddr                   commitment
  signersBitmap                    signersBitmap
```

## Consumer contract

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.31;

import {IVerifier} from "molpha-core-contracts/interfaces/IVerifier.sol";

contract MyConsumer {
    IVerifier public immutable verifier;
    uint256 public constant MAX_STALENESS = 60; // seconds

    constructor(address verifier_) {
        verifier = IVerifier(verifier_);
    }

    function settle(
        IVerifier.DataUpdate calldata update,
        IVerifier.SchnorrSignature calldata sig
    ) external {
        // 1. Cryptographic verification — MUST check the return value.
        require(verifier.verify(update, sig), "Molpha: invalid signature");

        // 2. Freshness — the verifier does not enforce staleness; the consumer does.
        require(
            block.timestamp - update.canonicalTimestamp <= MAX_STALENESS,
            "Molpha: stale data"
        );

        // 3. Application logic using the verified value.
        _useValue(update.value);
    }

    function _useValue(bytes32 value) internal { /* ... */ }
}
```

<Warning>
  `verify` returns a boolean — it does **not** revert on a cryptographically invalid signature (structural violations revert; a bad signature returns `false`). Always `require(...)` the return value, or your contract will silently accept unverified data.
</Warning>

## Consumer responsibilities

`verify` proves *who signed what*, not *when you read it*. Your contract must:

* **Enforce freshness** against `canonicalTimestamp` — the verifier is stateless and has no replay window of its own.
* **Prevent replay** if your flow can be re-executed — the same valid payload verifies forever.
* **Validate `feedId` and `signaturesRequired`** match the feed you intend to consume.

## Gas

Representative execution gas from the repository benchmarks (`forge test --match-test test_gas_verify -vv`):

| Nodes | Threshold | Execution gas | Calldata gas | Est. total (with 21k base) |
| ----: | --------: | ------------: | -----------: | -------------------------: |
|     5 |         3 |      \~12,900 |      \~1,920 |                   \~35,800 |
|    10 |         5 |      \~16,900 |      \~1,930 |                   \~39,800 |
|    20 |         8 |      \~23,500 |      \~1,950 |                   \~46,400 |

Full contract reference: [EVM Verifier](/verifiers/evm). Deployed addresses: [Deployments](/verifiers/deployments).
