Skip to main content

Overview

PolymerProver processes proof messages from Polymer’s CrossL2ProverV2 and records proven intents. Unlike other provers, it uses log event proofs rather than direct cross-chain messaging. Contract: contracts/prover/PolymerProver.sol Inheritance: BaseProver, Whitelist, Semver Proof Type: "Polymer"
Polymer uses chain IDs (not custom domain IDs) and validates cross-chain events through cryptographic proofs of event logs.

Constructor

Initializes the PolymerProver contract.
address
required
Address of the Portal contract
address
required
Address of Polymer’s CrossL2ProverV2 contract
uint256
required
Maximum allowed size for encodedProofs in IntentFulfilledFromSource event data. Must be between 1 and 32,768 bytes (32 KB).
bytes32[]
required
Array of whitelisted prover addresses (as bytes32)
Errors:
  • ZeroAddress(): CrossL2ProverV2 address is zero
  • InvalidMaxLogDataSize(): maxLogDataSize is zero or exceeds MAX_LOG_DATA_SIZE_GUARD (32 KB)
  • ZeroPortal(): Portal address is zero
Location: contracts/prover/PolymerProver.sol:53

State Variables

CROSS_L2_PROVER_V2

Address of Polymer’s CrossL2ProverV2 contract used for validating event proofs.

MAX_LOG_DATA_SIZE

Maximum allowed size for encodedProofs in event data. Set at construction.

PROOF_TYPE

Constant indicating this contract uses Polymer for proving.

PROOF_SELECTOR

Event signature hash for the IntentFulfilledFromSource event.

Constants

Core Functions

prove

Emits IntentFulfilledFromSource events that can be proven by Polymer.
uint64
required
Chain ID of the source chain (Polymer uses actual chain IDs, not domain IDs)
bytes
required
Encoded (intentHash, claimant) pairs. Must not exceed MAX_LOG_DATA_SIZE.
Behavior:
  1. Validates caller is PORTAL
  2. Validates encodedProofs size doesn’t exceed MAX_LOG_DATA_SIZE
  3. Emits IntentFulfilledFromSource(sourceChainDomainID, encodedProofs)
Errors:
  • OnlyPortal(): Caller is not the Portal contract
  • MaxDataSizeExceeded(): encodedProofs exceeds MAX_LOG_DATA_SIZE
Access Control: Only callable by PORTAL Note: This function is payable for compatibility but does not use ETH. Location: contracts/prover/PolymerProver.sol:194

validate

Validates a single proof and processes contained intents.
bytes
required
Proof of an IntentFulfilledFromSource event from Polymer’s CrossL2ProverV2
Behavior:
  1. Calls CROSS_L2_PROVER_V2.validateEvent(proof) to verify the event
  2. Validates emitting contract is whitelisted
  3. Validates topics length is 64 bytes (2 topics)
  4. Validates event signature matches PROOF_SELECTOR
  5. Validates source chain ID matches current chain
  6. Validates destination chain ID from proof data
  7. Processes each (intentHash, claimant) pair
Errors:
  • InvalidEmittingContract(address): Emitting contract not whitelisted
  • InvalidTopicsLength(): Topics length is not 64 bytes
  • EmptyProofData(): Data is empty
  • ArrayLengthMismatch(): Proof data length is invalid
  • InvalidEventSignature(): Event signature doesn’t match
  • InvalidSourceChain(): Source chain ID doesn’t match current chain
  • InvalidDestinationChain(): Destination chain from proof data doesn’t match validateEvent result
Location: contracts/prover/PolymerProver.sol:83

validateBatch

Validates multiple proofs in a batch.
bytes[]
required
Array of proof data to validate
Behavior: Iterates through each proof and calls validate(proof). Location: contracts/prover/PolymerProver.sol:73

getProofType

Returns: "Polymer"

Internal Functions

processIntent

Processes a single intent proof.
bytes32
required
Hash of the intent being proven
address
required
Address that fulfilled the intent and should receive rewards
uint64
required
Destination chain ID for the intent
Behavior:
  • If intent already proven, emits IntentAlreadyProven and returns
  • Otherwise, stores proof data and emits IntentProven
Location: contracts/prover/PolymerProver.sol:158

Events

IntentFulfilledFromSource

Emitted on the destination chain when prove() is called. This event is later proven on the source chain using Polymer’s proof system.
uint64
required
Chain ID of the source chain (where intent was created)
bytes
required
Encoded (intentHash, claimant) pairs

Proof Validation Flow

Polymer uses a unique two-step flow:
  1. Destination Chain: Call prove() on PolymerProver to emit IntentFulfilledFromSource event
  2. Source Chain: Generate event proof using Polymer’s infrastructure
  3. Source Chain: Call validate() or validateBatch() with the proof to process intents

Event Data Format

The IntentFulfilledFromSource event data is ABI-encoded bytes containing:

Validation Steps

  1. CrossL2ProverV2 Validation:
    • Polymer’s CrossL2ProverV2 cryptographically verifies the event occurred on destination chain
    • Returns: destinationChainId, emittingContract, topics, data
  2. Authorization Check:
    • Validates emittingContract is whitelisted (must be trusted PolymerProver instance)
  3. Event Signature Validation:
    • Verifies topics[0] matches PROOF_SELECTOR
    • Verifies topics[1] (source chain ID) matches current chain
  4. Data Validation:
    • Decodes ABI-encoded bytes from event data
    • Extracts chain ID from first 8 bytes
    • Verifies chain ID matches destinationChainId from CrossL2ProverV2
  5. Intent Processing:
    • Iterates through (intentHash, claimant) pairs
    • Skips invalid EVM addresses
    • Stores proof data or emits IntentAlreadyProven

Usage Example

On Destination Chain (Intent Fulfillment)

On Source Chain (Proof Validation)

Domain ID vs Chain ID

Polymer uses actual chain IDs, not custom domain IDs. The sourceChainDomainID parameter in prove() should be the actual chain ID of the source chain.Examples:
  • Ethereum Mainnet: 1
  • Optimism: 10
  • Arbitrum: 42161
  • Base: 8453

Security Considerations

Whitelist Management

Only whitelisted prover addresses can emit valid IntentFulfilledFromSource events. This prevents unauthorized proof submissions.

Max Log Data Size

The MAX_LOG_DATA_SIZE limit prevents:
  • Excessive gas costs during event emission
  • Potential DoS attacks via large event logs
  • Storage bloat from oversized proofs

Address Validation

The validate() function skips non-EVM addresses (where upper 96 bits are non-zero), ensuring compatibility with EVM-based reward claims.