STRAT Staking
Stake STRAT to earn esETH yield — with 7-day reward streaming that prevents frontrunning and rewards long-term holders.
The Problem
Staking in DeFi has a well-known vulnerability: frontrunners can monitor the mempool for incoming reward distributions, stake just before the rewards land, claim their share, and immediately unstake. The honest staker who held for weeks gets diluted by someone who held for seconds.
This isn't a theoretical problem — it's endemic to simple reward-distribution designs like vanilla MasterChef contracts. It distorts incentives, punishes conviction, and rewards MEV extraction.
ETH Strategy solves this with a hybrid staking mechanism that streams rewards over 7 days rather than distributing them instantly.
Unlike protocols that pay staking rewards from inflationary token emissions, STRAT staking yield comes entirely from real protocol revenue — not dilutive emissions. Today, that revenue comes from ESPN fee share (distributed via merkle). Once Treasury Lending launches (Q2 2026), lending interest will become the primary revenue stream, flowing directly to StakedStrat as esETH. More protocol activity means more yield. sSTRAT-v2 is a direct claim on the protocol's economic output.
How It Works
Deposit STRAT into the StakedStrat contract and receive sSTRAT-v2, a non-transferable receipt token that tracks your staked balance. Your stake earns esETH yield proportional to how much you've staked and how long you've been staking.
The core flow:
Stake — Approve STRAT spending to the contract, then transfer STRAT. You receive sSTRAT-v2 1:1 with your deposit (sSTRAT-v2 is minted to you).
Earn — As protocol revenue flows into the contract as esETH, it streams to stakers over a 7-day period, proportional to each staker's share of the total pool.
Claim — Claim accrued esETH rewards at any time without changing your staked position.
Unstake — Withdraw STRAT at any time. No lock period. Pending rewards are automatically claimed before the stake is reduced, so nothing is forfeited. Your sSTRAT-v2 is burned proportionally.
7-Day Reward Streaming
This is the key mechanism. Rather than distributing rewards the moment they arrive, the contract streams them linearly over a 7-day window.
Why It Matters
The 7-day stream is a security and fairness feature, not just a mechanic:
Anti-frontrunning: An attacker who stakes just before a large reward deposit and exits immediately captures nothing. They must hold for the full streaming period to earn their proportional share — tying up capital for marginal gain.
Fair distribution: Earlier stakers always retain their share of yield accrued up to that point. New stakers begin earning only from the moment they join.
Anti-griefing: Dust deposits barely perturb an ongoing reward stream. If someone sends 0.001 esETH while a large stream is active, the stream duration and rate barely change.
How Streaming Works
When esETH reward tokens arrive at the contract, calling syncRewards() detects the new balance and starts (or extends) the stream:
New rewards detected — The contract compares its current balance against cumulative accounting:
newRewards = (currentBalance + totalClaimed) - totalNotifiedRewards. Any positive difference is new rewards that haven't been streamed yet.Blending with active streams — If a reward stream is already active, the new rewards are blended with the remaining undistributed tokens using a value-weighted average duration:
When
remaining >> newRewards:newDuration ≈ remainingTime(dust attacks barely perturb the ongoing stream)When
newRewards >> remaining:newDuration ≈ REWARD_DURATION(fresh batch gets the full 7-day window)
Linear drip — Rewards are distributed to stakers per second based on their share of the total staked pool. Internally, a cumulative
rewardsPerShareaccumulator tracks yield per staked token, while each user'srewardDebtrecords their baseline — ensuring earlier stakers retain accrued yield and new stakers only earn from the point they join.
syncRewards() is permissionless and is called automatically during stake, unstake, claim, and migration operations. Anyone can also call it directly.
Worked Example
Alice has staked 1,000 STRAT and is the only staker. 10 esETH arrives as rewards.
Day 0:
syncRewards()detects 10 esETH. A 7-day stream begins at ~1.43 esETH/day.Day 3: Alice has accrued ~4.29 esETH. She claims it.
Day 3: Bob stakes 1,000 STRAT. He starts earning from this moment — he gets none of Alice's already-accrued rewards.
Day 7: The remaining ~5.71 esETH has been split 50/50 between Alice and Bob (equal stake). Alice earned ~7.14 esETH total, Bob earned ~2.86 esETH.
If Bob had tried to frontrun by staking at Day 6.9 and unstaking at Day 7, he'd capture only ~0.07 esETH (0.1 day of streaming × 50% pool share × ~1.43 esETH/day) while locking 1,000 STRAT. The economics of the attack don't work.
Revenue Sources
StakedStrat is a passive revenue receiver — esETH is simply transferred to the contract address, and syncRewards() detects the new balance and starts streaming it to stakers. This means any protocol component can direct revenue to stakers by sending esETH to the contract.
The planned revenue sources for StakedStrat:
Protocol fee share from ESPN operations
Live (via merkle)
ESPN yield accrues to STRAT stakers; currently distributed via merkle, will flow directly to StakedStrat on-chain once deployed
Treasury Lending interest payments
Roadmap — Q2 2026
Interest paid by borrowers flows to StakedStrat as esETH; expected to be the primary revenue source once live
All protocol revenue is directed to a single staking contract — making STRAT staking yield a transparent, on-chain reflection of total protocol activity.
Stake Migration
Need to rotate wallets? The migrateStake() function lets you move some or all of your staked position to a new address without unstaking:
Migrated rewards are proportional to the migrated stake amount
Any pending rewards for the recipient are paid out to the recipient during migration
If you pass
amount = 0, the full stake is migratedYour remaining (non-migrated) pending rewards stay claimable at your original address
Destination address must be non-zero, cannot be the caller, and cannot be the contract itself
This means you can change custody without losing your position in the reward stream.
sSTRAT-v2 Token Properties
sSTRAT-v2 is the receipt token you get when you stake. It is explicitly non-transferable:
Name
Staked STRAT v2
Symbol
sSTRAT-v2
Standard
ERC-20 (with transfers disabled)
Transferable
No — transfer, transferFrom, and approve all revert with TransferDisabled
Migration
Via migrateStake() only (performs an internal transfer)
sSTRAT-v2 is an accounting receipt, not a tradable asset. Your sSTRAT-v2 balance always equals your staked STRAT amount. It exists so that integrators and wallets can display staked balances via standard ERC-20 interfaces, but it cannot be traded, pooled, or used as collateral externally.
Status: Upcoming Release — STRAT staking is currently live via merkle-based reward distribution. The on-chain StakedStrat contract with 7-day reward streaming will launch as part of the upcoming release, replacing the merkle distribution.
Failure Modes and Gotchas
Reentrancy protection. All state-changing functions (stake, unstake, claim, migrateStake) are guarded by nonReentrant. Reward token transfers cannot be exploited to re-enter the contract and corrupt accounting.
Input validation. Staking or unstaking zero reverts with ZeroAmount. Unstaking or migrating more than your balance reverts with InsufficientStake. Attempting transfer, transferFrom, or approve on sSTRAT-v2 reverts with TransferDisabled.
No lock period — but frontrunning doesn't work. You can unstake at any time, but the 7-day streaming design means short-duration staking captures negligible rewards. The system is designed to be permissionless without being exploitable.
Unstake auto-claims rewards. When you unstake, pending rewards are automatically claimed and sent to you. There is no scenario where unstaking causes you to forfeit earned yield. This is an explicit design choice — some staking contracts silently forfeit unclaimed rewards on unstake.
getPendingRewards() may undercount. The view function projects the current reward stream forward but does not account for newly arrived reward tokens that haven't been synced yet. If rewards were just sent to the contract, call syncRewards() first for an accurate reading.
Seed stake requirement. The contract assumes totalStaked > 0 whenever rewards are flowing. If totalStaked reaches zero while esETH is streaming, those rewards remain in the contract but cannot be fairly distributed to future stakers. To prevent this, a small protocol-controlled seed stake (from a protocol-owned address) is deposited at deployment and never fully withdrawn. This is a deployment-level invariant maintained by the protocol team.
Rewards require syncRewards() to begin streaming. esETH sent to the contract doesn't distribute automatically — the syncRewards() function must be called to detect new tokens and start the stream. This happens automatically during stake/unstake/claim operations, but if no user actions occur for an extended period, accumulated rewards won't begin streaming until someone interacts with the contract.
sSTRAT-v2 is non-transferable. You cannot sell, transfer, or use sSTRAT-v2 as collateral in external protocols. The only way to move your staked position is via migrateStake(). This is by design — it prevents secondary markets from forming around staked positions and keeps the reward accounting clean.
Migration pays out recipient's pending rewards. When you migrate stake to an address that already has a staked position, that address's pending rewards are claimed and sent to them as part of the migration transaction. This prevents accounting corruption but means the recipient will receive an unexpected reward payout.
For a comprehensive view of protocol risks and mitigations, see Risks.
Last updated