-
Notifications
You must be signed in to change notification settings - Fork 84
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
Pool booster #2400
base: master
Are you sure you want to change the base?
Pool booster #2400
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2400 +/- ##
==========================================
- Coverage 50.96% 48.67% -2.29%
==========================================
Files 92 97 +5
Lines 4529 4783 +254
Branches 1203 1262 +59
==========================================
+ Hits 2308 2328 +20
- Misses 2217 2451 +234
Partials 4 4 ☔ View full report in Codecov by Sentry. |
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 did the first pass on Factory and both PB implementation.
With more hindsight, I'm wondering if this Factory contract is really necessary? Maybe a simple UI can be enough?
Because here, the factory is used to keep a track of all PB deployed, in order to bribes all the PB at the same time. But:
bribesAll()
have a significant amount of chance of reverting when amount of registered PB is high.- A simple multicall can do the same, with even more granularity (excluding some PB for example).
- as creation of PB is permissioned, factory isn't really needed imo.
I know we already talked about this in the Spec document on Notion, but with more hindsight, I'm less convinced in the need of a Factory.
What's more, every time we will need to add a need PB type, we will need to upgrade the proxy, which is slow (governance) and unsafe! In comparison, adding it in the UI, is way faster, and doesn't imply security matter.
I think having a Factory doesn't add value and bring a lot of hurdles. (Really sorry for changing my mind after finalizing specs).
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 looks really good!
Even though there are more contracts now, I believe it will be easier and faster to scale thanks to this architecture!
I’ve left some minor comments to check out.
for (uint256 i = 0; i < length; i++) { | ||
address poolBoosterAddress = poolBoosters[i].boosterAddress; | ||
bool skipBribeCall = false; | ||
for (uint256 j = 0; j < _exclusionList.length; j++) { |
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: as we cached length on the previous loop, maybe we can cache it here too? (This is really nit-picking, totally fine to keep it like 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.
good point: 77c21d8
require( | ||
_address.code.length > 0 && _address != address(0), | ||
"Failed creating a pool booster" | ||
); |
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 really good like this I think! 👍
*/ | ||
function removeFactory(address _factoryAddress) external onlyGovernor { | ||
require(_factoryAddress != address(0), "Invalid address"); | ||
require(isApprovedFactory(_factoryAddress), "Not an approved factory"); |
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 think we don't need this check. It is doing 2 time the same thing.
First we go through all factories to ensure it is there, then we go through all factories a second time and then if this is there, remove it.
- Maybe isApprovedFactory can return the position in the array to avoid doing 2 times the loop?
- Maybe we can just remove this check?
However, gas is cheap and too much check isn't an issue, so it is ok to keep it if you like.
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 a governance action an not really expected to be called often (if at all). For that reason I wouldn't be too worried with extra gas usage?
|
||
uint256 osBribeAmount = balance.mulTruncate(split); | ||
// -1 to prevent possible rounding issues with OS token | ||
uint256 otherBribeAmount = balance - osBribeAmount - 1; |
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 have fuzz tested that balance
could never be equal to osBribeAmount
(due to rounding issue in mulTruncate
). 👍
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.
thanks for that
function approveFactory(address _factoryAddress) external onlyGovernor { | ||
require(_factoryAddress != address(0), "Invalid address"); | ||
|
||
factories.push(_factoryAddress); | ||
emit FactoryApproved(_factoryAddress); | ||
} |
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.
There is no check to ensure that the factory isn't already approved.
But in the other hand, I don't see any issue if we have 2 times the same factory here.
So I'm fine to keep it like 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.
Actually, that is a great point. Adding a check and a test here: 735f55f
In case we have 2 entries of the same factory we could get a false sense of security from calling remove once. Since the other factory would still be in the list and considered supported.
import { PoolBoosterSwapxPair } from "./PoolBoosterSwapxPair.sol"; | ||
import { AbstractPoolBoosterFactory } from "./AbstractPoolBoosterFactory.sol"; | ||
|
||
import "hardhat/console.sol"; |
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.
Hehe
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.
713eab5 😬
"Invalid bribeContractOther address" | ||
); | ||
// expect it to be between 1% & 99% | ||
require(_split > 1e16 && _split < 99e16, "Unexpected split amount"); |
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.
range could be between 0 and 100%.
constructor( | ||
address _bribeContractOS, | ||
address _bribeContractOther, | ||
address _osToken, |
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 osToken should be oeth, ousd... tokens with 18 decimals. Maybe just make sure it's not a token with less decimals that is added to make sure MIN_BRIBE_AMOUNT
is still valid
"Invalid ammPoolAddress address" | ||
); | ||
require(_salt > 0, "Invalid salt"); | ||
|
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 swapX gauges can't be created by anyone, how will the deployment workflow be like?
Pool booster
This deploys a Pool Booster Factory on Sonic which has the ability to create individual pool booster. Pool booster is a contract that receives forwarded yield (from an AMM pool) and forwards it to corresponding Bribe contract -> which is part of the Gauge incentives.
Notice:
PoolBoosterSwapxPair
is a pool booster that supports Classic stable and classic volatile pools. Because there are no such pools on SwapX we can not fork tests its functionality. Also we can not test it on other non OS gauges since they don't accept the OS as an incentive token.Code Change Checklist
To be completed before internal review begins:
Internal review: