-
Notifications
You must be signed in to change notification settings - Fork 4
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
Add OGNRewardsSource contract #408
Conversation
@shahthepro I have added my comments regarding the changes. |
* Add Migrator contract * Fix some tests * Code review changes * Update OgvStaking tests * Disable delegation tests * Allow just unstakes * Fix comment * More cleanup * Fix brownie tests
* Check available balance in `previewRewards` * Chore: forge fmt --------- Co-authored-by: Daniel Von Fange <[email protected]>
FixedRateRewardsSourceRequirementsThe FixedRateRewardsSource works to provide a steady per block stream of incentives funds to the xOGN staking contract. Rewards can be sent to the contract from any source (including incentives, as well as protocol buybacks), but will drip out at a rate that can be changed by the strategist. In the event that not enough funds are in the dripper, what funds are there are given out, and the dripper is reset to start accruing max dripped funds again. In this way even if there are fewer funds than expected coming in, the contract will still hand out whatever funds it does get. Deployment ConsiderationsThere's a potential circular address dependency between this contract and the staking contract. Both need to know the address of the other. We've taken the simple route and made this contract us a mutable address for the staking contract, while the staking contract uses an immutable address for this. If the contract is not initialized, collect rewards will revert because the message sender is not 0, preventing anything weird from happening. This should be deployed into a proxy. Internal State
We should not have resolution issues on AttackDepending on how this contract is used, it could hold up to a month or two of incentives. This could be a substantial amount reward tokens. This contract does not hold any user funds. Attackers could attempt to steal funds. However, Funds only transfer to the admin controlled rewards target. Attackers could attempt to increase the number of rewards paid. However rewards paid can only be increased by donating to the contract (and only then if it does not have enough rewards) A collectRewards should be called before changing the setRewardsPerSecond, if we care about accuracy, or if it has not been called in a long time. This ensures that the past is paid at the past rate. LogicContract logic looks correct . Tests
FlavorThere are a few tiny flavor changes I see, but we can leave the contract as is.
OverflowNo for loops Proxy
Black magic
Dependencies
Deploy
Authentication
Cryptographic code_No Crypto Gas problems
External calls
Ethereum
|
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.
Approving FixedRateRewardsSource
uint256 oldPoints = 0; | ||
uint256 oldEnd = 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.
gas: no need for initialising with default values.
require(to != address(0), "Staking: To the zero address"); | ||
require(duration >= minStakeDuration, "Staking: Too short"); |
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.
Consider custom errors?
assertEq(amount, 0, "Lockup still exists"); | ||
assertEq(end, 0, "Lockup still exists"); | ||
assertEq(points, 0, "Lockup still exists"); |
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.
good to add a different string as it will be easier to figure out which one fails, if one if them fail.
assertEq(amount, 0, "amount:Lockup still exists");
assertEq(end, 0, "end:Lockup still exists");
assertEq(points, 0, "points:Lockup still exists");
import "OpenZeppelin/[email protected]/contracts/token/ERC20/extensions/ERC20Burnable.sol"; | ||
import "./Governable.sol"; | ||
|
||
interface IStaking { |
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.
can we move this interface to a separate (interfaces) folder?
import "contracts/tests/MockOGV.sol"; | ||
import "contracts/tests/MockOGVStaking.sol"; | ||
|
||
contract MigratorTest is Test { |
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.
good to add tests for event data as well.
ogn.mint(address(migrator), 10000000 ether); | ||
|
||
// Users have enough OGV | ||
ogv.mint(alice, 10000000 ether); |
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.
10000000 ether
seems redundant across the tests. maybe make it a constant?
lockupIds[0] = 0; | ||
lockupIds[1] = 1; | ||
|
||
uint256 stakeAmount = (11000 ether * 0.09137 ether) / 1 ether; |
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.
0.09137 ether
can be a constant in tests or can fetched from migrator.CONVERSION_RATE().
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.
I guess one advantages of having this number in the tests as well is that it confirms that the contract also has the right conversion rate set. Somewhat like double entry accounting.
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.
Yeah, agree with both, I can probably move it to the top of the test file as constant (still separate from the hardcoded contract value)
If you made a contract change, make sure to complete the checklist below before merging it in master.
Contract change checklist: