Staking: asset vs LP

Staking happens through the stPopulx contract (ST-PPLX tracks positions). The stake(uint256 amount, bool asset, bool locked) function distinguishes two deposit types.

Asset staking (PPLX)

LP staking

Zap and LP

The Zap contract credits LP staking through zapSTPPLX (Zap-only caller), not the regular asset stake path.

Daily reward flow (oracle → cron → user)

Rewards are not minted by the contract on each block. They are distributed once per day by an off-chain cron, then made claimable on-chain. Three actors are involved:

  1. Cron (off-chain). Every 24 h, a backend job:
    • reads two daily reward pools from the backend (one for asset stakers, one for LP stakers, both expressed in PPLX/day);
    • fetches every active position via stPopulx.getStakersDetails();
    • applies a 1.5× weighting to each position whose assetLocked or lpLocked flag is true (the +50% locked bonus);
    • splits each pool prorata against the weighted staked supply and writes the per-wallet shares to the backend;
    • records the run so a re-run for the same UTC day is a no-op (idempotence).
  2. Oracle (on-chain bridge). The same backend then calls stPopulx.vestingReward(staker, amount) for each staker and amount it computed. This is the only reward-creation path on-chain and it is gated by onlyOracle: nobody else can mint reward credits.
  3. You (on-chain claim). From the dapp you call claimReward(uint256 key) or compoundReward(uint256 key) directly on stPopulx. These functions are not onlyOracle — the oracle credits the vesting entry, you redeem it yourself when you want to. Each entry vests linearly over vestingTime (default 7 days); claiming early applies a per-day decaying penalty defined on the staking contract.

The PPLX paid out by claimReward / compoundReward is sourced from VaultPopulx. If the vault is dry, the main token contract mints the missing amount on the fly via swapChildPopulxToPopulx — see the Token page for the dilution mechanics and how the burn-tax era is meant to absorb it.

APY matrix

Four APY tiers are exposed at POST /getAPY and surfaced on the staking dashboard. They are display-only figures: the cron always distributes the configured daily pools in full, no matter how many wallets are staking.

TierFieldFormula (display)For
Asset, non-lockedapy_asset(asset pool / 90 M) × 365 × 100Citizens with default stPPLX
Asset, lockedapy_asset_lockedapy_asset × 1.5Citizens with opt-in 12-month lock
LP, non-lockedapy_lp(LP pool / 90 M) × 365 × 100LP stakers without lock
LP, lockedapy_lp_lockedapy_lp × 1.5Founders, Zap users, opt-in LP lockers

Why 90 000 000?

The denominator is a fixed display baseline of 90 000 000 PPLX. It mirrors the 90% of total supply minted into VaultPopulx at deploy — i.e. the maximum capital that can ever be staked in PPLX before the contract starts minting from swapChildPopulxToPopulx. We use it as a single, stable baseline so the headline APY does not yo-yo every time someone stakes or unstakes.

It is purely a display normalization knob. The cron does not use it: it always distributes the full daily pool prorata against the actual on-chain weighted stake. As a consequence:

Locked bonus (+50%)

The 1.5× multiplier is enforced exclusively by the off-chain cron, not by the contract: a locked position receives 50% more weight when the daily pool is divided among stakers. The contract itself only enforces the 12-month withdrawal lock; it never moves any tokens because of the locked flag. This means:

Reward vesting (in-contract)

Each call to vestingReward appends a per-user entry indexed by key. Reference duration vestingTime defaults to 7 days. Calling claimReward(key) before full vesting applies a per-day decaying penalty; compoundReward(key) rolls the entry back into your stake without penalty. Exact formulas are visible in the verified staking contract on Etherscan.

What can change without a re-deploy

Anything that affects past distributions (already credited on-chain via vestingReward) is immutable.

Disclaimer. Minimums, pair address, vault, tax rates, daily reward pools and APY baseline are whatever the production contract / API uses — verify on-chain and on the live dashboard.