Skip to content
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

Voting Multipliers #100

Open
wants to merge 35 commits into
base: dev
Choose a base branch
from
Open

Voting Multipliers #100

wants to merge 35 commits into from

Conversation

RonTuretzky
Copy link
Collaborator

#71

This is not upgrade-safe due to new variables introduced in an inherited class. Suggesting to couple this PR with #96 and create a brand new YieldDistributor

@RonTuretzky RonTuretzky force-pushed the feat/voting_multiplier branch from 3a0c818 to daeb1ce Compare September 28, 2024 11:59
src/YieldDistributor.sol Outdated Show resolved Hide resolved
src/YieldDistributor.sol Outdated Show resolved Hide resolved
uint256 breadVotingPower = this.getVotingPowerForPeriod(BREAD, lastCycleStart, lastClaimedBlockNumber, _account);
uint256 butteredBreadVotingPower =
this.getVotingPowerForPeriod(BUTTERED_BREAD, lastCycleStart, lastClaimedBlockNumber, _account);
return (breadVotingPower + butteredBreadVotingPower) * multiplier / PRECISION;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see what's going on. TBH I don't think PRECISION should be shared here since it's being used in two different calculations. I think the getTotalMultipliers function should probably return a tuple like (multiplier, multiplier_precision) and that should be used here. Ignore my previous comment about using "1 instead of 1e18"

Copy link
Collaborator Author

@RonTuretzky RonTuretzky Oct 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you're saying each multiplier should have it's own precision potentially? can't we just assume they are all 1e18?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should return a single number formatted to 1e18, to avoid confusion and enforce standardization

@@ -20,7 +21,7 @@ import {IYieldDistributor} from "src/interfaces/IYieldDistributor.sol";
* @custom:coauthor kassandra.eth
* @custom:coauthor theblockchainsocialist.eth
*/
contract YieldDistributor is IYieldDistributor, OwnableUpgradeable {
contract YieldDistributor is IYieldDistributor, OwnableUpgradeable, VotingMultipliers {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I'm a little dubious of the upgrade safety here. It would probably be best to implement VotingMultipliers to use ERC7201 storage layouts (like they do with OwnableUpgradeable) to avoid storage layout collisions. It seems complicated but it's actually a pretty trivial one time calculation and some boilerplate code for accessing storage variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we should just deploy a new proxy for this version, and use the setter on the bread contract, as this would also help us resolve #96

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a foreseeable problem deploying as a new proxy, thus changing the address? if there is not, i would prefer we deploy fresh, therefore do not need to worry about upgrade-safety, and not over-complicated things. but again, this is assuming there is no major problem with changing the address.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploying a new contract is definitely the move in this instance but I mean in future instances where we maybe want to make some changes to the VotingMultipliers.sol contract. Namespacing the storage layouts ensure YieldDistributor and VotingMultipliers are using their own storage locations that won't clash, so if we want to add a variable to one or the other, we can do so safely. I can make a quick branch so show what it would look like.

Copy link
Contributor

@bagelface bagelface Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think there is a strong case to be made for VotingMultipliers to be its own contract.

@RonTuretzky RonTuretzky requested a review from daopunk October 24, 2024 06:37
@RonTuretzky RonTuretzky requested a review from bagelface October 29, 2024 14:08
@RonTuretzky RonTuretzky linked an issue Oct 30, 2024 that may be closed by this pull request
@RonTuretzky
Copy link
Collaborator Author

Deprioritizing for now

@daopunk daopunk reopened this Dec 1, 2024
src/YieldDistributor.sol Outdated Show resolved Hide resolved
src/YieldDistributor.sol Outdated Show resolved Hide resolved
src/interfaces/IVotingMultipliers.sol Outdated Show resolved Hide resolved
src/multipliers/NFTMultiplier.sol Outdated Show resolved Hide resolved
src/multipliers/PermanentNFTMultiplier.sol Outdated Show resolved Hide resolved
test/YieldDistributor.t.sol Show resolved Hide resolved
test/YieldDistributor.t.sol Outdated Show resolved Hide resolved
src/VotingMultipliers.sol Outdated Show resolved Hide resolved
src/VotingMultipliers.sol Outdated Show resolved Hide resolved
src/YieldDistributor.sol Show resolved Hide resolved
/// @notice Calculates the total multiplier for a given _user
/// @param _user The address of the _user
/// @return The total multiplier value for the _user
function getTotalMultipliers(address _user) public view returns (uint256) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming we keeping this as a quality of life function so we can avoid the double query getValidMultiplierIndexes(address) -> getTotalMultipliers(address, uint256[])? If so, I think this should be moved to be closer to getTotalMultipliers(address, uint256[]) so the overload is obvious. Maybe word adding a note in the natspec comments with a @dev tag

/// @notice Array of allowlisted multiplier contracts
IMultiplier[] public allowlistedMultipliers;

/// @notice Calculates the total multiplier for a given _user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop the underscore form _user when referring to it in the comments to be consistent with other comments.

/// @notice Returns the multiplier at the specified index in the allowlist
/// @param index The index of the multiplier in the allowlist
/// @return The multiplier contract at the specified index

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove line break

error InvalidMultiplierIndex();
/// @notice Emitted when a new multiplier is added to the allowlist
/// @param multiplier The address of the added multiplier

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove line break


/// @title Cross-Chain Proveable Multiplier Interface
/// @notice Interface for contracts that provide a cross-chain proveable multiplying factor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove line break

/// @title Dynamic NFT Multiplier Interface
/// @notice Interface for contracts that provide a dynamic multiplying factor for _users based on NFT ownership
/// @dev Extends the INFTMultiplier interface with dynamic multiplier functionality

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove line break

import {IProveableMultiplier} from "src/interfaces/multipliers/IProveableMultiplier.sol";
/// @title On-Chain Proveable Multiplier Interface
/// @notice Interface for contracts that provide an on-chain proveable multiplying factor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove line break

import {IDynamicNFTMultiplier} from "src/interfaces/multipliers/IDynamicNFTMultiplier.sol";
/// @title Proveable Multiplier Interface
/// @notice Interface for contracts that provide a proveable multiplying factor based on _user activities

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove line break

*/
function castVoteWithMultipliers(uint256[] calldata _points, uint256[] calldata _multiplierIndices) public {
uint256 _currentVotingPower = getCurrentVotingPower(msg.sender);
if (_currentVotingPower < minRequiredVotingPower) revert BelowMinRequiredVotingPower();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure we want to check this requirement before multipliers are applied??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trueeeee

@@ -110,17 +112,20 @@ contract YieldDistributor is IYieldDistributor, OwnableUpgradeable {
* @return uint256 The voting power of the user
*/
function getCurrentVotingPower(address _account) public view returns (uint256) {
return this.getVotingPowerForPeriod(BREAD, previousCycleStartingBlock, lastClaimedBlockNumber, _account)
+ this.getVotingPowerForPeriod(BUTTERED_BREAD, previousCycleStartingBlock, lastClaimedBlockNumber, _account);
uint256 lastCycleStart = lastClaimedBlockNumber - cycleLength;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realizing this will be invalid if cycleLength is changed. We need a "lastCycleLength" variable. Maybe it'd be good to create a Cycle struct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should open a separate issue for this ... also mark it as bug so we don't upgrade changes without considering this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Voting Multiplier Spec
4 participants