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

feat/gauge-proxy-v2 and related updates #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

UrAvgDeveloper
Copy link
Collaborator

No description provided.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

library Address {
Copy link

@larrythecucumber321 larrythecucumber321 Sep 29, 2022

Choose a reason for hiding this comment

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

We should decouple the (larger) libraries and interfaces in dedicated files/folders

_;
}

modifier onlyGov() {

Choose a reason for hiding this comment

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

This might be more appropriate to include in ProtocolGovernance

address _jar,
address _governance,
address _distribution,
string[] memory _rewardSymbols,
Copy link

@larrythecucumber321 larrythecucumber321 Sep 29, 2022

Choose a reason for hiding this comment

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

We shouldn't be storing arbitrary rewardSymbols in our contracts - contract addresses should be the first class citizens (in events and whatever else). If needed, the cononical symbols can be obtained using IERC20(token).symbol()

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed this.

_deposit(amount, account, 0, block.timestamp, false);
}

function depositForAndLock(

Choose a reason for hiding this comment

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

What are some scenarios where a delegated deposit is useful? Since the user holding the tokens will have to approve the gauge contract for spending the token, they might as well go all the way and ultimately perform the deposit themselves right, rather than waiting for someone to eventually do it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Needs discussion. Although these functions cause no harm and might support an use case of infinite approval to the platform and the platform auto renewing your rewards as deposits.

thisStake.ending_timestamp;

// Get the weighted-average lock_multiplier
uint256 numerator = (lock_multiplier * timeBeforeExpiry) +

Choose a reason for hiding this comment

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

As I understand it, claims that are made after the lock expires receive the original undecayed lock. For example, if a user locks for 1 year and doesn't make a claim until 1 year and 1 days later, they will receive a full 2.5x boost for their lock (when it would have normally decayed if they claimed throughout the year).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes I will average the decay.

uint256 combined_boosted_amount = (liquidity * lock_multiplier) /
_MultiplierPrecision;
lockBoostedDerivedBal =
lockBoostedDerivedBal +
Copy link

@larrythecucumber321 larrythecucumber321 Sep 29, 2022

Choose a reason for hiding this comment

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

Isn't lockBoostedDerivedBal always 0? What is this variable meant to represent?

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 applied a for loop and add the boost for each locked stake in each iteration in case of multiple stakes. This will be removed now that we have a single lock.

combined_boosted_amount;
}

return dillBoostedDerivedBal + lockBoostedDerivedBal;

Choose a reason for hiding this comment

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

dillBoostedDerivedBal reaches a maximum of the user's _balance to reflect a 2.5x boost whereas lockBoostedDerivedBal follows a different paradigm and reaches a maximum of _balance * 2.5, meaning that the impact of a locked stake outweighs that of a DILL lock. I believe they have to match up otherwise the math becomes incorrect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch on the math difference between the 2 boosts. Need to rethink if this is possible similar to the DILL boost calculation. Although at the end the derived balance due to different boosts is relative (max being 2.5 and min being 1). I am thinking even if both boosts have different calcs, at the end it might be okay due to the relativity. I will still rethink this to maintain consistency.


function setMultipliers(uint256 _lock_max_multiplier) external onlyGov {
require(
_lock_max_multiplier >= uint256(1e18),

Choose a reason for hiding this comment

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

Use _MultiplierPrecision for this

emit LockedStakeMaxMultiplierUpdated(lockMaxMultiplier);
}

function setMaxRewardsDuration(uint256 _lockTimeForMaxMultiplier)
Copy link

@larrythecucumber321 larrythecucumber321 Sep 29, 2022

Choose a reason for hiding this comment

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

I think these functions setMaxRewardsDuration and setMultipliers are dangerous because it disturbs existing derivedSupply and derivedBalance calculations by naively mutating critical global variables. I honestly think these are better off removed.

Copy link

@larrythecucumber321 larrythecucumber321 left a comment

Choose a reason for hiding this comment

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

These comments only include a review of the GaugeV2 and VirtualGaugeV2 contracts for now.

Regarding contract structure, I think these two contracts should both inherit from a GaugeBase abstract contract as there is much shared code/functionality between them.

Also, I think there is also fundamental difference in how we understand the virtual gauges to function. In your implementation, you seem to envision jars having the ability to deposit into the gauge on behalf of users. I would like to understand the full flow, but I don't believe that our jars, as currently designed/deployed, are able to implement this proxy deposit/withdrawal function.

My personal understanding of the purpose of virtual guages was that we could migrate the legacy GaugeProxy users to the new system without the friction of requiring them to withdraw and re-stake. This would've involved querying the legacy gauge for users' balances to determine the rewards they should receive. Although this might not be feasible as updateReward cannot be frequently called in this scenario. Would love to hear your thoughts.

}

