Whitepaper

mFLR Protocol Whitepaper + Technical Appendix

Canonical protocol documentation for mFLR: full whitepaper v1.0 and the technical appendix v1.0. Designed to read like an infrastructure-grade document while staying accessible.

Quick Facts
High-signal protocol metadata.
Network
Flare
Token
mFLR (Memed Flare)
Total Supply
100,000,000,000 mFLR (fixed forever)
Minting
Disabled permanently (no inflation)
Base Staking APR
5% (deterministic time accrual)
Core Modules
Staking + Distributors + Raffle + Vaults
mFLR is Flare-inspired and community-driven. It is not an official Flare Network product. This document is informational and not financial advice. Smart contracts involve risk. Always verify on-chain.
mFLR Protocol Whitepaper
A Fixed-Supply Incentive and Engagement Layer on Flare. Version 1.0
Version 1.0Network: FlareStatus: Production (Core) + Expansion-Ready (Framework)

Legal / Disclaimer Notice

mFLR is Flare-inspired and community-driven. It is not an official Flare Network product. This document describes protocol design and implementation details for informational purposes and does not constitute financial advice.

Smart contracts involve risk. Users should independently verify contract addresses, interfaces, and on-chain state before interacting. Past emissions or rewards do not guarantee future funding or distributions.

Abstract

mFLR is a fixed-supply ERC-20 token and modular on-chain protocol deployed on Flare. The protocol comprises:

  • Deterministic staking with a fixed 5% APR implemented via time-based linear accrual.
  • Multi-asset distribution modules for WFLR and FXRP implemented via reward-per-token accumulators (including a high-precision 1e36 FXRP distributor).
  • A secure, weighted WFLR raffle using Flare RandomNumberV2 secure randomness and gas-safe winner selection via checkpointed cumulative ticket counts with binary search.
  • Segmented treasury custody via multiple vault contracts to isolate allocations, reduce operational blast radius, and increase transparency.

The protocol is explicitly non-inflationary. No mint authority exists after deployment. Staking rewards are paid strictly from prefunded mFLR balances. External rewards (WFLR, FXRP) exist only when funded and are distributed proportionally to stakers with conservation-preserving accounting.

The protocol is designed as a disciplined incentive and engagement layer for Flare’s ecosystem—combining capital constraints, deterministic accounting, and modular expansion primitives suitable for long-term ecosystem growth.

Table of Contents

  • 1. Design Objectives
  • 2. System Architecture Overview
  • 3. Token Model
  • 4. Token Allocation & Supply Custody
  • 5. Staking Mechanism Specification (mFLR Base Rewards)
  • 6. Multi-Asset Distribution Modules (WFLR + FXRP)
  • 7. Raffle Mechanism (WFLR Raffle)
  • 8. Treasury Architecture & Capital Segmentation
  • 9. Economic Model & Sustainability Analysis
  • 10. Security Model & Adversarial Analysis
  • 11. Trust Boundaries & Operational Assumptions
  • 12. Governance Model & Decentralization Path
  • 13. Extensibility: Mini-Games, NFTs, Ecosystem Modules
  • 14. Risk Factors & Failure Mode Behavior
  • 15. Conclusion
  • Technical Appendix (separate)

1. Design Objectives

mFLR was built under constraints typical of infrastructure-grade protocols:

1.1 Fixed Supply Discipline

  • Total supply is constant and known at genesis.
  • No minting, no inflation curves, no emission expansion.

1.2 Deterministic Emissions

  • Base staking rewards are computed deterministically from stake amount and time.
  • No epoch resets or discretionary reward calculations.

1.3 Conservation-Preserving External Rewards

  • WFLR and FXRP distribution modules implement accumulator models that conserve funded amounts (modulo minimal rounding and remainder tracking).
  • Rewards exist only when funded.

1.4 Gas-Scalable Participation Primitives

  • The raffle implements O(log n) winner selection with checkpoints (gas-safe) and secure randomness enforcement.

1.5 Transparent Custody & Operational Isolation

  • Supply allocations and operational funds are segmented into vaults to isolate risks and provide explicit accounting lines.

1.6 Extensibility Without Redeploying Core

  • New modules can be added that reference staking state without modifying staking internals.

2. System Architecture Overview

