Renaiss Engineering · Whitepaper · v1.0.0 · 2026-08-28

Renaiss Gacha: Committed Sets and Verifiable Collectible Draws

Abstract

A gacha draw normally happens inside the operator's server, and the player has to trust that the operator did not choose the outcome. Digital records do not solve this on their own, because an operator who sees the result first can still rewrite it. We propose a protocol built on three pillars. (i) Construction. The Fair Set Algorithm derives each set under published construction constraints, including an expected-value range and minimum and maximum collectible counts for each tier. Top tier collectibles are a guaranteed part of every set: top tier drops are never a maybe. (ii) Seal. Renaiss Gacha draws each set from one large inventory of Renaiss Collectibles, which gives every collectible a fair shot at entering a set. Before the set becomes available, its Merkle root is recorded on-chain, so the lineup can't change after it goes live. A later addition, removal, or substitution produces a different root. (iii) Draw. Each purchase then derives an ECVRF output from post-commit on-chain data. An ECVRF (elliptic curve verifiable random function, RFC 9381) is a keyed function: every output comes with a proof that anyone can check against the published public key. The output is reduced modulo the number of collectibles remaining in the set, and the selected collectible is removed. The proof pins down the exact collectible, proven end to end, not a tier or a range, and a verifier can reconstruct the committed lineup and replay the draws in order without trusting the operator's database.

1Introduction

1.1 · The trust problem

Commerce in gacha has come to rely on the operator serving as a trusted third party for two separate decisions: which collectibles enter a set and which remaining collectible a buyer receives. A fair random draw cannot repair a set that was composed outside its published constraints. A well-built set does not help if the operator can reroll or substitute the selected collectible. Both decisions need public rules and evidence.

Fairness covers the set before sale and the collectible selected after payment. Either claim should be independently checkable.

1.2 · What provable fairness requires

Pillar I · Construction

The Fair Set Algorithm must produce a set that passes the published EV and tier-count rules, so top tier drops are never a maybe.

Pillar II · Seal

The set is drawn from the full Renaiss Collectible inventory and sealed by an on-chain Merkle root before sale. The lineup can't change after it goes live.

Pillar III · Draw

Post-commit on-chain data, ECVRF, and modulo over the remaining collectibles pin down the exact collectible, provable end to end.

1.3 · Contributions

This paper describes three connected mechanisms, one for each pillar. First, the Fair Set Algorithm derives each set from the collectibles in inventory. Its inputs and rules are public, so a verifier can inspect and reproduce the derivation, and the algorithm accepts a set only when it satisfies the published construction predicate (§4). Second, a Merkle root recorded on-chain commits the accepted Renaiss Collectibles lineup before buyers draw from it (§5). Third, ECVRF randomness derived from post-commit chain data selects an index from the collectibles still available (§6). The resulting record can be replayed from public evidence (§7 and §8).

2Model and goals

A fairness claim depends on what each participant can choose and which facts a verifier can recover. This section states those boundaries before describing the protocol.

2.1 · Actors and trust

ActorRoleTrust
PlayerPays and receives a collectible.Checks the commitment and draw evidence.
OperatorHolds inventory and the VRF key.Trusted for custody and fulfillment, not for altering a committed result.
ChainStores the set root and supplies post-commit data.Trusted for consensus, finality, and block production.
VerifierAnyone with a browser and public data.Recomputes the result without trusting the operator's database.

2.2 · Threat model

We assume the operator is hostile and give it every capability short of breaking the cryptography.

The operator can

see outcomes first · run the app & DB · compose set lineups within published constraints · hold and use the VRF secret key

The operator cannot, without detection

predict a future block hash · forge a second proof for one seed · edit a committed lineup without changing its root · serve a different result that still passes public replay

The first capability deserves a note. Because the operator computes each draw on its own server, it sees the resulting collectible before the player does. That does not let it change the collectible: the proof binds the operator to the one outcome the published key produces for the seed, so knowing a result early gives it no way to alter it.

2.3 · Security goals

GoalStatement
G1 · Constrained setEvery published set passes the EV and tier-count predicate.
G2 · Committed lineupThe on-chain Merkle root detects any later lineup change.
G3 · Deterministic drawOne valid VRF output maps to one remaining collectible.
G4 · Verifiable recordPublic evidence reproduces the collectible without database trust.

3Protocol overview

