-
Notifications
You must be signed in to change notification settings - Fork 47
minter: Add inflation bounds to inflation adjustment algorithm #645
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
base: delta
Are you sure you want to change the base?
minter: Add inflation bounds to inflation adjustment algorithm #645
Conversation
|
Suggested further actions:
|
| // Transfer state from old Minter | ||
| currentMintableTokens = oldMinter.currentMintableTokens(); | ||
| currentMintedTokens = oldMinter.currentMintedTokens(); | ||
| inflation = oldMinter.inflation(); |
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.
Should we copy all fields including inflationChange and targetBondingRate to make sure we get a consistent state snaphot? Otherwise, we'd be relying on the transaction that constructed the contract to have initialized it with the same values as the current minter.
We usually run the contract creation separately so that we have a fixed address for the governor transaction. In that case it probably makes sense to make the upgrade tx "self-contained", copying all state, not relying on args configured in other txs. WDYT?
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 are two reasons why we thought it would rather be more confusing:
- We wouldn't be able to copy all possible fields, since
maxInflationandminInflationare not part of the currently deployed contract. In other words it would be confusing during the next upgrade that everything is copied except for those 2 values - The overwrite of other arguments is redundant and can create additional confusion. For example, in case governance decides to also change some of the configurable parameters (e.g.
inflationChange) during the Minter upgrade, it will result in 1) deploying the contract with the new or some values 2) callingmigrateOldMinterStatethat will reset them to the old state 3) callingset*functions to set them to the new values
Based on this, we've decided to update only the minimum required state that is dynamically changing.
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 problem is that the contracts are not created on the governance transaction, so someone would need to have run a separate transaction first to deploy the new Minter contract. This transaction would not be on governor-scripts repo so it would need to be reviewed separately, creating further complexity on the deployment flow (or at least that's how I remember we did it before).
So IMO an extra transaction to change any other parameters that the governance wants would be preferred, as it would also be very explicit (and not set on a "deploy contract" transaction that is not necessarily audited on the governance process).
Regarding not copying the maxInflation and minInflation, I think it could be covered by a local comment saying that the fields were added with the migration function, so they should be copied if a new version is made. WDYT?
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.
creating further complexity on the deployment flow (or at least that's how I remember we did it before).
I'm not sure where the additional complexity is coming from, as the deployed contract and its state have to be reviewed anyway. Typically, the review of the contract should be part of the standard "governance payload review": if the payload mentions/interacts with a new contract, the code as well as the state have to be checked. In my opinion, having 2 places where a state variable is being modified is rather confusing than "explicit".
So IMO an extra transaction to change any other parameters that the governance wants would be preferred, as it would also be very explicit (and not set on a "deploy contract" transaction that is not necessarily audited on the governance process).
Same problem here: do you then would also suggest to set inflation ceiling and floor in the governance payload to make it explicit? (although those values have already been set at deployment via the constructor arguments)
Regarding not copying the
maxInflationandminInflation, I think it could be covered by a local comment
If we still would go with updating migrateOldMinterState scope, what do you mean by the "local" comment? Some kind of TODO comment inside the function (e.g. "TODO: add inflationCeiling and inflationFloor once old miter has those values")?
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## delta #645 +/- ##
===============================================
Coverage 100.00000% 100.00000%
===============================================
Files 29 29
Lines 1331 1354 +23
Branches 223 232 +9
===============================================
+ Hits 1331 1354 +23
Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
victorges
left a comment
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.
LGTM! The only required change is fixing the name of the setinflationCeiling/Floor functions
| function inflationCeiling() external view returns (uint256); | ||
|
|
||
| function minInflation() external view returns (uint256); | ||
| function inflationFloor() external view returns (uint256); |
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 like the rename! Make sure there's no occurences of [Mm]ax.+[Ii]nflation on the project anymore 👀
contracts/token/Minter.sol
Outdated
| * @param _inflationFloor New inflation floor as a percentage of total token supply | ||
| */ | ||
| function setMinInflation(uint256 _minInflation) external onlyControllerOwner { | ||
| function setinflationFloor(uint256 _inflationFloor) external onlyControllerOwner { |
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.
Probably mis-replaced the name here:
| function setinflationFloor(uint256 _inflationFloor) external onlyControllerOwner { | |
| function setInflationFloor(uint256 _inflationFloor) external onlyControllerOwner { |
Will need to rename in other places like tests etc
contracts/token/Minter.sol
Outdated
| * @param _inflationCeiling New inflation cap as a percentage of total token supply | ||
| */ | ||
| function setMaxInflation(uint256 _maxInflation) external onlyControllerOwner { | ||
| function setinflationCeiling(uint256 _inflationCeiling) external onlyControllerOwner { |
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.
Same
| function setinflationCeiling(uint256 _inflationCeiling) external onlyControllerOwner { | |
| function setInflationCeiling(uint256 _inflationCeiling) external onlyControllerOwner { |
test/unit/Minter.js
Outdated
| const startInflation = await minter.inflation() | ||
| // Ensure the logic is unaffected by the target bonding rate | ||
| for (const targetBondingRate of [400, 500, 600]) { | ||
| it("inflation is increased IF inflation < inflationFloor (independent from bonding rate)", async () => { |
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: Even better than the parenthesis would be specifying the bonding rate on the test title
| it("inflation is increased IF inflation < inflationFloor (independent from bonding rate)", async () => { | |
| it($"inflation is increased IF inflation < inflationFloor (targetBondingRate=${targetBondingRate})", async () => { |
Same below
What does this pull request do? Explain your changes. (required)
This PR extends the original PR (introduced inflation bounds for the Minter) with tests and other changes required for deploying the contract and merging the PR.
Specific updates (required)
maxInflationandminInflationconstructor arguments, setters and the updated inflation logicminInflationlower bounddeploy_contracts.tslogic to match on-chain stateIMinter.solinterfaceHow did you test each of these updates (required)
We used the existing hardhat setup to extend the coverage for the newly added code:
maxInflationconstructor argument can’t be > 100%minInflationconstructor argument can’t be > 100%minInflationconstructor argument can’t be >maxInflationminInflationconstructor argument can be same asmaxInflationand can be0setMinInflationfunction can only be called by the Controller ownersetMinInflationfunction fails if providedminInflation> 100%setMinInflationfunction fails if providedminInflation>maxInflationsetMinInflationcan setminInflationto 0,maxInflationor other valid valuesetMaxInflationfunction can only be called by the Controller ownersetMaxInflationfunction fails if providedmaxInflation> 100%setMaxInflationfunction fails if providedmaxInflation<minInflationsetMaxInflationcan setmaxInflationto 0,minInflationor other valid valuemigrateOldMinterStatefunction can only be called by the Controller ownermigrateOldMinterStatefunction can only be called when old minter is still registered in the controllermigrateOldMinterStatefunction successfully transfers old minter variables to the current minterinflationis increased up tomaxInflationIFcurrent < targetBondingRateinflationis increased up tominInflationIFinflation < minInflation(independent from the bonding rate)inflationis decreased down tominInflationIFcurrent > targetBondingRateinflationis decreased down tomaxInflationIFinflation > maxInflation(independent from the bonding rate)inflationis maintained IFcurrent = targetBondingRateAND withinminInflationandmaxInflationinflationis maintained IFminInflation = maxInflation(independent from the bonding rate)migrateToNewMinteron the previous MintermigrateOldMinterStateon the new MinterMINTER_ROLEto the new MinterMINTER_ROLEfrom the previous MinterMinterUpgradethat previously ensured that internal state is zeroed, changed to ensure state of the 3 “dynamic” variables is correctly migratedMinterUpgradethat previously ensured that user received 0 rewards after the upgrade is changed to ensure received reward is greater than 0We also took an opportunity to improve the CI by:
test:coverage:checkcommand thatexits with non-zero code, if coverage is not 100%test.yamlworkflow that executes the above commandTo prepare for the new Minter deployment, we’ve also manually done the following checks:
@openzeppelin/contracts/token/ERC20/IERC20.soldependency was updated. Here is the diff: only comments and argument names were changed, this has no effect on the actual bytecode@openzeppelin/contracts/utils/math/SafeMath.soldependency was updated. Here is the diff: only comments and formatting of the code were changed, this has no effect on the actual bytecodecontracts/bonding/IBondingManager.solwas updated. Here is the diff: 1 new event and 2 new functions were added, unused by the Minter contractDoes this pull request close any open issues?
No, but it addresses the discussion started on Livepeer Forum and in the original PR.
Checklist:
README and other documentation updatedℹ️ We found no relevant documentation of the Minter contract inside this repository
yarn testpassNext steps
maxInflationandminInflationvalues for the deployment (although not a blocker for this PR, since those values can be changed after the deployment during the actual governor update)