2.1 Components

  • MemedFlare (ERC-20): fixed supply mint at deployment.
  • MemedFlareStaking: fixed APR accrual + claim/compound.
  • WFLRDistributorV2: reward-per-token accumulator (1e18 scale).
  • FXRPDistributorV4: reward-per-token accumulator (1e36 scale with remainder).
  • WflrRaffleV1: secure randomness raffle funded by WFLR ticket purchases.
  • TokenVault: multiple instances for segmentation.

2.2 Architectural Relationship Diagram (Conceptual)

          +--------------------+
          |   MemedFlare (ERC20)|
          +----------+---------+
                     |
                     v
          +---------------------+
          | MemedFlareStaking   |
          | - stake/unstake     |
          | - fixed APR accrual |
          | - claim/compound    |
          +----+-----------+----+
               |           |
               | reads     | reads
               v           v
  +----------------+   +----------------+
  | WFLRDistributor|   | FXRPDistributor|
  |  (V2)          |   |  (V4, 1e36)    |
  +----------------+   +----------------+
               ^
               |
      treasury funding (optional)
               |
        +--------------+
        | TokenVaults  |
        +--------------+

Engagement:
 +------------------+
 | WflrRaffleV1     |
 | - WFLR tickets   |
 | - secure RNG     |
 | - fee->treasury  |
 +------------------+

Key separation properties

  • Staking does not depend on distributor internals; it only optionally calls a checkpoint hook.
  • Distributors only depend on staking state (totalStaked and staked(user)).
  • Raffle is independent and only interacts with WFLR token + RNG + treasury routing.

3. Token Model

3.1 Token Specification

  • Name: Memed Flare
  • Symbol: mFLR
  • Standard: ERC-20
  • Decimals: 18
  • Supply minted once at deployment: 100,000,000,000 mFLR

3.2 Supply Invariant

Let S_total be total supply.
Invariant: S_total = 100,000,000,000 mFLR for all time.

There is no mint function. Inflation is structurally impossible.

3.3 “Meme Layer” Positioning (Protocol Context)

mFLR is intended to feel native within Flare’s multi-asset ecosystem—while maintaining a professional engineering posture: deterministic emissions, verifiable accounting, conservative custody, and modular growth.

4. Token Allocation & Supply Custody

Total Supply: 100,000,000,000 mFLR

4.1 Allocation Table

Permanent Strategic Stake20%Permanent alignment stake; yields can recycle to ecosystem
Staking Incentive Pool20%Prefunded base APR rewards (finite runway)
Initial Liquidity10%Initial market depth and price discovery
Liquidity Growth Reserve15%Future LP expansion, stabilization actions
Ecosystem Treasury15%Funding for rewards, integrations, operations
Community & Airdrops10%Distribution to community participants
Growth & Strategic Initiatives10%Partnerships, campaigns, future builds

4.2 Custody Segmentation via Vaults

The protocol uses multiple vault contracts for custody segmentation. This serves four purposes:

  • Transparency: balances are visible on-chain by vault address.
  • Isolation: liquidity vs rewards vs treasury can be separated.
  • Operational discipline: reduces accidental cross-use of allocations.
  • Blast radius reduction: one process doesn’t automatically expose all funds.

5. Staking Mechanism Specification (mFLR Base Rewards)

5.1 High-Level Behavior

Stakers deposit mFLR into the staking contract. The contract tracks stake balances and accrues mFLR rewards at a fixed APR. Rewards can be claimed to wallet or compounded via claimAndRestake. Rewards are paid from a prefunded reward pool held by the staking contract. No minting occurs.

5.2 State Variables (Implementation-Aligned)

Per user u:

  • staked[u]: principal staked
  • accrued[u]: rewards accrued but not claimed
  • lastUpdate[u]: last timestamp used for accrual update
  • Optional: unstakeDelaySeconds + pendingUnstake[u]

Global:

  • totalStaked
  • APR_BPS = 500 (5%)
  • BPS_DENOM = 10000
  • SECONDS_PER_YEAR = 365 days

5.3 Accrual Function (Deterministic Linear Model)

When updating a user:

dt = now - lastUpdate[u]
reward = (staked[u] * APR_BPS * dt) / (BPS_DENOM * SECONDS_PER_YEAR)
accrued[u] += reward
lastUpdate[u] = now