3.1 · The three pillars

The protocol separates the construction of a valid set, the seal that fixes its lineup before sale, and the draw of a collectible. Each pillar leaves evidence for the next.

Pillar I · Construction

The deterministic algorithm proposes a lineup, then the acceptance predicate checks its EV and per-tier counts.

Pillar II · Seal

A set drawn from Renaiss Collectible inventory is sealed on-chain with a Merkle root before sale.

Pillar III · Draw

After payment, chain data and ECVRF produce β, and keccak256(β) modulo the remaining-collectible count selects the exact collectible.

When a buyer pays, the contract fixes the pack and checkout identifiers. A finalized block supplies the remaining seed input. The VRF proof and ordered draw history then reproduce the selected collectible, while the on-chain root confirms that the collectible came from the committed set.

3.2 · The commitment timeline

For each draw, operator-controlled inputs are public before the relevant entropy exists. The finalized block hash becomes available only after payment. The order below is part of the protocol, not an operational convention.

1

Before any ripVRF key · algorithm

We publish the VRF public key and open-source the Fair Set Algorithm.

Establishes the key used to check later proofs and the rules used to build sets.

2

Set goes liveMerkle root

The lineup is built and its Merkle root is recorded on-chain.

Any later lineup change produces a different root (§5.4).

3

You commit fundspackId · checkoutId

You fund the rip; the contract mints your packId and checkoutId.

Two of the three seed inputs are now fixed on-chain. The third still does not exist.

4

Block finalizesblockHash

Consensus produces the block carrying your purchase.

The seed's entropy is set here, after your funds commit, and nobody could predict it a moment earlier.

5

The drawβ · π

ECVRF maps the seed to randomness and an 80-byte proof; your collectible is assigned and recorded.

For a fixed seed and key, ECVRF has one verifiable output (§6).

6

After settlementreplay

A verifier re-derives the collectible from public data and the published key.

Verification does not require the private key or operator database (§8).

The lineup commitment precedes sale. The block hash used for the draw appears after payment. Public verification checks both sides of that boundary.

Pillar I · Construction

Top tier drops are never a maybe

Sets run back to back, one active at a time. Each must carry a fixed count of top tier collectibles and pass the published rules before it goes live. Fairness is built in rather than promised.

4Fair Set Algorithm

The Fair Set Algorithm derives a set from the candidate inventory, a published configuration, and a VRF-derived random stream. Random choices come from that stream. All other choices follow fixed scoring, balancing, and acceptance rules.

4.1 · Published construction constraints

The configuration defines an expected-value range, a set-size range and a maximum set size, value floors for the tiers, target tier shares, minimum and maximum counts for each tier, and, where configured, a hard cap on the share of the set a tier may hold. These values govern which sets may be published. They are construction constraints, not per-draw odds — the realized lineup fixes the draw probabilities, derived in §6.3.

TierValue floorTarget shareMinimumMaximumShare cap
Tier S≥ $1001%N, where N ≥ 1N
Tier A≥ $904%2510%
Tier B≥ $6020%102030%
Tier C≥ $1075%3760

Illustrative configuration. Target shares guide construction; acceptance is decided by the EV range, the set-size cap, per-tier minimum and maximum counts, and per-tier share caps where configured.

4.2 · Constrained construction

The inputs are the candidate tokens and their values, the configuration above, and the random stream described in §4.4. The algorithm samples without replacement (a token picked for the set leaves the candidate pool), so a token cannot appear twice in one set. Construction treats the published rules in two classes. Hard bounds must always be satisfied. The minimum number of collectibles in a tier and the lower and upper bounds on expected value are two examples; the full list is the acceptance conditions of §4.3. Soft targets guide the search but carry no guarantee. The target expected value and the target share of collectibles in a tier are two examples. The algorithm is also tuned to use the inventory broadly and evenly, scored by the evaluator described in §4.5.

The construction procedure itself is under continuous improvement; every algorithm version is open source and can be checked on this site's verification pages. What a verifier can rely on stays fixed: every random choice comes from the VRF-derived stream, the same inputs reproduce the same set, replay runs the algorithm version and configuration that built the set, and the acceptance predicate in §4.3, not the construction stage, decides what is published.

4.3 · Acceptance predicate

Construction and acceptance are separate. A candidate becomes the published set only when all of the following conditions hold:

Accept(S, C) ⇔ lowerEV ≤ floor(Σ value(collectible) ÷ |S|) ≤ upperEV
  ∧ |S| ≤ maxSetSize
  ∧ for every tier t: minₜ ≤ countₜ(S) ≤ maxₜ
  ∧ for every tier t with a share cap: countₜ(S) ≤ shareₜ · |S|
  ∧ every token id in S is unique

If no candidate passes the predicate within the attempt limit, no set is published from that run. The bounds are not relaxed to force a result.

Every accepted set starts with its configured tier counts. As collectibles are drawn without replacement, the remaining composition changes in a public and reproducible way.

4.4 · Deterministic construction

Build-time randomness is separate from the draw in §6. The build stream derives from the hash and number of a finalized block, the on-chain packId, and the set number under a fixed domain tag. The VRF output expands into a deterministic sequence:

// The domain tag scopes this seed to set generation, so it can't
// collide with hashes from other contexts.

α = keccak256( domainTag ‖ blockHash ‖ blockNumber₃₂ ‖ packId ‖ setId₃₂ )
(β, π) = ECVRF_prove(sk, α)  ·  rᵢ = SHA-512(β ‖ i) → [0, 1)

Given the block reference, packId, set number, proof, configuration, and candidate inventory, a verifier can reconstruct the random stream and the accepted lineup. The Fair Set Algorithm is open-source and each set's inputs are published. Replaying the same inputs follows the same attempts and produces the same accepted set.

4.5 · Implementation agnostic

The protocol pins down three artifacts: the input token data published for each packing run, the algorithm configuration carrying the hard bounds and soft targets of §4.1, and an evaluator function that scores candidate algorithms. An algorithm scores higher when its sets fulfil the soft conditions and use the inventory more broadly and evenly; the exact measures can evolve without touching the hard bounds. Together, the three fix what a construction must consume, what it must respect, and what it should be good at, without fixing how it works.

The construction algorithm itself is therefore replaceable. It can be improved in house, contributed by the community, or sourced through a decentralized process, and none of that changes what a verifier checks: the published inputs, the chain-derived random stream, and the acceptance predicate of §4.3 stay the same.

Browse the sets →

Pillar II · Seal

The lineup can't change after it goes live

Every set comes from one big on-chain inventory of Renaiss collectibles, so every collectible has a fair shot. Before the set goes on sale, its Merkle root is recorded on-chain, and any later change to the lineup breaks the root.

5Inventory and seal

5.1 · Collectible inventory

Renaiss maintains a large Renaiss Collectible inventory. The inventory is itself an on-chain contract that holds every collectible, so the full pool a set can draw from is public rather than a private list on our servers. A set is a finite lineup derived from that inventory for pack draws. Collectible identity and value travel with the set-construction inputs, so the acceptance checks in §4 apply to named tokens, not to an abstract rarity distribution.

5.2 · Composition and selection

Composition

Which collectibles enter the set. The Fair Set Algorithm proposes a lineup under published construction constraints (§4).

Selection

Which remaining collectible a buyer receives. ECVRF randomness selects one index after payment (§6).

These are separate fairness claims. The construction predicate checks the lineup before sale. The draw proof checks each selection after a buyer commits funds.

5.3 · Packing a set

A pack does not offer the whole inventory. Packing selects a set from the inventory contract for a single pack. That choice is not ours to make by hand. It runs a public algorithm that is transparent in its rules, reproducible from its inputs, and open source, so anyone can rebuild the same set from the same public data and check that the lineup was not hand-picked. §4 gives the algorithm in full. Here we trace the four steps that turn the inventory contract into a committed set.

1

Snapshot on-chain ownership

Read every collectible the inventory contract owns at a finalized block. The snapshot is public and fixed to that block height, so anyone reading the chain starts from the same pool.

2

Exclude in-play tokens

Drop tokens that are currently tied up, e.g. sitting in an open set's lineup, locked to a draw awaiting settlement.

3

Run the Fair Set Algorithm

Feed the eligible tokens and the public configuration into the open-source algorithm (§4). Its rules and inputs are published, so the accepted set follows from public data alone.

4

Commit before the set is active

Store the accepted set, hash it into a Merkle root, and record the root on-chain before the set opens for draws.

