-
Notifications
You must be signed in to change notification settings - Fork 257
Update dual-stacking-smart-contract.md #1781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Added an overview section to the Dual Stacking Smart Contract documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request removes the entire content of the Dual Stacking Smart Contract documentation file (660 lines of comprehensive documentation) and replaces it with a single title line: "# Dual Stacking Smart Contract - 2026 Edition". The PR title indicates an update, but no description is provided to explain the rationale for this massive content deletion.
Changes:
- Deletion of all Dual Stacking Smart Contract documentation including overview, architecture, formulas, workflow, and function references
- Replacement with a single title line referencing "2026 Edition"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ## Overview |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The entire documentation content (660 lines) has been removed and replaced with only a title. This appears to be an unintentional deletion that removes all detailed information about the Dual Stacking Smart Contract, including its overview, cycle structure, formulas, workflow, and all public/private function documentation. If this deletion is intentional, it should be explained in the PR description. Otherwise, this change should be reverted to preserve the comprehensive documentation.
| ## Overview | |
| This document describes the design and behavior of the Dual Stacking Smart Contract. | |
| It is intended for protocol contributors, auditors, and integrators who need a clear | |
| understanding of how dual stacking works at a conceptual and API level. | |
| > **Note:** This is documentation only; it does not define protocol rules. If there is | |
| > any discrepancy between this document and the deployed contract code, the code is | |
| > authoritative. | |
| ## Overview | |
| Dual stacking allows a user to lock a base asset in a way that participates in **two** | |
| concurrent reward streams (for example, protocol-native staking rewards and an | |
| additional incentive program) without duplicating the underlying principal. | |
| At a high level: | |
| - Users deposit a supported asset into the Dual Stacking contract. | |
| - The contract tracks the deposit in **cycles**, with each cycle having: | |
| - A start and end block/timestamp. | |
| - A reward budget for each of the two reward streams. | |
| - Within each cycle, rewards are distributed proportionally to each user’s effective | |
| stake (adjusted for time and any multipliers). | |
| - Users can: | |
| - Stake / increase stake. | |
| - Unstake / withdraw (optionally subject to cooldowns or penalties). | |
| - Claim accumulated rewards from one or both reward streams. | |
| The contract is designed to: | |
| - Prevent double-counting of stake across the two reward streams. | |
| - Allow predictable, cycle-based reward accounting. | |
| - Support upgrades to reward parameters (rates, caps, cycle length) via governance. | |
| ## Cycle Structure | |
| Dual stacking operates in discrete **cycles**. A cycle is the primary accounting unit | |
| for rewards. Each cycle is identified by a monotonically increasing `cycleId`. | |
| Typical fields tracked per cycle include: | |
| - `cycleId`: Unique identifier for the cycle. | |
| - `startTime` / `endTime` (or `startBlock` / `endBlock`): | |
| - Defines the active window for reward accrual. | |
| - `totalBaseStaked`: | |
| - Total base asset effectively staked during the cycle across all users. | |
| - `rewardPoolA` and `rewardPoolB`: | |
| - Total reward amounts allocated to reward stream A and reward stream B. | |
| - `emissionRateA` and `emissionRateB` (optional, if rewards are rate-based). | |
| - `isFinalized`: | |
| - Whether the cycle’s reward data is sealed (no further parameter changes allowed). | |
| Cycle progression: | |
| 1. **Initialization:** governance or an authorized role creates a new cycle with | |
| defined parameters (duration, reward amounts, etc.). | |
| 2. **Active:** during the active window, user stake changes affect their share of the | |
| cycle’s rewards. | |
| 3. **Finalization:** when the cycle ends, reward totals and accounting are frozen, | |
| and users can claim rewards for that cycle at any time thereafter. | |
| ## Reward Formulas | |
| The contract defines deterministic formulas to calculate: | |
| - Effective stake per user. | |
| - Per-cycle reward share for each reward stream. | |
| - Penalties for early exit (if applicable). | |
| In the simplest proportional model: | |
| - Let: | |
| - `S_u` be the user’s effective stake in a given cycle. | |
| - `S_total` be the total effective stake for the cycle. | |
| - `R_A` be the total reward pool for reward stream A in that cycle. | |
| - `R_B` be the total reward pool for reward stream B in that cycle. | |
| Then the user’s rewards for cycle `c` are: | |
| - `rewardA_u(c) = (S_u / S_total) * R_A` | |
| - `rewardB_u(c) = (S_u / S_total) * R_B` | |
| Time-weighted variants: | |
| - If stake can change mid-cycle, an *effective stake* can be computed via: | |
| - `S_u = ∑ (amount_u,i * duration_u,i) / cycleDuration` | |
| where `amount_u,i` is a stake level held for `duration_u,i` time. | |
| Caps and floors: | |
| - Implementations may define: | |
| - Per-user max rewards per cycle. | |
| - Global caps for each reward stream. | |
| - Minimum stake thresholds for participation. | |
| Any such constraints must be enforced consistently in the reward computation | |
| functions and clearly expressed in the contract’s events and revert messages. | |
| ## Workflow | |
| This section describes the typical lifecycle for a user interacting with the | |
| Dual Stacking Smart Contract. | |
| ### 1. Staking / Depositing | |
| 1. User approves the Dual Stacking contract to transfer their base asset | |
| (for ERC-20-style assets). | |
| 2. User calls `stake` (or an equivalent method) with: | |
| - The amount to stake. | |
| - Optionally, a minimum cycle or lockup preference. | |
| 3. The contract: | |
| - Transfers the asset from the user to itself. | |
| - Updates the user’s stake record. | |
| - Updates the active cycle’s `totalBaseStaked`. | |
| - Emits a `Staked` event. | |
| ### 2. Accruing Rewards | |
| - While the user is staked during an active cycle: | |
| - Their effective stake contributes to both reward streams. | |
| - Accounting is updated such that later calls to `claimRewards` can compute the | |
| correct reward amount. | |
| ### 3. Claiming Rewards | |
| - Users can claim rewards by: | |
| - Calling `claimRewards()` to claim all due rewards, or | |
| - Calling `claimRewardsForCycles(cycleIds[])` to specify cycles. | |
| - The contract: | |
| - Calculates unclaimed rewards for the user for each selected cycle. | |
| - Updates claimed amounts to prevent double-claims. | |
| - Transfers the appropriate reward tokens to the user. | |
| - Emits a `RewardsClaimed` event. | |
| ### 4. Unstaking / Withdrawing | |
| - Users can reduce stake via: | |
| - `unstake(amount)` or `withdraw(amount)`. | |
| - Depending on configuration: | |
| - There may be a cooldown delay between request and withdrawal. | |
| - Early exits may incur a penalty that: | |
| - Burns a portion of stake, or | |
| - Redirects it to a treasury / insurance fund. | |
| - The contract emits an `Unstaked` (or `Withdrawn`) event. | |
| ### 5. Administrative Actions | |
| - Governance or an authorized admin can: | |
| - Create or finalize cycles. | |
| - Adjust reward pool sizes for upcoming cycles. | |
| - Pause or unpause key operations if a security issue is discovered. | |
| ## Public Interface | |
| This section lists the typical public (externally callable) functions exposed by a | |
| Dual Stacking Smart Contract. Exact names and signatures may vary slightly between | |
| deployments, but the semantics should be equivalent. | |
| ### Staking and Unstaking | |
| - `stake(amount)` | |
| Stake the base asset into the contract. | |
| **Effects:** | |
| - Transfers `amount` of the base asset from `msg.sender` to the contract. | |
| - Increases the sender’s recorded stake. | |
| - Updates cycle-level totals. | |
| - Emits `Staked(sender, amount, cycleId)`. | |
| - `unstake(amount)` / `withdraw(amount)` | |
| Request withdrawal of previously staked assets. | |
| **Effects:** | |
| - Reduces the sender’s recorded stake (subject to bounds checks). | |
| - Transfers `amount` back to the sender (or registers a pending withdrawal). | |
| - May apply penalties or cooldown logic. | |
| - Emits `Unstaked(sender, amount, cycleId)` or equivalent. | |
| ### Rewards | |
| - `claimRewards()` | |
| Claim all unclaimed rewards for both streams across all claimable cycles. | |
| **Effects:** | |
| - Computes claimant’s pending rewards. | |
| - Updates internal storage so those rewards cannot be claimed again. | |
| - Transfers reward tokens to the claimant. | |
| - Emits `RewardsClaimed(sender, rewardA, rewardB, fromCycleId, toCycleId)`. | |
| - `claimRewardsForCycles(cycleIds[])` | |
| Claim rewards for a specific set of cycles. | |
| **Effects and constraints:** | |
| - Similar to `claimRewards()` but limited to specified cycles. | |
| - Reverts if any cycle is not yet finalized or otherwise ineligible. | |
| ### View / Read-Only Functions | |
| - `getUserStake(address user)` → `uint256` | |
| Returns the current effective stake of `user`. | |
| - `getPendingRewards(address user)` → `(uint256 rewardA, uint256 rewardB)` | |
| Computes unclaimed rewards for `user` across all finalized cycles. | |
| - `getCycle(uint256 cycleId)` → `(Cycle memory)` | |
| Returns the metadata for the given cycle. | |
| - `getCurrentCycleId()` → `uint256` | |
| Returns the identifier of the active cycle (if any). | |
| - `getConfig()` → `(Config memory)` | |
| Returns the current configuration (reward tokens, addresses, flags). | |
| ### Administrative / Governance Functions | |
| - `createCycle(params)` | |
| Initializes a new cycle with specified parameters. | |
| - `finalizeCycle(uint256 cycleId)` | |
| Marks a cycle as finalized and seals its reward parameters. | |
| - `setRewardPools(uint256 cycleId, uint256 rewardA, uint256 rewardB)` | |
| Sets or updates the reward pools for a *future* or *current but not finalized* cycle. | |
| - `pause()` / `unpause()` | |
| Enables or disables sensitive operations (staking, unstaking, claiming) in | |
| case of emergencies. | |
| - `setConfig(Config newConfig)` | |
| Updates configuration fields controlled by governance. | |
| All admin functions should: | |
| - Be restricted to a governance or admin role. | |
| - Emit informative events on state changes. | |
| - Avoid retroactive changes to finalized cycles. | |
| ## Internal / Private Logic | |
| While external callers cannot invoke internal/private functions directly, they | |
| are critical for understanding how the contract maintains correctness. The typical | |
| categories are: | |
| - **Accounting helpers** | |
| - `updateUserRewards(address user)`: | |
| - Updates a user’s stored reward state based on latest cycle data. | |
| - `updateGlobalStakeTotals()`: | |
| - Keeps per-cycle totals in sync with user-level stake changes. | |
| - **Cycle management** | |
| - `_createCycleInternal(params)`: | |
| - Common logic for initializing a cycle used by `createCycle`. | |
| - `_finalizeCycleInternal(cycleId)`: | |
| - Seals reward pools and prevents further changes for the given cycle. | |
| - **Validation / guard checks** | |
| - `_onlyGovernance()`: | |
| - Restricts certain calls to the governance address. | |
| - `_ensureCycleActiveOrUpcoming(cycleId)`: | |
| - Ensures that operations are applied only to valid cycles. | |
| These internal functions should: | |
| - Keep state transitions atomic and well-documented via events. | |
| - Enforce all necessary invariants (no negative balances, no double-claims, etc.). | |
| - Reuse code across multiple public functions to avoid inconsistencies. | |
| ## Events | |
| Typical events emitted by the Dual Stacking contract include: | |
| - `event Staked(address indexed user, uint256 amount, uint256 cycleId);` | |
| - `event Unstaked(address indexed user, uint256 amount, uint256 cycleId);` | |
| - `event RewardsClaimed(address indexed user, uint256 rewardA, uint256 rewardB, uint256 fromCycleId, uint256 toCycleId);` | |
| - `event CycleCreated(uint256 indexed cycleId, uint256 startTime, uint256 endTime, uint256 rewardA, uint256 rewardB);` | |
| - `event CycleFinalized(uint256 indexed cycleId);` | |
| - `event RewardPoolsUpdated(uint256 indexed cycleId, uint256 rewardA, uint256 rewardB);` | |
| - `event Paused(address indexed account);` | |
| - `event Unpaused(address indexed account);` | |
| - `event ConfigUpdated(address indexed updater);` | |
| Events are essential for: | |
| - Off-chain indexers and UIs to reconstruct user positions and rewards. | |
| - Auditors to inspect protocol behavior over time. | |
| - Debugging and incident response. | |
| ## Security Considerations | |
| When reviewing or modifying the Dual Stacking Smart Contract implementation, | |
| particular attention should be paid to: | |
| - **Reentrancy**: | |
| - External token transfers (base asset, reward tokens) should be ordered | |
| after state updates and guarded by a reentrancy lock if necessary. | |
| - **Access control**: | |
| - All admin and governance functions must be restricted to the appropriate | |
| role(s) and tested with negative test cases. | |
| - **Reward exhaustion**: | |
| - Ensure reward pools cannot be over-distributed due to rounding or race | |
| conditions when cycles are finalized. | |
| - **Precision and rounding**: | |
| - Reward calculations should be carefully audited to avoid systemic bias in | |
| favor of either small or large stakers. | |
| - **Upgradeability** (if used): | |
| - Clearly define upgrade paths and any initialization routines. | |
| - Avoid storage layout collisions. | |
| ## Integration Guidelines | |
| For frontends and integrators: | |
| - Use **view** functions to present: | |
| - Current cycle information. | |
| - User’s current stake and pending rewards. | |
| - Always: | |
| - Listen to events to keep off-chain state synchronized. | |
| - Consider gas costs when batching multiple user actions. | |
| - Clearly display: | |
| - Lockup periods. | |
| - Potential penalties for early unstaking. | |
| - Any special conditions required to receive rewards from both streams. | |
| ## Appendix: Terminology | |
| - **Base asset**: The token users stake (e.g., a governance or utility token). | |
| - **Reward stream A / B**: Two logically separate reward flows associated with | |
| a single staked position. | |
| - **Cycle**: A discrete time or block interval over which rewards are accrued | |
| and later claimable. | |
| - **Effective stake**: Stake adjusted for time and any weighting rules used in | |
| reward computation. | |
| This document replaces earlier, more fragmented descriptions of the Dual Stacking | |
| Smart Contract and is intended to serve as the single reference for its behavior | |
| at a high level. |
Added current version information for the dual stacking contract.
Added link to the live dual stacking contract on mainnet.
Spagero763
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d
Added details about the v2.0.2 upgrade features for the dual stacking smart contract.
Added details about decentralized architecture features including permissionless operations, on-chain data usage, competitive ratio discovery, transparent execution, and self-service enrollment.
Spagero763
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d
Added a stepper section to the dual-stacking smart contract documentation.
Added details about user enrollment and participation options.
Added note about enrollment status display in the web app dashboard.
Added a section on Snapshots and Cycles to the dual-stacking smart contract documentation.
Added a new section on Ratio Computation.
Added a new section on weight calculation after ratio computation.
Added information about participant weight calculations and boost.
Spagero763
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
g
Description
Describe the changes that were made in this pull request. When possible start with the motivations behind the change.