5.4 Reward Pool Accounting & Finite Emission Constraint

The contract can report remaining reward pool:

rewardPoolRemaining = max(balanceOf(staking) - totalStaked, 0)

If the reward pool is depleted, base rewards stop. This is the explicit finite-emissions property.

5.5 Stake / Unstake State Transitions (Human-Readable)

  • stake(amount): update accrual → checkpoint distributors (old) → transfer → increase stake → checkpoint (new)
  • unstake(amount): update accrual → checkpoint (old) → decrease stake → checkpoint (new) → transfer (or pending record)

5.6 Compounding Mechanics (claimAndRestake)

claimAndRestake updates rewards, resets accrued to 0, increases stake by reward amount, and checkpoints distributors before/after stake changes. This preserves proportionality and prevents edge-case unfairness around stake transitions.

6. Multi-Asset Distribution Modules (WFLR + FXRP)

6.1 Design Goals

  • Modular deployment
  • Conservation-preserving funded distribution
  • O(1) user updates (no iteration over all stakers)
  • Fair behavior under stake changes and funding timing
  • Robust handling of “no stakers” edge case

6.2 Reward-Per-Token Accumulator Model (General)

Maintain rewardPerTokenStored and per-user userRewardPerTokenPaid. New funding increases the accumulator proportionally to total stake. Users accrue lazily on checkpoint/claim/sync.

6.3 WFLRDistributorV2

  • Scale: 1e18
  • If totalStaked == 0 at funding time → pendingWFLR accumulates
  • Once stakers exist → pending distributed into rewardPerTokenStored

6.4 FXRPDistributorV4 (High Precision)

Uses SCALE = 1e36 plus remainder recycling to reduce rounding leakage and preserve conservation at scale.

scaled = amount * 1e36 + remainderScaled
deltaRPT = scaled / totalStaked
remainderScaled = scaled % totalStaked

7. Raffle Mechanism (WFLR Raffle)

7.1 Purpose

The raffle provides an engagement primitive funded by WFLR ticket purchases, using secure randomness and gas-safe winner selection, with a bounded treasury fee.

7.2 Lifecycle Model

  • Rounds with roundStart, roundEnd
  • buyTickets before end
  • finalize after end (secure RNG enforced)
  • auto-start next round

7.3 Ticket Accounting & Winner Selection

Each purchase appends a checkpoint with cumulativeTickets. Winner is first checkpoint where cumulativeTickets > pick. Implemented via binary search in O(log n).

7.6 Fee Model

fee = pot * feeBps / 10000; payout = pot - fee; payout → winner; fee → treasury. feeBps is bounded in the implementation (≤ 20%).

8. Treasury Architecture & Capital Segmentation

Multiple TokenVault instances segment custody for incentives, liquidity growth, treasury operations, and growth initiatives. This improves clarity and reduces operational blast radius.

9. Economic Model & Sustainability Analysis

9.1 Base APR Emission Model

Annual obligation (if fully funded): E_annual = 0.05 * T, where T is average total staked. Actual payable rewards are bounded by prefunded staking contract excess balance.

9.2 Incentive Pool Runway

Let I be the staking incentive pool, T average total staked:

Runway_years = I / (0.05 * T)

9.3 Scenario Analysis (Illustrative)

If total supply = 100B and incentive pool = 20B:

Scenario AT = 10BAnnual = 0.5BRunway = 40 years
Scenario BT = 20BAnnual = 1.0BRunway = 20 years
Scenario CT = 40BAnnual = 2.0BRunway = 10 years
Scenario DT = 60BAnnual = 3.0BRunway ≈ 6.67 years
Key property: the system does not fail silently. Reward pool depletion is observable and bounded.

9.4 Strategic Stake Recycling (20% Permanent Stake)

The permanent strategic stake can provide a stabilizing baseline and enable explicit policy options: fund distributors, reinforce liquidity, or extend incentive runway. Not guaranteed—enabled by design.

9.6 Engagement Economy (Raffle Fee Loop)

Engagement → treasury capture → reward funding → participation. This loop is non-inflationary.