E_avail = owned(inventory, blockₙ) ∩ eligible(pack) \ inPlay
S = FairSetAlgorithm(E_avail, config)
root = Merkle(S)  →  recorded on-chain before the set is active

5.4 · On-chain Merkle commitment

Before a set becomes available, each collectible in the accepted lineup is hashed into a Merkle tree [3], and the root is recorded on-chain. Adding, removing, or substituting a collectible changes the root. The operator therefore cannot present a different lineup later without producing a mismatch against the on-chain commitment.

leafᵢ = keccak256(abi.encode(tokenIdᵢ, saltᵢ, valueInUsd))   ·   root = Merkle(leaf₀ … leafₙ₋₁)   ·   changed lineup or value ⇒ different root

A 1,024-leaf set has depth 10, so an inclusion proof contains ten sibling hashes, 320 bytes of proof data. Given a collectible's token id, salt, value in USD, and proof path, a verifier can reconstruct the root and compare it with the value on-chain. A successful comparison proves that the collectible and its construction-time value in USD belong to the committed lineup.

A sample set of 32 cards — exactly 5 pairing rounds, the whole tournament on one screen. Your card is Card30; each click plays one real keccak256 round and logs its actual hashes below the tree. Then swap a different token id into the leaf and watch every round derail. Hover or tap any lit cell for the full values. (Real sets commit the same way, just deeper.)

The Merkle root does not choose a collectible. It fixes the set from which the draw is allowed to choose.

5.5 · Public set record

The set record joins the accepted lineup to its on-chain Merkle root. Each later draw references that committed set. A database may index the lineup for fast access, but a verifier checks its contents against the root rather than treating the database as authoritative.

Browse the packing runs →

Pillar III · Draw

The exact collectible, proven end to end

On-chain randomness maps each pull to one of the collectibles left in the set. The proof pins down the exact collectible you receive, not a tier or a range. Replay the draw and you get the same result.

6Verifiable draw

6.1 · Post-commit seed

seed α = keccak256( domainTag ‖ blockHash ‖ packId ‖ checkoutId₃₂ )

The seed hashes three public values under a fixed domain tag: the hash of the block that contains the purchase, the on-chain packId, and the checkout number the settlement contract assigned to the pull. The tag scopes the hash to one meaning (this pack-draw seed formula, version 1), so a hash from another context or from a future revision of the formula cannot collide with it. It serves the same domain-separation role that EIP-712 defines for typed Ethereum data [5]; the seed itself is not EIP-712 encoded. Checkout numbers restart at 1 for each pack, so the seed includes packId as well. This keeps pulls from different packs distinct even when they share a block and checkout number.

None of these inputs are ours to choose. The packId and checkout number are fixed by the contract when the purchase executes. The block hash does not exist at that point; validators produce it when the block finalizes, after funds are committed, and we learn it at the same moment everyone else does. To bias a draw we would have to predict the hash of a block that has not been built, which we cannot do. What remains is the chain-trust assumption of §2.1: a block producer could in principle influence a hash, so the chain, not the operator, is the party trusted for entropy.

t₀ · commit

Funds lock; packId and checkoutId are fixed.

t₁ · block finalized

Hash unknowable at t₀, by anyone.

t₂ · draw proven

The recorded result can be replayed.

6.2 · The ECVRF proof: 80 bytes, deterministic

(β, π) = ECVRF_prove(sk, α) · suite ECVRF-EDWARDS25519-SHA512-ELL2 (0x04) · π = Γ(32) ‖ c(16) ‖ s(32)

The suite and verification procedure follow RFC 9381 [1], an elliptic-curve realization of the verifiable random function primitive introduced by Micali, Rabin, and Vadhan [2]. For one seed and one key there is exactly one valid β. A verifier runs ECVRF_verify(PK, α, π) per RFC 9381 §5.3 and recomputes β from the proof itself (Appendix B).

Uniqueness also settles a question the threat model raises (§2.2). Because we hold the secret key, we compute β on our own server and see the resulting collectible before the player. For the seed and the published key there is only one β we can prove, so seeing the result early gives us no other outcome to substitute. The proof we publish is the one anyone recomputes and checks.

6.3 · Slot mapping · sampling without replacement

index = keccak256(β) mod |E|

|E| is the count of collectibles still available. Draws assign over a shrinking, canonically sorted lineup in checkout order, so collisions can't happen and replay is unambiguous. The modulo bias for |E| ≤ 2¹⁴ against a 256-bit hash is bounded below 2⁻²⁴² (Appendix A).

