The _capRates
function calculates the max allowed rate as
exp
is based on the block difference,
So the exp
can be assumed to be the difference in block numbers for simplicity. The issue is that the expression given above grows very fast with time, since it is an exponential function. For large exp
, there can be an overflow.
The code implements the same formula in the following way, in multiple places in the code.
The first line above shows the calculation of a temporary exponentiated term. This will later be multiplied with the last stored ratio. The code also operates in 128X128 fixed point arithmetic, so the above is converted to 128X128 as well. But 128X128 numbers can hold far smaller quantities, so an overflow check is needed before this conversion.
The second line in the snippet above does that. If the intermediate result is above a certain value, it is not converted into 128X128, and the calculation is skipped. This prevents the overflow, and is thus overflow protection
.
However, this is missing in the case when rates decrease in the _capRates
function. For decreasing rates, the same exponentiated term is calculated, but this is ultimately then divided from the last rate.
As seen above, the exponentiated term is converted to 128X128, but there is no check if this is possible! This might lead to an overflow, and the well might break.
If a long time has passed since the last update, the capExponent
term will start to grow. So the propensity of this problem starts to grow as well with time.
For some rough numbers, we assume gamma = 1
, so the code allows a 100% change per block effectively. Then I ran the test below to find the limits of this conversion.
We basically exponentiate the variable TWO
and convert it to 128x128. For one case, TWO is 2, and for the other case its 1.5.
From running these tests, I saw that exponentiating 2 overflows when converting to 128X128 when the power is 126. Exponentiating 1.5 overflows when the power is 217.
In other words, if the ratio decreases due to a swap, and a user has not touched that well for 127 blocks, if the gamma rate was 100% change per block, the well will stop working since the exponentiated value will overflow.
Similarly for a gamma of 50% per block, the well overflows after leaving untouched for 218 blocks.
Whatever the gamma may be, the well will break after a certain number of blocks of unuse.
In all other cases in the code, there is either overflow protection like shown above, or the exponentiation is on a decaying function (1 - x)^n, which will never overflow. This is the only case where the exponentiation is on a growing function without protection.
If a swap reduces the rate of the well, and then the well is left untouched for a long time, the well will become unusable. This is because when it will be finally updated, it will have a tendency to overflow since the exponentiation is high and there is no overflow protection.
Foundry
Add the same overflow protection. If the number cannot be converted to 128X128, ratio limit should be 0.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.