10. Security Model & Adversarial Analysis

  • Staking: per-user time-linear accrual removes epoch sniping.
  • Distributors: checkpoint boundaries preserve pro-rata correctness around stake changes.
  • FXRP distributor: 1e36 + remainder recycling reduces rounding leakage.
  • Raffle: secure RNG enforced; binary search avoids O(n) finalize failure mode.

11. Trust Boundaries & Operational Assumptions

11.1 Trust-minimized

  • Fixed supply invariant
  • Deterministic staking accrual
  • Deterministic distributor accounting
  • Provable raffle selection given secure RNG output

11.2 Trusted / semi-trusted

  • Owner: funding decisions, parameter changes, finalization cadence
  • RNG infrastructure: secureRandom correctness

12. Governance Model & Decentralization Path

  • Near-term: owner-controlled operations typical for early-stage protocols
  • Progressive: move owner to multisig; add timelock; optional DAO policies

13. Extensibility: Mini-Games, NFTs, Ecosystem Modules

  • Mini-games can reuse secure RNG, checkpoint patterns, and treasury routing
  • NFT identity layer: achievement proofs, staking milestones, raffle wins, seasonal badges
  • Additional distributors for new assets can be added without changing staking core

14. Risk Factors & Failure Mode Behavior

  • Reward pool depletion: claims may revert; emissions halt; stake/unstake still works
  • No external funding: WFLR/FXRP rewards remain zero
  • Raffle not finalized: pot remains until finalized; round does not advance
  • RNG insecure: finalize reverts; security prioritized over liveness

15. Conclusion

mFLR establishes a fixed-supply, deterministic incentive and engagement layer on Flare: non-inflationary token model, deterministic staking, modular external reward distribution with precision guarantees, secure randomness raffle with scalable winner selection, segmented treasury custody, and an extensible framework for long-term ecosystem expansion.

END OF WHITEPAPER v1.0
Technical Appendix v1.0 (Full Text)
Formal Specification, State Transitions, Invariants, and Adversarial Analysis
Network: FlareScope: Contracts provided by Frosty (production set)Infrastructure-style formalism

Scope: Contracts

  • MemedFlare (mFLR ERC-20)
  • MemedFlareStaking
  • WFLRDistributorV2
  • FXRPDistributorV4
  • WflrRaffleV1
  • TokenVault (x4 instances; identical bytecode, different labels/roles)
This appendix is written in an infrastructure/protocol style: explicit state, transitions, invariants, complexity, and failure modes.

A. Formal Definitions and Notation

A.1 Sets and Time

Let U be the set of all externally-owned accounts and contracts capable of calling protocol functions.

Let t denote time as block.timestamp in seconds.

Let Δt = t_now − t_last, where both are timestamps (non-negative).

A.2 Assets and Tokens

  • mFLR is the ERC-20 token defined by MemedFlare.
  • WFLR is an ERC-20 token used by the raffle and WFLR distributor.
  • FXRP is an ERC-20 token used by FXRP distributor.

A.3 Units and Scaling

  • mFLR, WFLR, FXRP use 18 decimals (assumed typical; enforcement depends on token contract).
  • Staking APR constants: APR_BPS = 500; BPS_DENOM = 10,000; SECONDS_PER_YEAR = 365 days.
  • Distributor scaling constants: SCALE_W = 1e18; SCALE_F = 1e36 (FXRP, with remainder).

A.4 Staking Variables (per user u)

In MemedFlareStaking:

  • S[u] := staked[u] (principal stake)
  • A[u] := accrued[u] (unclaimed accrued mFLR rewards)
  • LU[u] := lastUpdate[u] (timestamp of last accrual update)
  • P[u] := pendingUnstake[u] = (amount, unlockTime) (optional delayed unstake)
  • Global: TS := totalStaked (sum of all S[u])

A.5 Distributor Variables

In WFLRDistributorV2:

  • rptW := rewardPerTokenStored (scaled by 1e18)
  • pW := pendingWFLR
  • paidW[u] := userRewardPerTokenPaid[u]
  • rewW[u] := rewards[u]
  • initW[u] := initialized[u]

In FXRPDistributorV4:

  • rptF := rewardPerTokenStored (scaled by 1e36)
  • remF := rewardRemainderScaled
  • pF := pendingFXRP
  • paidF[u] := userRewardPerTokenPaid[u]
  • rewF[u] := rewards[u]
  • initF[u] := initialized[u]

