-
Notifications
You must be signed in to change notification settings - Fork 8
Add Delegation Pool contract #449
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: develop
Are you sure you want to change the base?
Conversation
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 PR implements a comprehensive Delegation Pool contract that allows users to pool their SQT tokens for delegation to indexers, with automated reward management and fee collection. The pool manager can allocate funds to indexers to optimize rewards while users receive ERC20 shares representing their stake.
Key changes:
- Adds a new DelegationPool contract with delegation, undelegation, and withdrawal functionality
- Implements era-based share pricing to prevent reward manipulation attacks
- Provides comprehensive test coverage with 1,340 test lines and mock contracts
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.
Show a summary per file
File | Description |
---|---|
contracts/DelegationPool.sol | Main delegation pool contract implementing ERC20 shares, manager functions, and auto-compounding |
test/DelegationPool.test.ts | Comprehensive test suite covering all functionality with edge cases and integration tests |
contracts/mocks/MockStakingManager.sol | Mock contract for testing auto-compound functionality with simulated rewards |
contracts/interfaces/IStakingManager.sol | Extended interface with delegation and reward management functions |
publish/revertcode.json | Added error codes (DP001-DP015) for delegation pool specific errors |
contracts/RewardsPool.sol | Minor type consistency fixes (uint to uint256) |
contracts/RewardsBooster.sol | Minor type consistency fix (uint to uint256) |
CLAUDE.md | Added development documentation for AI assistance |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
@codex review |
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
/** | ||
* @dev Automatic compound rewards for all active delegations | ||
*/ | ||
function autoCompound() external { | ||
require(activeIndexers.length > 0, 'DP013'); | ||
|
||
// Update share price for new era BEFORE claiming rewards | ||
// This ensures any new deposits use the old price (no reward benefit) | ||
_updateSharePriceIfNeeded(); | ||
|
||
IStakingManager stakingManager = IStakingManager( | ||
settings.getContractAddress(SQContracts.StakingManager) | ||
); | ||
IERC20 sqToken = IERC20(settings.getContractAddress(SQContracts.SQToken)); | ||
|
||
uint256 rewardsBefore = sqToken.balanceOf(address(this)); | ||
stakingManager.batchStakeReward(activeIndexers); | ||
uint256 rewardsAfter = sqToken.balanceOf(address(this)); | ||
|
||
uint256 totalRewards = rewardsAfter - rewardsBefore; | ||
|
||
if (totalRewards == 0) { | ||
return; // No rewards to compound | ||
} | ||
|
||
// Calculate and deduct fees from rewards | ||
uint256 feeAmount = 0; | ||
if (feePerMill > 0) { | ||
feeAmount = (totalRewards * feePerMill) / PER_MILL; | ||
accumulatedFees += feeAmount; | ||
emit FeesDeducted(totalRewards, feeAmount); | ||
} | ||
|
||
// Add remaining rewards to available assets for compounding | ||
uint256 compoundAmount = totalRewards - feeAmount; | ||
availableAssets += compoundAmount; |
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.
Recompute share price after autoCompound adds rewards
In autoCompound
the contract locks the era share price via _updateSharePriceIfNeeded()
before calling batchStakeReward
and never updates it again once availableAssets
increases (lines 488‑520). Deposits executed later in the same era continue minting shares with the stale currentEraSharePrice
, so newcomers can buy shares at the pre‑reward rate and capture a portion of the freshly compounded rewards they didn’t contribute. The share price should be recalculated after rewards are added (or rewards should mint new shares) so asset-per-share stays accurate within the era.
Useful? React with 👍 / 👎.
Co-authored-by: Copilot <[email protected]>
Implements a Delegation Pool contract
Overview
A Delegation Pool contract that allows aggregation of SQT to be pooled together and used to delegate to indexers.
Delegation should behave the same as if the user had delegated directly to an indexer. There is a manager (owner) of the pool
that determines the delegation strategy to indexers.
Details
Delegation
Users delegate their SQT to the pool and receive pool shares (ERC20 tokens) representing their stake in the pool. The pool manager can then
allocate those funds to the indexers they choose to optimise rewards.
Undelegation
Users can then trigger undelegation which will burn their shares and
start a withdrawal process that then allows the user to withdraw their SQT after the lock period which is the same duration as if they had
directly delegated.
Withdrawls
After the lock period, users can withdraw their SQT and rewards from the pool, minus and pool and unbonding fees.
Managers
The pool manager is responsible for making sure the available assets in the pool are delegated to indexers to earn rewards.
The manager can do all the same functionality as delegating directly to an indexer such as delegate, undelegate, redelegate and claim rewards.
The manager can also trigger auto-compounding of rewards which claims rewards from all indexers as well as set a reward fee.