Because the modulus makes every remaining collectible equally likely at each step, a tier's draw probability is just its share of the pool at that moment — and it shifts after every removal as the pool shrinks:

P(tier t | history h) = remaining collectibles in tier t after h ÷ total collectibles remaining after h
draw 1|E| = 1,024i = 412#40479 removed
draw 2|E| = 1,023i = 77#12083 removed
each removal shifts every later index; history is part of the input

Fig. · Sampling without replacement over a shrinking pool: replaying draw n requires (and so verifies) draws 1 through n−1.

7Verifiable audit trail

Each draw record carries the verification bundle: block hash, checkoutId, β, π, the resolved collectible, and its draw sequence. The on-chain Merkle root fixes the lineup. The purchase data and finalized block determine α; given α and the published key, β is the single value that passes proof verification; and the modulo rule maps that β to one selected collectible. A database entry that conflicts with any of those facts fails independent replay.

The database is an index for these records, not the source of their validity. For that reason, this paper calls the record verifiable rather than describing the whole database as immutable.

Prove a draw →

8Verify your own pull

Sections §4 through §7 exist so that anyone can run this one. Verification is a short sequence of deterministic checks, done in a browser over numbers read from a transaction receipt. The draw logic follows in full. We omit the storage and indexing machinery, which adds nothing to the argument.

8.1 · Checkout order

Every pull gets a checkoutId at payment, a per-pack sequence number the settlement contract assigns as purchase transactions execute. The ordering is therefore fixed by consensus: checkoutIds follow block number, and within a block, the transaction's position in it. Neither we nor the player choose where in the queue a pull lands. Draws consume the set in ascending checkoutId order, so a set's entire draw history is one totally ordered sequence that anyone can reconstruct.

8.2 · One seed, one collectible

Three deterministic functions turn public facts into a collectible; their exact byte encodings are fixed in Appendix C. First, the seed ties the pull to entropy that did not exist when it was paid for:

α = keccak256( tag ‖ blockHash ‖ packId ‖ checkoutId₃₂ )

The block hash is fixed by consensus only after the purchase is included. The packId and checkoutId are fixed at purchase. So before payment, neither party can predict the seed. After payment, neither party can change it. Second, the ECVRF maps the seed to randomness, and for one seed and one key there is exactly one β that any proof can attest to:

(β, π) = ECVRF_prove(sk, α)  ·  β unique per (sk, α)

Third, the randomness picks a slot in the surviving lineup by modulus, and the chosen collectible leaves the pool:

index = keccak256(β) mod |E|  ·  E ← E ∖ {collectible}

No step leaves room for a choice. Given the published key, the set lineup, and the ordered draw history, the collectible at checkoutId n is fully determined.

8.3 · The verification procedure

1

Read the chain

Read the set root, checkoutId, packId, block hash and buyer.

2

Recompute α

keccak256 over the tag and the three on-chain values.

3

Verify π

ECVRF_verify(PK, α, π); recomputed β must equal the record.

4

Derive the index

Replay prior draws; keccak256(β) mod |E|.

5

Check the collectible

The collectible must match the derived index and prove inclusion under the on-chain root.

Step 4 matters more than it appears. Because sampling is without replacement (§6.3), the verifier replays every earlier draw in the set, checking each proof, before deriving its own index. A single dishonest draw anywhere in a set's history breaks the replay of every draw after it. The procedure uses no secret and no database, and it does not depend on trusting our software. It is one pure function over public inputs (Appendix E), and it runs as the interactive verifier on this site.

Try the verifier →

9Security analysis

Each row below is a defense with a failure mode you can reproduce. Swap the outcome and the proof stops verifying. Edit the lineup and the root changes. Alter the recorded collectible and replay reaches a different result. You can watch the honest path resolve, one step at a time, in the interactive verifier.

AttackDefenseResult
Grind for a good seedThe seed binds a block hash that doesn't exist at commit time (§6.1).prevented
Swap the outcomeA fixed seed and public key admit one verifiable β. A substituted output fails proof verification (§6.2).detected
Thin the set after publishAny lineup edit changes the Merkle root that every draw references (§5.4).detected
Rewrite historyIndependent replay detects a mismatch. Database constraints also reject prohibited changes (§7).detected
Abort a bad outcomeEvery paid checkout is numbered on-chain, draws resolve in strict checkout order, and no re-roll path exists. A withheld draw stalls the sequence and leaves a permanent gap against the published record once the set closes.detected