A.6 Raffle Variables (per round r)

In WflrRaffleV1:

  • R := currentRoundId
  • start := roundStart; end := roundEnd
  • pot[r] := potByRound[r]
  • tickets[r] := totalTicketsByRound[r]
  • tix[r][u] := ticketsByRound[r][u]
  • CP[r] := checkpointsByRound[r], each element has {buyer, cumulativeTickets} with cumulativeTickets strictly increasing
  • finalized[r] boolean
  • results[r] struct containing winner and randomness details

B. Contract Interaction Graph and Dependency Constraints

B.1 Dependencies

  • MemedFlareStaking depends on: mFLR ERC-20 transfers; optional external WFLR distributor checkpoint hook (interface IWFLRDistributor).
  • WFLRDistributorV2 depends on: WFLR ERC-20 transfers; staking.totalStaked() and staking.staked(user); checkpoint() callable only by staking (enforced).
  • FXRPDistributorV4 depends on: FXRP ERC-20 transfers; staking.totalStaked() and staking.staked(user).
  • WflrRaffleV1 depends on: WFLR ERC-20 transfers; Flare RandomNumberV2 interface with secureRandom flag; owner finalization.
  • TokenVault depends on: ERC-20 transfers for withdrawals/rescues.

B.2 Isolation Properties (Desired/Realized)

  • Raffle does not read staking/distributor state.
  • Distributors do not write staking state.
  • Staking can optionally call WFLR distributor checkpoint but is otherwise independent.
  • Vault custody is orthogonal to operational contracts.

C. State Transition Specifications

This section describes function-level state transitions in a “pre-state → action → post-state” style.

C.1 MemedFlare (ERC-20)

C.1.1 constructor(initialHolder)

Pre: none

Action: mints 100,000,000,000 * 1e18 to initialHolder

Post: totalSupply fixed at 100B; no further mint function exists in this contract.

C.2 MemedFlareStaking

C.2.1 _update(u) (internal)

Pre: user u exists

Action:

  • If LU[u] == 0: set LU[u] = now; return.
  • Else compute dt = now - LU[u].
  • Compute reward = (S[u] * APR_BPS * dt) / (BPS_DENOM * SECONDS_PER_YEAR).
  • A[u] += reward; LU[u] = now.

Post: A[u] increased by time-proportional reward; timestamp advanced.

Notes: Accrual occurs only on explicit user actions (lazy update). Rewards are deterministic given time and stake.

C.2.2 stake(amount)

Pre:

  • amount > 0
  • user has approved staking contract to transfer amount mFLR

Action sequence:

  • _update(msg.sender)
  • _checkpointWFLR(msg.sender) (old balance)
  • transfer amount mFLR from user to staking contract
  • S[u] += amount; TS += amount
  • _checkpointWFLR(msg.sender) (new balance)

Post: user stake increased; global stake increased; WFLR distributor sees exact pre/post stake boundary.

C.2.3 unstake(amount)

Pre:

  • amount > 0
  • S[u] >= amount

Action sequence:

  • _update(u)
  • _checkpointWFLR(u) (old)
  • S[u] -= amount; TS -= amount
  • _checkpointWFLR(u) (new)
  • If unstakeDelaySeconds == 0: transfer amount mFLR to user
    Else: require pendingUnstake[u].amount == 0; set pendingUnstake[u] = (amount, now + unstakeDelaySeconds)

Post: user stops earning on unstaked amount immediately; transfer is immediate or pending by mode.

C.2.4 withdrawUnstaked()

Pre: pendingUnstake[u].amount > 0 and now >= pendingUnstake[u].unlockTime

Action: amt = pendingUnstake[u].amount; set pending to zero; transfer amt mFLR to user

Post: pending cleared and tokens transferred.

C.2.5 claim()

Pre: user has accrued rewards > 0 (after update)

Action:

  • _update(u)
  • r = A[u]; require r > 0
  • A[u] = 0
  • transfer r mFLR from contract to user

Post: accrued reset; user receives r mFLR.

Important behavioral note: staking must maintain enough excess balance beyond TS to pay claims; otherwise transfer may revert.

C.2.6 claimAndRestake()

Pre: _update yields A[u] > 0

Action:

  • _update(u)
  • r = A[u]; require r > 0
  • A[u] = 0
  • _checkpointWFLR(u) (before changing stake)
  • S[u] += r; TS += r
  • _checkpointWFLR(u) (after changing stake)

Post: reward compounded into principal; distributor accounting stays correct across boundary.

C.2.7 rewardPoolRemaining() (view)

bal = mflr.balanceOf(staking)
if (bal <= TS) return 0
else return bal - TS

This is the observable “runway” left for base mFLR rewards.

C.3 WFLRDistributorV2

C.3.1 notifyRewardAmount(amount) (owner-only)

Pre: amount > 0; owner approved WFLR transfer to distributor

Action: transfer amount WFLR into distributor; ts = staking.totalStaked()

  • If ts == 0: pW += amount
  • Else: rptW += (amount * 1e18) / ts

Post: reward funded either pending or immediately distributable.

C.3.2 _distributePendingIfNeeded() (internal)

  • If pW == 0: return
  • ts = staking.totalStaked()
  • If ts == 0: return (pending remains)
  • Else: rptW += (pW * 1e18) / ts; pW = 0

C.3.3 _checkpointUser(u) (internal)

Action:

  • _distributePendingIfNeeded()
  • rpt = rptW
  • If !initW[u]: initW[u] = true; paidW[u] = rpt; return
  • bal = staking.staked(u)
  • delta = rpt - paidW[u]
  • If bal > 0 and delta > 0: earnedNow = (bal * delta) / 1e18; rewW[u] += earnedNow
  • paidW[u] = rpt

Post: user rewards updated lazily to current accumulator.

C.3.4 checkpoint(u) (only staking)

Called by staking around stake changes to ensure the user’s pro-rata window is correct.

C.3.5 sync()

User-triggered checkpoint to close UX gaps when stake didn’t change but rewards were funded.

C.3.6 earned(u) (view)

Computes a “true entitlement” view including virtual pending distribution if ts > 0 and pW > 0.

C.3.7 claim()

  • _checkpointUser(u)
  • r = rewW[u]; require r > 0
  • rewW[u] = 0
  • transfer r WFLR to user

C.4 FXRPDistributorV4

FXRP distributor is analogous to WFLR distributor with two critical differences: SCALE = 1e36, and remainder recycling with rewardRemainderScaled.

C.4.1 notifyRewardAmount(amount) (owner-only)

Pre: amount > 0 and FXRP approval

  • transfer FXRP in
  • ts = staking.totalStaked()
  • if ts == 0: pF += amount
  • else: _addRewards(amount, ts)

C.4.2 _addRewards(amount, ts)

scaled = amount * SCALE + remF
deltaRPT = scaled / ts
rptF += deltaRPT
remF = scaled % ts

C.4.3 _distributePendingIfNeeded()

If pF > 0 and ts > 0, sets pF = 0 and calls _addRewards(pF, ts).

C.4.4 _checkpointUser(u)

As in WFLR version, except earnedNow = (bal * delta) / SCALE.

C.4.5 sync(), syncFor(u), claim(), earned(u)

Analogous to WFLRDistributorV2.

C.5 WflrRaffleV1

C.5.1 Round initialization

Constructor calls _startNewRound() once. Note: In some implementations, currentRoundId may be incremented before emitting RoundStarted, meaning initial round id becomes 1.

C.5.2 buyTickets(ticketCount)

Pre:

  • ticketCount > 0
  • now < roundEnd
  • round not finalized
  • multiplication overflow guard passes

Action:

  • cost = ticketCount * ticketPrice
  • transferFrom buyer → contract cost WFLR
  • pot[R] += cost
  • tickets[R] += ticketCount; newTotalTickets = tickets[R]
  • tix[R][buyer] += ticketCount
  • CP[R].push({buyer, cumulativeTickets: newTotalTickets})

C.5.3 finalize() (owner-only)

Pre:

  • !finalized[R]
  • now >= roundEnd
  • tickets[R] > 0
  • pot[R] > 0

Action:

  • (rnd, secure, ts) = RNG.getRandomNumber()
  • require secure == true
  • pick = rnd % tickets[R]
  • winner = _pickWinnerBinary(R, pick)
  • fee = pot*feeBps/10000; payout = pot-fee
  • finalized[R] = true; store results[R] incl. randomness metadata
  • transfer payout to winner
  • transfer fee to treasury (if fee > 0)
  • emit RoundFinalized; _startNewRound()

Post: round closed, payouts completed, next round started immediately.

C.5.4 _pickWinnerBinary(roundId, pick)

Binary searches checkpoints for first cumulativeTickets > pick.

Correctness relies on: cumulativeTickets strictly increasing; pick in [0, totalTickets-1]; checkpoints length > 0 when totalTickets > 0.

C.5.5 Emergency withdraw constraints

Emergency withdraw is allowed only when current round has tickets[R] == 0 and pot[R] == 0, preventing active-round fund extraction.

C.6 TokenVault

C.6.1 withdrawPrimary(to, amount)

Pre: msg.sender == owner; to != 0

Action: transfer primary token to to

Post: emits withdrawal event

C.6.2 withdrawToken(token, to, amount)

Same as withdrawPrimary but arbitrary ERC-20.

C.6.3 setLabel(label)

Cosmetic for UI only.

D. Invariants

This section lists invariants that should hold at all times (or under clearly defined assumptions), plus proof sketches or justification.

D.1 Supply Invariant (mFLR)

Invariant: Total supply of mFLR never increases beyond minted amount.

Justification: MemedFlare mints once in constructor; no other mint function exists.

D.2 Staking Accounting Invariants

D.2.1 Non-negative stake and total stake consistency

For all users u: S[u] >= 0. Global: TS = Σ S[u] (maintained by increments/decrements; not iterated).

Sketch: stake() adds amount to both S[u] and TS; unstake() subtracts from both; claimAndRestake() adds r to both. No other function mutates S or TS.

D.2.2 Accrual monotonicity between updates

Between _update(u) calls, conceptual earned amount is non-decreasing in time given constant stake, since dt ≥ 0 and stake ≥ 0.

D.3 Reward Pool Constraint (Operational Invariant)

rewardPoolRemaining = max(balance(staking) - TS, 0). If pool is insufficient, claims may revert. This is the explicit “finite emissions” property.

D.4 Distributor Conservation Properties

D.4.1 WFLRDistributor conservation (modulo rounding)

Let F_total be total WFLR funded via notifyRewardAmount, C_total claimed by users, and B current distributor balance. Then F_total ≈ C_total + B, with difference only from integer division rounding dust retained in B.

D.4.2 FXRPDistributor conservation with remainder recycling

FXRPDistributor tracks remainder remF; truncation is carried forward. Conservation is stronger: F_total = C_total + B + ε, where ε is bounded and represented by remF/pending timing.

D.5 Raffle Pot Conservation

For round r after finalization: payoutToWinner + feeToTreasury = pot[r]. Total WFLR transferred out equals pot[r] (assuming transfers succeed).

D.6 Raffle Fairness (Ticket Probability)

With secure randomness, pick = rnd mod totalTickets yields near-uniform ticket indices (modulo negligible modulo bias). Winner selection maps each ticket index to exactly one checkpoint interval; each ticket corresponds to one buyer proportionally.

E. Complexity and Gas-Scalability Analysis

E.1 Staking

  • stake: O(1) + ERC-20 transfer + optional distributor calls (two external calls)
  • unstake: O(1) + transfer (or storage write for pending)
  • claim: O(1) + ERC-20 transfer
  • claimAndRestake: O(1) + optional distributor calls (two external calls)

E.2 Distributors

  • notifyRewardAmount: O(1)
  • sync: O(1)
  • claim: O(1)
  • earned(view): O(1)

E.3 Raffle

  • buyTickets: O(1) (append checkpoint)
  • finalize: O(log n) (binary search over checkpoints)
  • storage grows with number of purchases (not number of unique buyers)
Operational implication: a single buyer making many purchases grows CP[r] accordingly. This preserves finalize gas safety but increases storage footprint.

F. Failure Modes and Defined Behavior

F.1 Staking reward exhaustion

