-
Notifications
You must be signed in to change notification settings - Fork 3
[RD-1865] Gauge continuous distributions #5
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: development
Are you sure you want to change the base?
[RD-1865] Gauge continuous distributions #5
Conversation
This commit modifies the allocator strategy to distribute tokens to gauges based on votes received rather than to voters based on voting power. The same proportional allocation logic is used but applied to gauge vote counts instead of voter powers.
The change adds proper validation to prevent setting distributions for past epochs that have no snapshot, while allowing updates to snapshotted epochs.
The strategy now relies on external claim tracking rather than storing claim data internally
The commit modifies the allocation strategy to use live data from the gauge voter contract for current epoch calculations, while still using snapshots for past epochs.
The tests analyze gas usage patterns for claims across different epochs and distributions, helping measure and optimize performance.
The commit adds a sum to optimize gas costs for calculating past epochs' distributions. Key changes: - Implement sum processing when setting epoch distributions - Optimize getClaimeableAmount by using sum values for past epochs - Add tests for sum functionality and gas optimization
| if (msg.sender != owner() && msg.sender != address(dao())) { | ||
| revert IAllocatorStrategy.OnlyDAOAllowed(msg.sender); |
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.
owner() or dao() doesn't match OnlyDAOAllowed()
| super.initialize(_strategyTypeId, _dao, _plugin, _auxData); | ||
|
|
||
| IGaugeVoterSnapshotter _snapshotter = abi.decode(_auxData, (IGaugeVoterSnapshotter)); | ||
| if (address(_snapshotter) == address(0)) revert InvalidSnapshotter(); |
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.
Additional checks like code.size or supportsInterface() might help
| function getInitializationEncodingTypes() external pure override returns (string memory types) { | ||
| return "address"; // IGaugeVoterSnapshotter | ||
| } | ||
|
|
||
| /// @inheritdoc IAllocatorStrategy | ||
| function getCreationEncodingTypes() external pure override returns (string memory types) { | ||
| return "uint256,uint256"; // startEpoch, endEpoch | ||
| } | ||
|
|
||
| /// @inheritdoc IAllocatorStrategy | ||
| function getClaimEncodingTypes() external pure override returns (string memory types) { | ||
| return ""; // No auxData needed for claims since we accumulate all epochs | ||
| } |
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.
As recommended earlier, I would provide a single source of truth (i.e. encodeInitializeParams(), decodeInitializeParams(), encodeNewEncodingTypes, ...) rather than shipping ABI getters that the UI must handle on its own and which may add friction/mismatches
| GaugeDistributionCampaign storage campaign = campaigns[_campaignId]; | ||
|
|
||
| // Validate campaign exists | ||
| _validateCampaignExists(_campaignId); |
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.
_assertCampaignExists()
| uint256 startFrom = _getNextUnprocessedEpoch(campaign); | ||
|
|
||
| // Only calculate epochs not yet processed | ||
| for (uint256 epoch = startFrom; epoch <= endEpoch;) { |
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.
Unbound loops may lead to gas limit issues in the future.
- Why are we looping if we mainly care about
epoch == currentEpoch? - What is
snapshotter.isEpochSnapshotted()actually doing?
| /// @notice Validates that a past epoch has a snapshot | ||
| /// @param _epochId Epoch to validate | ||
| /// @param _currentEpoch Current epoch | ||
| function _validatePastEpochHasSnapshot(uint256 _epochId, uint256 _currentEpoch) internal view { |
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.
_assertEpochSnapshotted()
| _setEpochDistribution(campaign, _epochId, _amount, currentEpoch); | ||
| } | ||
|
|
||
| function _setEpochDistribution( |
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.
Set epoch distribution, what is the "distribution" being set?
Consider adding natspec comments that explain what this function is about
| /// @title GaugeVoterSnapshotter | ||
| /// @notice Contract that captures and stores historical gauge voting data | ||
| /// @dev Stores snapshots of gauge votes and total voting power for each epoch | ||
| contract GaugeVoterSnapshotter is IGaugeVoterSnapshotter, DaoAuthorizableUpgradeable { |
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.
Why using DaoAuthorizableUpgradeable if there is no auth() guard or dao() getter?
| ERC165Upgradeable | ||
| { | ||
| /// @notice The ID of the permission required to manage encoder configurations | ||
| bytes32 public constant ENCODER_MANAGER_PERMISSION_ID = keccak256("ENCODER_MANAGER_PERMISSION"); |
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.
Where is this permission used?
| ERC165Upgradeable | ||
| { | ||
| /// @notice The ID of the permission required to manage strategy configurations | ||
| bytes32 public constant STRATEGY_MANAGER_PERMISSION_ID = keccak256("STRATEGY_MANAGER_PERMISSION"); |
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.
Where is this permission used?
Files to focus on to review: