-
Notifications
You must be signed in to change notification settings - Fork 18
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
👷 KSX - Remove escrow on inflationary rewards and remove staking cooldown #252
base: main
Are you sure you want to change the base?
Conversation
contracts/StakingRewardsV2.sol
Outdated
} | ||
} | ||
|
||
function _getRewardCompounding(address _account) |
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.
needs natspec. i am confused what this is supposed to do
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.
This is called when compounding, basically it is doing the same as _getReward
but without transfering because the rewards are staked right after this (can be staked immediatly after calling this (see _compound()
).
Added natspec to specify this.
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.
Hmm, is there a difference to this vs. the code in _getReward other than transferring? I see duplicate code. I was thinking that this reward calculating logic would be shared between the two and getReward only has the distinction of transferring to the user.
ie.
getReward() {
(kwenta, usdc) = _calculateReward()
transfer kwenta
transfer USDC
}
compound() {
(kwenta, usdc) = _calculateReward()
stake kwenta
transfer USDC
}
_calculateReward() {
...
}
TLDR; we should be practicing DRY here to minimize room for error.
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.
Refactored with a _processReward
so that there is no duplicate logic
I've merged the 'Staking Cooldown Removal' feature into this branch and also pulled the USDC rewards from main branch. This PR should be the one that goes live with the KSX deployment. |
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.
Everything LGTM! Nice work
@@ -19,7 +19,7 @@ import {IEscrowMigrator} from "./interfaces/IEscrowMigrator.sol"; | |||
/// @title KWENTA Reward Escrow V2 | |||
/// @author Originally inspired by SYNTHETIX RewardEscrow | |||
/// @author Kwenta's RewardEscrow V1 by JaredBorders ([email protected]), JChiaramonte7 ([email protected]) | |||
/// @author RewardEscrowV2 by tommyrharper ([email protected]) | |||
/// @author RewardEscrowV2 by tommyrharper ([email protected]), Flocqst ([email protected]) |
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.
nit: I would break each author up on separate lines
contracts/StakingRewardsV2.sol
Outdated
} | ||
} | ||
|
||
function _getRewardCompounding(address _account) |
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.
Hmm, is there a difference to this vs. the code in _getReward other than transferring? I see duplicate code. I was thinking that this reward calculating logic would be shared between the two and getReward only has the distinction of transferring to the user.
ie.
getReward() {
(kwenta, usdc) = _calculateReward()
transfer kwenta
transfer USDC
}
compound() {
(kwenta, usdc) = _calculateReward()
stake kwenta
transfer USDC
}
_calculateReward() {
...
}
TLDR; we should be practicing DRY here to minimize room for error.
whenNotPaused | ||
updateReward(_account) | ||
returns (uint256 reward) | ||
returns (uint256 kwentaReward) |
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.
Doesn't seem you're using kwentaReward outside of _processReward, but for consistency sake you should either return both kwenta and USDC reward as a tuple or return neither.
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.
initial review of main contracts
looks pretty straight forward so far
@@ -81,9 +75,6 @@ contract StakingRewardsV2 is | |||
/// @notice summation of rewardRate divided by total staked tokens | |||
uint256 public rewardPerTokenStored; | |||
|
|||
/// @inheritdoc IStakingRewardsV2 | |||
uint256 public cooldownPeriod; |
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.
are we redeploying staking v2 or upgrading? because im pretty sure if we upgrade this removal will brick everything
@@ -81,9 +75,6 @@ contract StakingRewardsV2 is | |||
/// @notice summation of rewardRate divided by total staked tokens | |||
uint256 public rewardPerTokenStored; | |||
|
|||
/// @inheritdoc IStakingRewardsV2 | |||
uint256 public cooldownPeriod; | |||
|
|||
/// @notice represents the rewardPerToken | |||
/// value the last time the staker calculated earned() rewards | |||
mapping(address => uint256) public userRewardPerTokenPaid; |
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.
it wont let me comment a couple lines below for some reason but mapping(address => uint256) public userLastStakeTime;
should be removed because we remove the use of it everywhere in the code
// update state (first) | ||
rewards[_account] = 0; | ||
|
||
// emit reward claimed event and index account | ||
emit RewardPaid(_account, reward); | ||
emit RewardPaid(_account, kwentaReward); |
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 other event is called RewardPaidUSDC
this should be called RewardPaidKwenta to match
{ | ||
// Process Kwenta reward | ||
kwentaReward = rewards[_account]; | ||
if (kwentaReward > 0) { | ||
// update state (first) | ||
rewards[_account] = 0; |
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.
if transferKwenta is set to false meaning they want to compound their rewards then doesnt this line ruin that?
their rewards are set to 0 but they dont get transferred their kwenta, so next time this is called again (im assuming after they waited for it to compound in this contract), then their rewards will be 0 or close to 0 and therefore they lost their kwenta entirely?
if im understanding this correctly then this rewards[_account] = 0;
line shouldnt apply if transferKwenta == false
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.
oh upon further look, kwentaReward is extrapolating this value? and it hopefully gets relogged when calling _stake in _compound?
@@ -397,8 +386,8 @@ contract StakingRewardsV2 is | |||
/// @dev internal helper to compound for a given account | |||
/// @param _account the account to compound for | |||
function _compound(address _account) internal { | |||
_getReward(_account); | |||
_stakeEscrow(_account, unstakedEscrowedBalanceOf(_account)); | |||
uint256 reward = _processReward(_account, _account, false); |
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.
will reward be 0 here?
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.
just reviewed all the tests. aside: i cant find where we explicitly test these new _processReward changes.
important: we need to test the upgrade from a current fork --> new deployment (much like how cc-vesting does it). this should be done before we upgrade to ensure everything will be good, especially storage slots.
this may be doable in stakingV2.upgrade.t.sol. if not then we might have to add a new file. this may be difficult because i think everthing (testing and upgrading) is baked together and deeply webbed
Get Reward On Behalf | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
function test_getRewardOnBehalf() public { |
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 do we remove this test and the accompanying fuzz test?
//////////////////////////////////////////////////////////////*/ | ||
|
||
function test_Get_Reward_And_Stake_On_Behalf() public { | ||
function test_Get_Reward_On_Behalf() public { |
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.
its good that we are testing getReward() by itself now (im assuming we didnt before) but why are we just replacing the "on behalf" test? we no longer test getting the reward AND staking anymore
we should have both this test & the test_Get_Reward_And_Stake. not either or
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.
this reminds me: where do we test getReward (at least the new changes)? cant find it
@@ -354,7 +336,7 @@ contract StakingV2CheckpointingTests is DefaultStakingV2Setup { | |||
assertEq(value, previousTotal + amountToStake); | |||
|
|||
// move beyond cold period | |||
vm.warp(block.timestamp + stakingRewardsV2.cooldownPeriod()); | |||
vm.warp(block.timestamp + 2 weeks); |
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.
how come we mostly remove the cooldown period in this test file but then sometimes we add back this warp forward 2 weeks?
rewardsUsdc = usdc.balanceOf(user1); | ||
assertEq(rewards, expectedRewards); | ||
assertApproxEqAbs(rewardsUsdc, expectedUsdcRewards, 10); | ||
assertApproxEqAbs(rewardsUsdc, expectedUsdcRewards, 50); |
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 do we change this from 10 to 50? does that make the assert less accurate?
i just tested this locally with 10 and it still passes
assertEq(2 ether + 1 weeks, stakingRewardsV2.balanceOf(user1)); | ||
assertEq(1 ether + 1 weeks, stakingRewardsV2.escrowedBalanceOf(user1)); | ||
assertEq(1 ether, stakingRewardsV2.escrowedBalanceOf(user1)); | ||
assertEq(0, rewardEscrowV2.unstakedEscrowedBalanceOf(user1)); |
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.
this test suite needs to also test that all the accessible storage slots are not bricked
Remove escrow on inflationary rewards + Remove staking cooldown