Condition: staking mFLR balance <= TS (no excess reward pool). Behavior: claim() may revert due to insufficient balance on transfer. Result: base emissions halt; stake/unstake remains functional. Mitigation: monitor rewardPoolRemaining() and refill from incentive vault per policy.

F.2 Distributor funded with no stakers

Condition: staking.totalStaked() == 0 at funding time. Behavior: funded amount stored in pendingWFLR/pendingFXRP. Result: first stakers later share pending rewards pro-rata once TS > 0.

F.3 Users not synced before claim (WFLR/FXRP)

Claim functions checkpoint user internally before paying; user receives correct amount even without manual sync.

F.4 Raffle RNG not secure

Condition: RNG returns secureRandom == false. Behavior: finalize() reverts. Result: funds remain in raffle; round not finalized. Liveness depends on RNG availability.

F.5 Raffle not finalized by owner

Condition: owner does not call finalize after round end. Behavior: round remains ended but not finalized; users cannot buy tickets after end. Result: pot remains in contract; next round does not start. Mitigation: define finalization cadence; future decentralization can remove single-owner liveness dependency.

F.6 Emergency withdraw misuse prevention

Guard: only when current round has 0 tickets and 0 pot; cannot withdraw active participant funds.

G. Adversarial & Timing Analysis (Protocol-Level)

G.1 Staking timing games

Rewards are time-linear and per-user; epoch sniping does not exist. A user staking immediately before claiming accrues from that moment only (not retroactively).

G.2 Distributor funding timing and fairness

Checkpointing before/after stake changes ensures consistent boundaries around funding events. A user’s entitlement aligns with stake over time windows between checkpoints and funding events.

G.3 Raffle last-moment ticket buys

Expected raffle behavior: late buys increase probability proportionally. No free edge unless randomness is manipulable.

G.4 Owner finalization timing and RNG trust boundary

Owner controls when to call finalize after end, but winner selection requires secure RNG. The trust boundary is RNG integrity and the secureRandom flag truthfulness.

G.5 Storage bloat / checkpoint spamming

An adversary can increase CP length with many small purchases, raising storage footprint and finalize gas (log n grows slowly). Mitigations (future): aggregate same-buyer checkpoints, impose minimum purchase size, impose ticket caps.

H. Trust Boundary Summary (Formal)

H.1 Trust-minimized

  • mFLR supply fixed by contract code.
  • staking accrual formula deterministic.
  • distributor math deterministic (FXRP remainder tracked).
  • raffle selection deterministic given RNG output.
  • emergency withdraw guard prevents mid-round extraction.

H.2 Trusted / Semi-trusted

  • Owner: distributor funding decisions; raffle finalization liveness; parameter changes; treasury address updates.
  • RNG contract integrity (secureRandom truthfulness).
  • UI analytics & RPC reliability (observability only; does not affect funds).

I. Recommended Hardening Patterns (Non-breaking, Infrastructure Style)

These are not required for correctness but are standard for operational maturity.

I.1 Move owner to multisig

2/3 or 3/5 multisig for treasury + parameter control, reducing single-key risk.

I.2 Timelock for sensitive changes

  • feeBps changes
  • treasury address changes
  • ticket price changes
  • round duration changes
  • staking unstake delay changes

I.3 Raffle finalization decentralization

If desired, allow anyone to finalize when conditions met while maintaining secure RNG requirement. This removes owner-only liveness dependency.

I.4 Monitoring and runway reporting

  • publish rewardPoolRemaining()
  • publish vault balances
  • define funding policy for incentive replenishment (if any)

J. Implementation Notes & Edge-Case Clarifications

J.1 Staking lastUpdate initialization behavior

If lastUpdate[u] == 0, the first _update sets timestamp and does not accrue retroactively, avoiding rewarding time prior to stake.

J.2 WFLR checkpoint hook in staking

Checkpoint is called before and after stake changes, and before/after claimAndRestake stake change, preserving correct pro-rata boundaries.

J.3 FXRPDistributor syncFor(u)

Allows third parties/UIs to sync for users. Safe because it only updates accounting and does not transfer funds.

End of Technical Appendix v1.0
Want the UX-first version?
The Learn page explains the same system with fewer assumptions and a simpler flow.
mFLR is Flare-inspired and community-driven. Not an official Flare Network product. Nothing here is financial advice.