diff --git a/contracts/compound-rate-keeper/AbstractCompoundRateKeeper.sol b/contracts/compound-rate-keeper/AbstractCompoundRateKeeper.sol index d2917d1d..ecd5a399 100644 --- a/contracts/compound-rate-keeper/AbstractCompoundRateKeeper.sol +++ b/contracts/compound-rate-keeper/AbstractCompoundRateKeeper.sol @@ -169,6 +169,37 @@ abstract contract AbstractCompoundRateKeeper is ICompoundRateKeeper, Initializab _changeCapitalizationPeriod(capitalizationPeriod_); } + /** + * @notice Implementation of exponentiation by squaring + * @param x_ basis, decimal number + * @param n_ power of x + * @param b_ precision of x + * @return z_ result + */ + function _rpow(uint256 x_, uint256 n_, uint256 b_) internal pure returns (uint256 z_) { + if (x_ == 0) { + if (n_ == 0) { + z_ = b_; + } else { + z_ = 0; + } + } else { + if (n_ % 2 == 0) { + z_ = b_; + } else { + z_ = x_; + } + uint256 half = b_ / 2; // for rounding + + for (uint256 i = n_ / 2; i >= 1; i = i / 2) { + x_ = (x_ * x_ + half) / b_; + if (i % 2 == 1) { + z_ = (z_ * x_ + half) / b_; + } + } + } + } + /** * @notice The private function to update the compound rate */ @@ -207,28 +238,4 @@ abstract contract AbstractCompoundRateKeeper is ICompoundRateKeeper, Initializab function _getMaxRate() private pure returns (uint256) { return type(uint128).max * PRECISION; } - - function _rpow(uint256 x_, uint256 n_, uint256 b_) private pure returns (uint256 z_) { - if (x_ == 0) { - if (n_ == 0) { - z_ = b_; - } else { - z_ = 0; - } - } else { - if (n_ % 2 == 0) { - z_ = b_; - } else { - z_ = x_; - } - uint256 half = b_ / 2; // for rounding - - for (uint256 i = n_ / 2; i >= 1; i = i / 2) { - x_ = (x_ * x_ + half) / b_; - if (i % 2 == 1) { - z_ = (z_ * x_ + half) / b_; - } - } - } - } } diff --git a/contracts/mock/compound-rate-keeper/CompoundRateKeeperMock.sol b/contracts/mock/compound-rate-keeper/CompoundRateKeeperMock.sol index 391d6d01..575cb547 100644 --- a/contracts/mock/compound-rate-keeper/CompoundRateKeeperMock.sol +++ b/contracts/mock/compound-rate-keeper/CompoundRateKeeperMock.sol @@ -15,4 +15,8 @@ contract CompoundRateKeeperMock is OwnableCompoundRateKeeper { _setCapitalizationRate(capitalizationRate_); _setCapitalizationPeriod(capitalizationPeriod_); } + + function rpow(uint256 x_, uint256 n_, uint256 b_) external pure returns (uint256 z_) { + return _rpow(x_, n_, b_); + } } diff --git a/test/compound-rate-keeper/CompoundRateKeeper.test.ts b/test/compound-rate-keeper/CompoundRateKeeper.test.ts index ab7cac68..e645b4a6 100644 --- a/test/compound-rate-keeper/CompoundRateKeeper.test.ts +++ b/test/compound-rate-keeper/CompoundRateKeeper.test.ts @@ -261,5 +261,10 @@ describe("CompoundRateKeeper", () => { it("check max timestamp for 1000%", async () => { await checkByParams(11); }); + + it("check correct work of rpow function", async () => { + expect(await keeper.rpow(0, 0, 5)).to.equal(5); + expect(await keeper.rpow(0, 1, 5)).to.equal(0); + }); }); });