Skip to main content
Bor is the block production layer of Polygon Chain. Its block production mechanism is adapted from the Clique proof-of-authority protocol, described in EIP-225, modified for stake-weighted producers selected by Heimdall. Producers sign their blocks using secp256k1. Since the Rio hardfork, each span has exactly one selected producer that seals every block in that span (the “VEBloP” model). If that producer stalls, a new span under a different producer is required to resume block production.

Producer selection

Post-Rio, each span is produced by a single block producer drawn from a small set of eligible producers (the producer pool, currently up to four). The pool is determined on-chain from validator producer votes, and one producer from it is assigned to each span. The producer pool is computed as follows:
  1. Validators cast ranked producer votes on-chain. Each vote is weighted by the voting validator’s stake and by the position of the candidate in that validator’s ranked list, so higher-ranked picks carry more weight.
  2. Candidates are ranked by their total weighted score, with ties broken deterministically by validator ID.
  3. Walking down the ranking, a candidate is admitted only if its score clears a per-position threshold of roughly two-thirds of the maximum possible weighted vote at that position. The first candidate that fails the threshold stops the walk, so the pool can be shorter than the limit, or empty.
  4. If no candidate set qualifies, the network falls back to a default set of producers.
For each span, one producer from this pool is assigned, and the assignment rotates across spans. If the current producer fails to make progress, Heimdall rotates to a different producer in the pool (see Stall detection and span rotation).

Spans

A span is a defined set of blocks produced under a single assigned producer. The producer for each span is drawn from the producer pool (see Producer selection), and the assignment rotates across spans.

Sprints

Within a span, a sprint is a smaller, fixed-size subset of blocks (currently 16 blocks). Pre-Rio, the sprint was the unit at which the producer was committed and at which backup producers rotated. Post-Rio, with a single producer per span, the sprint no longer drives producer selection or delay. The remaining live use of the sprint boundary is state synchronization: Bor commits pending state-sync records at the start of each sprint (see State synchronization with Ethereum).

Block authorization

Block producers sign the hash of the block header (excluding the signature itself) using secp256k1. The signature is appended to the extraData field of the block header. Post-Rio, the span’s single producer seals every block with difficulty 1. There are no backup producers and no out-of-turn signing.

Stall detection and span rotation

If a producer stalls, block production does not fall back to a backup producer. Instead, during header verification Bor detects a stall when a new header has the same author as its parent and no milestone covers it. Bor then blocks production and waits for Heimdall to publish a new span with a different producer (or until a timeout). Recovery therefore depends on Heimdall rotating the span to a new producer.

Span commitment

Heimdall mints spans ahead of time. Bor polls its Heimdall node to fetch new span data and commits it on-chain by calling commitSpan on the BorValidatorSet genesis contract. Bor trusts the span data as given; it points at a single Heimdall endpoint and does not cryptographically verify Heimdall’s data.

State synchronization with Ethereum

Bor synchronizes specific events from Ethereum through a state sync mechanism:
  1. Contracts on Ethereum emit the StateSynced event via StateSender.sol.
  2. Heimdall validators monitor these events and record the state-sync data in Heimdall state.
  3. At the start of every sprint, Bor fetches pending records from Heimdall and commits them via the StateReceiver.sol contract on Bor, keeping Bor state consistent with Ethereum.
This mechanism ensures that deposits from Ethereum are reflected in Bor’s state. For the full state sync flow, see State sync.