function changeGaugeProxy(address _newgaugeProxy) external {
require(msg.sender == governance, "can only be called by gaugeProxy");

Choose a reason for hiding this comment

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

Error message should say governance

if (_indefinite == true) {
_delegate.indefinite = true;
} else if (_delegate.prevDelegate == address(0)) {
_delegate.endPeriod = currentPeriodId + _periodsCount - 1;

Choose a reason for hiding this comment

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

Why is it that the endPeriod is subtracted by 1 week if there was no prior delegate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So if there is a previous delegate, the count for the end period of the next period starts from the next period as the prevDelegate will be active for the current period. If no previous delegate, just start the count from the current period.

currentId > _delegate.updatePeriodId) ||
(_delegate.prevDelegate == msg.sender &&
currentId == _delegate.updatePeriodId) ||
(_delegate.prevDelegate == address(0) &&

Choose a reason for hiding this comment

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

Doesn't this condition make it so that if the user previously had no delegate and decided to delegate this period, that ANYONE would be able to vote on their behalf?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

(_delegate.prevDelegate == address(0) && currentId == _delegate.updatePeriodId

The second check in the && condition ensures that this will work only if a delegate is set. If not set _delegate.updatePeriodId is 0 and currentId is never 0. If previous delegate is set, this OR condition is not checked as it passes for the previous OR conditions.

address[] memory _rewardTokens = new address[](1);
_rewardSymbols[0] = "PICKLE";
_rewardTokens[0] = address(PICKLE);
address vgauge = virtualGaugeMiddleware.addVirtualGauge(

Choose a reason for hiding this comment

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

For consistency, gauges[_token] can be assigned the return value from addVirtualGauge, like above

_totalWeight;
if (_reward > 0) {
uint256 reward_ = uint256(_reward);
uint256[] memory rewardArr = new uint256[](1);

Choose a reason for hiding this comment

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

I see that the gauges are meant to accomodate multiple types of rewards, but this distribute function never allows for the other rewards to be realized (as there's an onlyDistribution modifier on the gauge contracts)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Check for onlyDistribution modifier

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Add limit of 8 reward tokens

console.log("Rewards to Pickle gauge", pickleRewards.toString());

const yvecrvRewards = await pickle.balanceOf(yvecrvGaugeAddr);
console.log("Rewards to pyveCRV gauge", yvecrvRewards.toString());

Choose a reason for hiding this comment

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

I would expect to see an assertion that the average weekly rewards currently in each gauge are equal to those of the first week.

it("Should vote successfully (second voting)", async () => {
console.log("-- Voting on LP Gauge with 100% weight --");
const gaugeProxyFromUser = GaugeProxyV2.connect(userAddr);
populatedTx = await gaugeProxyFromUser.populateTransaction.vote(

Choose a reason for hiding this comment

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

Would it perhaps be more useful to have another user vote (with different weights) and test the feature that votes from past periods persist if untouched?

).to.be.revertedWith("set jar first");

// Set Jar
await Jar.setVirtualGauge(VirtualGaugeV2.address);

Choose a reason for hiding this comment

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

I don't see a new Jar contract with the virtual gauge interfaces

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.

2 participants