Skip to content

Elysium testnet. Tokens have no value.

DanakeDanake
Protocol

Stay clause

The Stay clause is an optional rule of a Fare: your stream continues only while your wallet still holds at least what it has already claimed.

What it checks#

The check is a single comparison, done on the payout token:

payoutToken.balanceOf(wallet) >= claimed

claimed is the total you have claimed from this Fare so far. The check is skipped until your first claim, because before that claimed is zero.

When a stream is forfeited#

  • On your own claim. If the Fare has the Stay clause, you have already claimed something, and your balance of the payout token is below what you claimed, claim() does not pay. It marks your stream as forfeited and adds what was left of it to the payer's surplus.
  • By anyone. enforceStay(fareId, wallet) runs the same check for any wallet. It reverts with StayHeld if the wallet still holds enough, and forfeits the stream otherwise. Anyone can call it, so a payer can enforce the clause without waiting for the holder to claim.

A forfeited stream cannot be claimed again. What was already claimed stays with the wallet. The forfeited amount is payout − claimed, and the payer recovers it with withdrawSurplus().

Why a payer uses it#

A payer opening a Fare wants holders, not sellers. Stay keeps paying wallets that keep what they are given, and returns the rest of the budget when a wallet sells.

Known limits#

  • Balance, not history. The clause checks a balance at the moment of the check. A wallet can sell, then buy back before anyone checks, and keep its stream.
  • Any source counts. Tokens bought on a market or received from another wallet count toward the balance. The clause does not know where the tokens came from.
  • Moving to another wallet breaks it. Sending the payout to your own second wallet looks like selling.
  • No check until the first claim. A wallet that never claims cannot break the clause; it can still claim everything at the end of vesting, then sell.
  • Checked on demand. Nothing runs automatically. A broken clause takes effect at the next claim() or enforceStay().

The app shows when a stream would be forfeited on the next claim (stayBroken), so a holder sees it before acting.