10Limitations

10.1 · Randomness beacon

The seed's entropy is the hash of a BSC block. At the moment funds commit, that hash does not exist, so no party can predict it. The residual is that the validator who builds the block carrying a purchase has some influence over its own block's hash [4], and can choose whether to include the transaction, which gives a block producer a bounded number of tries at the seed. We do not run BSC validators, and each attempt costs a full block, so the influence is marginal, but it is not zero. For that reason the chain, not the operator, is the party we trust for entropy.

10.2 · Permissionless entry

Today the operator submits the on-chain funding transaction, so it decides who may enter. Because only the operator's key produces a valid proof, it also decides whether a paid draw is resolved. Neither power lets the operator change an outcome: a recorded draw cannot be altered or forged, and every paid checkout is numbered on-chain at purchase, so a checkout whose draw never enters the published record leaves a permanent gap that anyone can measure against the chain. What is missing is prevention rather than detection. We keep looking for ways to close that gap and are considering permissionless submission, where anyone could send the funding transaction without the operator in the loop.

10.3 · Activation cadence

A set is built from a block chosen when the build runs (§4.4), so discretion over when to build is discretion over the build seed. Today that timing is operational rather than mechanical. A rule that activates sets on a fixed cadence, for example every N blocks or every fixed time interval, removes the operator's choice of build block, so activation timing carries no signal and cannot be used to search for a favorable composition.

10.4 · Chain reorgs

A draw references a block hash. That hash always comes from a block that BSC's fast-finality mechanism has marked final, one that two thirds of the validator set has voted irreversible, so a reorganization cannot replace it. Reverting a finalized block would take at least a third of the validator set breaking the voting rules [6], and BSC slashes each convicted validator 200 BNB of self-delegated stake, ejects it from the set, and jails it for 30 days; double-signing carries the same fine and jail term [7]. If finality stalls, resolution waits; it never falls back to an unfinalized block. A failure of finality itself would be a chain-level event outside the scope of this system. Even then, recorded draws are immutable and cannot be silently replaced; recovery requires a separate, visible remediation path rather than a second result for the same draw.

11Conclusion

Renaiss Gacha separates fairness into three checkable pillars. The Fair Set Algorithm admits a lineup only when it satisfies the published EV and tier-count constraints. An on-chain Merkle root commits the accepted set, drawn from Renaiss Collectible inventory, before sale. After payment, post-commit chain data and ECVRF determine the exact collectible among those remaining. Together, the commitment, construction transcript, and draw proof let a verifier reproduce the result without treating a database entry as authoritative.

A-EAppendices

A · Modulo-bias bound

For |E| ≤ 2¹⁴ and a 256-bit hash, the per-slot bias is bounded below 2⁻²⁴².

B · ECVRF verification math

Recompute U = sB − cY and V = sH − cΓ; accept iff c equals the first 16 bytes of SHA-512(suite ‖ 0x02 ‖ Y ‖ H ‖ Γ ‖ U ‖ V ‖ 0x00), then β = SHA-512(suite ‖ 0x03 ‖ 8Γ ‖ 0x00). RFC 9381 §5.3, §5.4.3, §5.2.

C · Canonical byte encodings

Exact concatenation order, endianness, and hex normalization for seed, leaf, and proof. One encoding, one hash.

D · Draw-record schema

Column-level definition of the draw row, constrained fields, and permitted lifecycle transitions.

E · Reference verifier

The complete pure-function verifier, as shipped on this site's interactive pages.

References

  1. Goldberg, Reyzin, Papadopoulos, Včelák. Verifiable Random Functions (VRFs). RFC 9381, IETF, 2023.
  2. Micali, Rabin, Vadhan. Verifiable Random Functions. FOCS, 1999.
  3. Merkle. A Digital Signature Based on a Conventional Encryption Function. CRYPTO, 1987.
  4. Ethereum. EIP-712: Typed structured data hashing and signing. 2018.
  5. BNB Chain. BEP-126: Introduce Fast Finality Mechanism. github.com/bnb-chain/BEPs, 2021.
  6. BNB Chain. BSC Slash Rules. BNB Chain Documentation.