-
Notifications
You must be signed in to change notification settings - Fork 375
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
Implementation of tickets 1604, 1597 and 1365 #2368
Conversation
@@ -121,23 +124,19 @@ contract SortedOracles is ISortedOracles, Ownable, Initializable { | |||
/** | |||
* @notice Updates an oracle value and the median. | |||
* @param token The address of the token for which the Celo Gold exchange rate is being reported. | |||
* @param numerator The amount of tokens equal to `denominator` Celo Gold. | |||
* @param denominator The amount of Celo Gold equal to `numerator` tokens. | |||
* @param value The amount of tokens equal to Celo Gold represented as a FixidityLib fraction |
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 this comment accurate? It seems value
is also expected to have been multiplied by getDenominator()
. Is this what we want? Now that we're using Fixidity, could we keep the internal denominator private and unexposed?
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.
param description fixed, internal denominator is private, but I have added a getter needed by the cli and contractskit
* @notice Returns the common fixidity denominator. | ||
* @return The common fixidity denominator. | ||
*/ | ||
function getDenominator() public 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.
Do we need 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.
since we have the int. denominator as private, I have added a public method that is to be used by external sources e.g. contractskit and cli. Please let me know if any objections to that
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.
Reviewed changes for 1604
@@ -109,15 +110,34 @@ contract MultiSig is Initializable { | |||
initializer | |||
validRequirement(_owners.length, _required) | |||
{ | |||
setInitialOwners(_owners); |
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 the idea here is to call addOwner
and changeRequirement
instead of creating new setters that will only be used on initialize.
And since those functions are external
probably makes sense to have an _addOwner
internal function that both initialize
and addOwner
calls. Some for the other function
* @return True upon success. | ||
* @dev unwrapped Fixidity value expected for _targetVotingYield | ||
*/ | ||
function setTargetVotingYield(uint256 _targetVotingYield) public onlyOwner returns (bool) { |
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'm not sure for this contract, but we are changing the semantics here... since dureing the lifetime of the contract we can change the target voting yield.
I wonder if that's what we want.
@asaj @marekolszewski comments?
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.
+1, the scope of this ticket was more about reducing tech debt than exposing setters for values that were previously not possible to set externally
* @param _startTime The time in unix. | ||
* @return True upon success. | ||
*/ | ||
function setStartTime(uint256 _startTime) public onlyOwner returns (bool) { |
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
@asaj @marekolszewski comments?
* @notice Updates the last dequeue timestamp. | ||
* @param _lastDequeue The last dequeue timestamp. | ||
*/ | ||
function setLastDequeue(uint256 _lastDequeue) public onlyOwner { |
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...
@asaj @marekolszewski comments?
* @notice Setter for the total supply. | ||
* @param totalSupply The total supply to set. | ||
*/ | ||
function setTotalSupply(uint256 totalSupply) 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.
I don't think we want a public function that lets you change the total supply
@asaj @marekolszewski comments?
* @notice Setter for the decimals of the token. | ||
* @param decimals The decimals to set. | ||
*/ | ||
function setDecimals(uint8 decimals) 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.
Same here... you can't change decimal at half of the lifecycle
* @notice Setter for the name of the token. | ||
* @param name The name to set. | ||
*/ | ||
function setName(string memory name) 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.
What about changing name
or symbol
during the lifecycle?
@asaj @marekolszewski comments?
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.
@BatiGencho where's 1597 implemented??
@@ -121,23 +124,19 @@ contract SortedOracles is ISortedOracles, Ownable, Initializable { | |||
/** | |||
* @notice Updates an oracle value and the median. | |||
* @param token The address of the token for which the Celo Gold exchange rate is being reported. | |||
* @param numerator The amount of tokens equal to `denominator` Celo Gold. | |||
* @param denominator The amount of Celo Gold equal to `numerator` tokens. | |||
* @param value The amount of tokens equal to Celo Gold represented as a FixidityLib fraction, premultiplied with the denominator |
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 idea of #1365 is not to premultiply with denominator, but instead make users report rates as a fractional number (encoded as a fixidity number).
So if rate is 1
, it should be encoded as 1000000000000000000000000
and if it's 0.5
it should be 500000000000000000000000
// All oracle rates are assumed to have a denominator of 2 ^ 64. | ||
uint256 public constant DENOMINATOR = 0x10000000000000000; | ||
uint256 private constant DENOMINATOR = 0x10000000000000000; |
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.
thus, this should be removed
…nt naming fixes, EpochRewards -> few setters switched to privet, Governance -> setLastDequeue() switched to private, StableToken -> setters for name, symbol, and decimals removed
… limechain/t_1604_1597_1365 # Conflicts: # packages/protocol/contracts/common/MultiSig.sol
numerator, denominator replaced with medianValue, unit test update
@@ -82,7 +82,11 @@ contract GasPriceMinimum is Ownable, Initializable, UsingRegistry { | |||
uint256 rateNumerator; | |||
uint256 rateDenominator; | |||
(rateNumerator, rateDenominator) = sortedOracles.medianRate(tokenAddress); | |||
return (gasPriceMinimum.mul(rateNumerator).div(rateDenominator)); | |||
FixidityLib.Fraction memory ratio = FixidityLib.newFixedFraction( |
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: s/ratio/rate
@@ -20,6 +20,7 @@ contract MultiSig is Initializable { | |||
event OwnerAddition(address indexed owner); | |||
event OwnerRemoval(address indexed owner); | |||
event RequirementChange(uint256 required); | |||
event RequirementSet(uint256 required); |
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.
Where is this used?
@@ -182,7 +172,7 @@ contract SortedOracles is ISortedOracles, Ownable, Initializable { | |||
* @return The median exchange rate for `token`. | |||
*/ | |||
function medianRate(address token) external view returns (uint256, uint256) { | |||
return (rates[token].getMedianValue(), numRates(token) == 0 ? 0 : DENOMINATOR); | |||
return (rates[token].getMedianValue(), numRates(token)); |
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 feels dangerous to change the behavior here unless you're 100% certain you've made changes everywhere the output of this function is consumed
await sortedOracles.report( | ||
stableToken.address, | ||
config.stableToken.goldPrice, | ||
1, | ||
new BigNumber(config.stableToken.goldPrice / 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.
Shouldn't we multiply by 10^24? i.e. use toFixed
here?
await oracles.report(stableToken.address, numerator, denominator, lesserKey, greaterKey) | ||
await oracles.report( | ||
stableToken.address, | ||
numerator.dividedBy(denominator), |
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.
Ditto, we need to use toFixed
here
@@ -115,7 +117,9 @@ contract('SortedOracles', (accounts: string[]) => { | |||
|
|||
describe('when a report has been made', () => { | |||
beforeEach(async () => { | |||
await sortedOracles.report(aToken, 1, 1, NULL_ADDRESS, NULL_ADDRESS, { from: anOracle }) | |||
await sortedOracles.report(aToken, new BigNumber(1), NULL_ADDRESS, NULL_ADDRESS, { |
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 you want toFixed(1)
here
@@ -128,7 +132,7 @@ contract('SortedOracles', (accounts: string[]) => { | |||
for (let i = 7; i > 3; i--) { | |||
const anotherOracle = accounts[i] | |||
await sortedOracles.addOracle(aToken, anotherOracle) | |||
await sortedOracles.report(aToken, 2, 1, anOracle, NULL_ADDRESS, { | |||
await sortedOracles.report(aToken, new BigNumber(2), anOracle, NULL_ADDRESS, { |
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.
toFixed(2)
@@ -170,7 +174,7 @@ contract('SortedOracles', (accounts: string[]) => { | |||
|
|||
describe('when a report has been made', () => { | |||
beforeEach(async () => { | |||
await sortedOracles.report(aToken, 10, 1, NULL_ADDRESS, NULL_ADDRESS, { | |||
await sortedOracles.report(aToken, new BigNumber(10), NULL_ADDRESS, NULL_ADDRESS, { |
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.
toFixed(10)
} | ||
|
||
const numerator = 10 | ||
const numerator = 5 |
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.
No need to define these as numerator and denominator now, you can just use a single "rate"
@@ -178,13 +179,17 @@ contract('StableToken', (accounts: string[]) => { | |||
beforeEach(async () => { | |||
await stableToken.setInflationParameters(inflationRate, SECONDS_IN_A_WEEK) | |||
await timeTravel(SECONDS_IN_A_WEEK, web3) | |||
await timeTravel(EighteenMonthsInSeconds, web3) |
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: Consider time traveling the eighteen months before the wek
…rate.ts the median rate is multiplied by 10^24 (toFixed), sortedoracles.ts (unittests) numerator / denomerator replaced with rate
sortedoracles unit tests small assertion correction
@@ -79,13 +79,10 @@ contract GasPriceMinimum is Ownable, Initializable, UsingRegistry { | |||
ISortedOracles sortedOracles = ISortedOracles( | |||
registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID) | |||
); | |||
uint256 rateNumerator; | |||
uint256 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.
nit: prefer rateNumerator
@@ -135,7 +136,7 @@ module.exports = async (callback: (error?: any) => number) => { | |||
// Report it | |||
await oracles.report( | |||
stableToken.address, | |||
numerator.dividedBy(denominator), | |||
toFixed(new BigNumber(numerator).dividedBy(new BigNumber(denominator))), |
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.
No need to make these bignumbers, you should be able to do toFixed(numerator / denominator)
@@ -416,7 +416,7 @@ contract('EpochRewards', (accounts: string[]) => { | |||
}) | |||
|
|||
it('should return one', async () => { | |||
assertEqualBN(await epochRewards.getRewardsMultiplier(), toFixed(1)) | |||
assertEqualBN(await epochRewards.getRewardsMultiplier(), toFixed(new BigNumber(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.
ditto, toFixed(1)
@@ -117,7 +117,7 @@ contract('SortedOracles', (accounts: string[]) => { | |||
|
|||
describe('when a report has been made', () => { | |||
beforeEach(async () => { | |||
await sortedOracles.report(aToken, new BigNumber(1), NULL_ADDRESS, NULL_ADDRESS, { | |||
await sortedOracles.report(aToken, toFixed(new BigNumber(1)), NULL_ADDRESS, NULL_ADDRESS, { |
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.
ditto
@@ -132,7 +132,7 @@ contract('SortedOracles', (accounts: string[]) => { | |||
for (let i = 7; i > 3; i--) { | |||
const anotherOracle = accounts[i] | |||
await sortedOracles.addOracle(aToken, anotherOracle) | |||
await sortedOracles.report(aToken, new BigNumber(2), anOracle, NULL_ADDRESS, { | |||
await sortedOracles.report(aToken, toFixed(new BigNumber(2)), anOracle, NULL_ADDRESS, { |
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.
ditto
@@ -174,7 +174,7 @@ contract('SortedOracles', (accounts: string[]) => { | |||
|
|||
describe('when a report has been made', () => { | |||
beforeEach(async () => { | |||
await sortedOracles.report(aToken, new BigNumber(10), NULL_ADDRESS, NULL_ADDRESS, { | |||
await sortedOracles.report(aToken, toFixed(new BigNumber(10)), NULL_ADDRESS, NULL_ADDRESS, { |
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.
ditto
const numerator = 5 | ||
const denominator = 1 | ||
const expectedMedianRate = expectedMedianRateFromGiven(numerator, denominator) | ||
const givenMedianRate = toFixed(new BigNumber(5).dividedBy(new BigNumber(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.
ditto, toFixed(5)
assertEqualBN(actualMedianRate, expectedMedianRate) | ||
assertEqualBN(numberOfRates.toNumber(), 1) | ||
assertEqualBN(actualMedianRate, givenMedianRate) | ||
assertEqualBN(numberOfRates, toFixed(new BigNumber(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.
ditto
}) | ||
|
||
describe('when there exists exactly one other report, made by this oracle', () => { | ||
const newMedianRate = 12 | ||
const newExpectedMedianRate = expectedMedianRateFromGiven(newMedianRate, denominator) | ||
const newExpectedMedianRate = toFixed(new BigNumber(12).dividedBy(new BigNumber(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.
ditto toFixed(12)
const anOracleExpectedMedianRate1 = expectedMedianRateFromGiven( | ||
anOracleMedianRate1, | ||
denominator | ||
const anOracleExpectedMedianRate1 = toFixed( |
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 these variables necessary anymore?
Closing as there are open PRs that address these issues individually. |
Description
Implementation of tickets 1604, 1597 and 1365
Related issues
Note
Regarding SortedOracles.sol, we are changing the type of values stored in the state variable r"ates" to unwrapped Fixidity fractions meaning those changes are not backwards compatible and shall remain as so onwards. The latter is to take effect on all interacting package levels.