Skip to content

Commit

Permalink
Merge branch 'release/v4.0.0-beta.7'
Browse files Browse the repository at this point in the history
  • Loading branch information
TylerEther committed Jul 4, 2023
2 parents c5b8a8c + ecd9118 commit a2d43ba
Show file tree
Hide file tree
Showing 17 changed files with 772 additions and 168 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Adrastia Core

[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
![5969 out of 5969 tests passing](https://img.shields.io/badge/tests-5969/5969%20passing-brightgreen.svg?style=flat-square)
![6007 out of 6007 tests passing](https://img.shields.io/badge/tests-6007/6007%20passing-brightgreen.svg?style=flat-square)
![test-coverage >99%](https://img.shields.io/badge/test%20coverage-%3E99%25-brightgreen.svg?style=flat-square)

Adrastia Core is a set of Solidity smart contracts for building EVM oracle solutions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ contract AlgebraLiquidityAccumulator is LiquidityAccumulator {
return _liquidityDecimals;
}

function computeAddress(address token, address _quoteToken) internal view returns (address pool) {
function computeAddress(address token, address _quoteToken) internal view virtual returns (address pool) {
if (token > _quoteToken) {
// Sort tokens so that the first token is the one with the lower address
(token, _quoteToken) = (_quoteToken, token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ contract AlgebraPriceAccumulator is PriceAccumulator {
address quoteToken_,
uint160 sqrtPriceX96,
uint128 tokenAmount
) internal pure returns (uint256 price) {
) internal pure virtual returns (uint256 price) {
// Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself
if (sqrtPriceX96 <= type(uint128).max) {
uint256 ratioX192 = uint256(sqrtPriceX96) * sqrtPriceX96;
Expand All @@ -106,7 +106,7 @@ contract AlgebraPriceAccumulator is PriceAccumulator {
}
}

function calculatePrice(address token) internal view returns (bool hasLiquidity, uint256 price) {
function calculatePrice(address token) internal view virtual returns (bool hasLiquidity, uint256 price) {
uint128 wholeTokenAmount = computeWholeUnitAmount(token);

address pool = computeAddress(token, quoteToken);
Expand Down Expand Up @@ -147,7 +147,7 @@ contract AlgebraPriceAccumulator is PriceAccumulator {
return _price.toUint112();
}

function computeAddress(address token, address _quoteToken) internal view returns (address pool) {
function computeAddress(address token, address _quoteToken) internal view virtual returns (address pool) {
if (token > _quoteToken) {
// Sort tokens so that the first token is the one with the lower address
(token, _quoteToken) = (_quoteToken, token);
Expand All @@ -164,7 +164,7 @@ contract AlgebraPriceAccumulator is PriceAccumulator {
);
}

function computeWholeUnitAmount(address token) internal view returns (uint128 amount) {
function computeWholeUnitAmount(address token) internal view virtual returns (uint128 amount) {
amount = uint128(10) ** IERC20Metadata(token).decimals();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ interface IVault {
interface IBasePool {
function getPoolId() external view returns (bytes32);

function inRecoveryMode() external view returns (bool);
function getPausedState()
external
view
returns (bool paused, uint256 pauseWindowEndTime, uint256 bufferPeriodEndTime);

function paused() external view returns (bool);
}

interface ILinearPool {
Expand Down Expand Up @@ -45,7 +50,7 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {

error TokenNotFound(address token);

error PoolInRecoveryMode(address pool);
error PoolIsPaused(address pool);

constructor(
IAveragingStrategy averagingStrategy_,
Expand Down Expand Up @@ -94,7 +99,7 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {
return false;
}

if (inRecoveryMode(poolAddress)) {
if (isPaused(poolAddress)) {
// The pool is in recovery mode
return false;
}
Expand All @@ -108,15 +113,15 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {

if (quoteTokenIsWrapped) {
// Check if the quote token linear pool is in recovery mode
if (inRecoveryMode(tokens[quoteTokenIndex])) {
if (isPaused(tokens[quoteTokenIndex])) {
// The quote token linear pool is in recovery mode
return false;
}
}

if (tokenIsWrapped) {
// Check if the token linear pool is in recovery mode
if (inRecoveryMode(tokens[tokenIndex])) {
if (isPaused(tokens[tokenIndex])) {
// The token linear pool is in recovery mode
return false;
}
Expand All @@ -133,19 +138,26 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {
return _liquidityDecimals;
}

function inRecoveryMode(address pool) internal view returns (bool) {
(bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(IBasePool.inRecoveryMode.selector));
function isPaused(address pool) internal view virtual returns (bool) {
(bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(IBasePool.getPausedState.selector));
if (success && data.length == 96) {
(bool paused, , ) = abi.decode(data, (bool, uint256, uint256));

return paused;
}

(success, data) = pool.staticcall(abi.encodeWithSelector(IBasePool.paused.selector));
if (success && data.length == 32) {
return abi.decode(data, (bool));
}

return false; // Doesn't implement the function
return false; // Doesn't implement any of the pause functions
}

function findTokenIndex(
address[] memory tokens,
address token
) internal view returns (bool, uint256, bool, uint256) {
) internal view virtual returns (bool, uint256, bool, uint256) {
uint256 length = tokens.length;
for (uint256 i = 0; i < length; ++i) {
if (tokens[i] == token) {
Expand Down Expand Up @@ -173,8 +185,8 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {
bytes memory data
) internal view virtual override returns (uint112 tokenLiquidity, uint112 quoteTokenLiquidity) {
// Ensure that the pool is not in recovery mode
if (inRecoveryMode(poolAddress)) {
revert PoolInRecoveryMode(poolAddress);
if (isPaused(poolAddress)) {
revert PoolIsPaused(poolAddress);
}

address token = abi.decode(data, (address));
Expand All @@ -197,8 +209,8 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {
// Token balance is for the wrapped token, get the balance of the underlying token

// Ensure that the token linear pool is not in recovery mode
if (inRecoveryMode(tokens[tokenIndex])) {
revert PoolInRecoveryMode(tokens[tokenIndex]);
if (isPaused(tokens[tokenIndex])) {
revert PoolIsPaused(tokens[tokenIndex]);
}

// Get the token wrapper pool ID
Expand All @@ -220,8 +232,8 @@ contract BalancerV2LiquidityAccumulator is LiquidityAccumulator {
// Token balance is for the wrapped token, get the balance of the underlying token

// Ensure that the quote token linear pool is not in recovery mode
if (inRecoveryMode(tokens[quoteTokenIndex])) {
revert PoolInRecoveryMode(tokens[quoteTokenIndex]);
if (isPaused(tokens[quoteTokenIndex])) {
revert PoolIsPaused(tokens[quoteTokenIndex]);
}

// Get the balances of the wrapper pool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ interface IBasePool {
*/
function getScalingFactors() external view returns (uint256[] memory);

function inRecoveryMode() external view returns (bool);
function getPausedState()
external
view
returns (bool paused, uint256 pauseWindowEndTime, uint256 bufferPeriodEndTime);

function paused() external view returns (bool);
}

interface ILinearPool {
Expand Down Expand Up @@ -65,7 +70,7 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {

error TokenNotFound(address token);

error PoolInRecoveryMode(address pool);
error PoolIsPaused(address pool);
error AmplificationParameterUpdating();

constructor(
Expand Down Expand Up @@ -119,7 +124,7 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
return false;
}

if (inRecoveryMode(poolAddress)) {
if (isPaused(poolAddress)) {
// The pool is in recovery mode
return false;
}
Expand All @@ -133,15 +138,15 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {

if (quoteTokenIsWrapped) {
// Check if the quote token linear pool is in recovery mode
if (inRecoveryMode(tokens[quoteTokenIndex])) {
if (isPaused(tokens[quoteTokenIndex])) {
// The quote token linear pool is in recovery mode
return false;
}
}

if (tokenIsWrapped) {
// Check if the token linear pool is in recovery mode
if (inRecoveryMode(tokens[tokenIndex])) {
if (isPaused(tokens[tokenIndex])) {
// The token linear pool is in recovery mode
return false;
}
Expand All @@ -158,8 +163,15 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
return super.canUpdate(data);
}

function inRecoveryMode(address pool) internal view returns (bool) {
(bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(IBasePool.inRecoveryMode.selector));
function isPaused(address pool) internal view virtual returns (bool) {
(bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(IBasePool.getPausedState.selector));
if (success && data.length == 96) {
(bool paused, , ) = abi.decode(data, (bool, uint256, uint256));

return paused;
}

(success, data) = pool.staticcall(abi.encodeWithSelector(IBasePool.paused.selector));
if (success && data.length == 32) {
return abi.decode(data, (bool));
}
Expand All @@ -170,7 +182,7 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
function findTokenIndex(
address[] memory tokens,
address token
) internal view returns (bool, uint256, bool, uint256) {
) internal view virtual returns (bool, uint256, bool, uint256) {
uint256 length = tokens.length;
for (uint256 i = 0; i < length; ++i) {
if (tokens[i] == token) {
Expand Down Expand Up @@ -203,8 +215,8 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
*/
function fetchPrice(bytes memory data) internal view virtual override returns (uint112 price) {
// Ensure that the pool is not in recovery mode
if (inRecoveryMode(poolAddress)) {
revert PoolInRecoveryMode(poolAddress);
if (isPaused(poolAddress)) {
revert PoolIsPaused(poolAddress);
}

address token = abi.decode(data, (address));
Expand All @@ -227,8 +239,8 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
// The token is inside a linear pool, so we need to convert the amount of the token to the amount of BPT

// Ensure that the token linear pool is not in recovery mode
if (inRecoveryMode(tokens[tokenIndex])) {
revert PoolInRecoveryMode(tokens[tokenIndex]);
if (isPaused(tokens[tokenIndex])) {
revert PoolIsPaused(tokens[tokenIndex]);
}

ILinearPool linearPool = ILinearPool(tokens[tokenIndex]);
Expand Down Expand Up @@ -272,8 +284,8 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
// quote token

// Ensure that the quote token linear pool is not in recovery mode
if (inRecoveryMode(tokens[quoteTokenIndex])) {
revert PoolInRecoveryMode(tokens[quoteTokenIndex]);
if (isPaused(tokens[quoteTokenIndex])) {
revert PoolIsPaused(tokens[quoteTokenIndex]);
}

ILinearPool linearPool = ILinearPool(tokens[quoteTokenIndex]);
Expand All @@ -286,23 +298,23 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
if (price == 0) return 1;
}

function computeWholeUnitAmount(address token) internal view returns (uint256 amount) {
function computeWholeUnitAmount(address token) internal view virtual returns (uint256 amount) {
amount = uint256(10) ** IERC20Metadata(token).decimals();
}

/**
* @dev Reverses the `scalingFactor` applied to `amount`, resulting in a smaller or equal value depending on
* whether it needed scaling or not. The result is rounded down.
*/
function _downscaleDown(uint256 amount, uint256 scalingFactor) internal pure returns (uint256) {
function _downscaleDown(uint256 amount, uint256 scalingFactor) internal pure virtual returns (uint256) {
return FixedPoint.divDown(amount, scalingFactor);
}

/**
* @dev Applies `scalingFactor` to `amount`, resulting in a larger or equal value depending on whether it needed
* scaling or not.
*/
function _upscale(uint256 amount, uint256 scalingFactor) internal pure returns (uint256) {
function _upscale(uint256 amount, uint256 scalingFactor) internal pure virtual returns (uint256) {
// Upscale rounding wouldn't necessarily always go in the same direction: in a swap for example the balance of
// token in should be rounded up, and that of token out rounded down. This is the only place where we round in
// the same direction for all amounts, as the impact of this rounding is expected to be minimal (and there's no
Expand All @@ -314,7 +326,11 @@ contract BalancerV2StablePriceAccumulator is PriceAccumulator {
* @dev Same as `_upscale`, but for an entire array. This function does not return anything, but instead *mutates*
* the `amounts` array.
*/
function _upscaleArray(uint256[] memory amounts, uint256[] memory scalingFactors, uint256 numTokens) internal pure {
function _upscaleArray(
uint256[] memory amounts,
uint256[] memory scalingFactors,
uint256 numTokens
) internal pure virtual {
for (uint256 i = 0; i < numTokens; ++i) {
amounts[i] = FixedPoint.mulDown(amounts[i], scalingFactors[i]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ interface IVault {
}

interface IBasePool {
function inRecoveryMode() external view returns (bool);
function getPausedState()
external
view
returns (bool paused, uint256 pauseWindowEndTime, uint256 bufferPeriodEndTime);

function paused() external view returns (bool);
}

interface IWeightedPool {
Expand All @@ -37,7 +42,7 @@ contract BalancerV2WeightedPriceAccumulator is PriceAccumulator {

error TokenNotFound(address token);

error PoolInRecoveryMode(address pool);
error PoolIsPaused(address pool);

constructor(
IAveragingStrategy averagingStrategy_,
Expand Down Expand Up @@ -71,7 +76,7 @@ contract BalancerV2WeightedPriceAccumulator is PriceAccumulator {
return false;
}

if (inRecoveryMode(poolAddress)) {
if (isPaused(poolAddress)) {
// The pool is in recovery mode
return false;
}
Expand All @@ -91,16 +96,23 @@ contract BalancerV2WeightedPriceAccumulator is PriceAccumulator {
return super.canUpdate(data);
}

function inRecoveryMode(address pool) internal view returns (bool) {
(bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(IBasePool.inRecoveryMode.selector));
function isPaused(address pool) internal view virtual returns (bool) {
(bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(IBasePool.getPausedState.selector));
if (success && data.length == 96) {
(bool paused, , ) = abi.decode(data, (bool, uint256, uint256));

return paused;
}

(success, data) = pool.staticcall(abi.encodeWithSelector(IBasePool.paused.selector));
if (success && data.length == 32) {
return abi.decode(data, (bool));
}

return false; // Doesn't implement the function
}

function findTokenIndex(address[] memory tokens, address token) internal pure returns (uint256) {
function findTokenIndex(address[] memory tokens, address token) internal pure virtual returns (uint256) {
uint256 length = tokens.length;
for (uint256 i = 0; i < length; ++i) {
if (tokens[i] == token) {
Expand All @@ -120,8 +132,8 @@ contract BalancerV2WeightedPriceAccumulator is PriceAccumulator {
*/
function fetchPrice(bytes memory data) internal view virtual override returns (uint112 price) {
// Ensure that the pool is not in recovery mode
if (inRecoveryMode(poolAddress)) {
revert PoolInRecoveryMode(poolAddress);
if (isPaused(poolAddress)) {
revert PoolIsPaused(poolAddress);
}

address token = abi.decode(data, (address));
Expand Down Expand Up @@ -153,7 +165,7 @@ contract BalancerV2WeightedPriceAccumulator is PriceAccumulator {
if (price == 0) return 1;
}

function computeWholeUnitAmount(address token) internal view returns (uint256 amount) {
function computeWholeUnitAmount(address token) internal view virtual returns (uint256 amount) {
amount = uint256(10) ** IERC20Metadata(token).decimals();
}
}
Loading

0 comments on commit a2d43ba

Please sign in to comment.