Skip to content

Commit

Permalink
gas ops
Browse files Browse the repository at this point in the history
  • Loading branch information
daopunk committed Apr 4, 2024
1 parent 355bea6 commit e963fbe
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 47 deletions.
7 changes: 5 additions & 2 deletions script/Registry.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,18 @@ address constant MAINNET_DENOMINATED_WSTETH_USD_ORACLE = 0xCeE84f86d76bADa122621
// Oracles params
uint256 constant MAINNET_ORACLE_INTERVAL = 1 hours;

// Chainlink feeds to USD
// Chainlink price feeds to USD
address constant MAINNET_CHAINLINK_ARB_USD_FEED = 0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6;
address constant MAINNET_CHAINLINK_ETH_USD_FEED = 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612;

// Chainlink feeds to ETH
// Chainlink price feeds to ETH
address constant MAINNET_CHAINLINK_WSTETH_ETH_FEED = 0xb523AE262D20A936BC152e6023996e46FDC2A95D;
address constant MAINNET_CHAINLINK_CBETH_ETH_FEED = 0xa668682974E3f121185a3cD94f00322beC674275;
address constant MAINNET_CHAINLINK_RETH_ETH_FEED = 0xD6aB2298946840262FcC278fF31516D39fF611eF;

// Chainlink sequencer feed for Arbitrum One
address constant MAINNET_CHAINLINK_SEQUENCER_FEED = 0xFdB631F5EE196F0ed6FAa767959853A9F217697D;

address constant ETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
address constant ARB = 0x912CE59144191C1204E64559FE8253a0e49E6548;
address constant ETH_ARB_POOL = 0xe51635ae8136aBAc44906A8f230C2D235E9c195F;
Expand Down
33 changes: 17 additions & 16 deletions src/contracts/oracles/CamelotRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ import {IDataStorageOperator} from '@algebra-core/interfaces/IDataStorageOperato
import {DataStorageLibrary} from '@algebra-periphery/libraries/DataStorageLibrary.sol';

contract CamelotRelayer {
int256 public immutable MULTIPLIER;
uint32 public immutable QUOTE_PERIOD;
uint128 public immutable BASE_AMOUNT;

// --- Registry ---
address public algebraPool;
address public baseToken;
address public quoteToken;

// --- Data ---
string public symbol;

uint128 public baseAmount;
int256 public multiplier;
uint32 public quotePeriod;

constructor(address _algebraV3Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) {
algebraPool = IAlgebraFactory(_algebraV3Factory).poolByPair(_baseToken, _quoteToken);
require(algebraPool != address(0), 'AlgebraRelayer_InvalidPool');
Expand All @@ -35,22 +36,22 @@ contract CamelotRelayer {
quoteToken = _token0;
}

baseAmount = uint128(10 ** IERC20Metadata(_baseToken).decimals());
multiplier = int256(18) - int256(uint256(IERC20Metadata(_quoteToken).decimals()));
quotePeriod = _quotePeriod;
BASE_AMOUNT = uint128(10 ** IERC20Metadata(_baseToken).decimals());
MULTIPLIER = int256(18) - int256(uint256(IERC20Metadata(_quoteToken).decimals()));
QUOTE_PERIOD = _quotePeriod;

symbol = string(abi.encodePacked(IERC20Metadata(_baseToken).symbol(), ' / ', IERC20Metadata(_quoteToken).symbol()));
}

function getResultWithValidity() external view returns (uint256 _result, bool _validity) {
// TODO: add catch if the pool doesn't have enough history - return false

// Consult the query with a TWAP period of quotePeriod
int24 _arithmeticMeanTick = DataStorageLibrary.consult(algebraPool, quotePeriod);
// Consult the query with a TWAP period of QUOTE_PERIOD
int24 _arithmeticMeanTick = DataStorageLibrary.consult(algebraPool, QUOTE_PERIOD);
// Calculate the quote amount
uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({
tick: _arithmeticMeanTick,
baseAmount: baseAmount,
baseAmount: BASE_AMOUNT,
baseToken: baseToken,
quoteToken: quoteToken
});
Expand All @@ -61,23 +62,23 @@ contract CamelotRelayer {

function read() external view returns (uint256 _result) {
// This call may revert with 'OLD!' if the pool doesn't have enough cardinality or initialized history
int24 _arithmeticMeanTick = DataStorageLibrary.consult(algebraPool, quotePeriod);
int24 _arithmeticMeanTick = DataStorageLibrary.consult(algebraPool, QUOTE_PERIOD);
uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({
tick: _arithmeticMeanTick,
baseAmount: baseAmount,
baseAmount: BASE_AMOUNT,
baseToken: baseToken,
quoteToken: quoteToken
});
_result = _parseResult(_quoteAmount);
}

function _parseResult(uint256 _quoteResult) internal view returns (uint256 _result) {
if (multiplier == 0) {
if (MULTIPLIER == 0) {
return _quoteResult;
} else if (multiplier > 0) {
return _quoteResult * (10 ** uint256(multiplier));
} else if (MULTIPLIER > 0) {
return _quoteResult * (10 ** uint256(MULTIPLIER));
} else {
return _quoteResult / (10 ** _abs(multiplier));
return _quoteResult / (10 ** _abs(MULTIPLIER));
}
}

Expand Down
37 changes: 17 additions & 20 deletions src/contracts/oracles/ChainlinkRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ import {IChainlinkOracle} from '@interfaces/oracles/IChainlinkOracle.sol';
/**
* @title ChainlinkRelayer
* @notice This contracts transforms a Chainlink price feed into a standard IBaseOracle feed
* It also verifies that the reading is new enough, compared to a staleThreshold
* It also verifies that the reading is new enough, compared to a STALE_THRESHOLD
*/
contract ChainlinkRelayer {
// --- Registry ---
uint256 public immutable STALE_THRESHOLD;
int256 public immutable MULTIPLIER;

IChainlinkOracle public chainlinkFeed;
// --- Registry ---
IChainlinkOracle public CHAINLINK_FEED;

// --- Data ---

string public symbol;
int256 public multiplier;
uint256 public staleThreshold;

// --- Init ---

/**
* @param _aggregator The address of the Chainlink aggregator
Expand All @@ -29,16 +26,16 @@ contract ChainlinkRelayer {
require(_aggregator != address(0), 'NullAggregator');
require(_staleThreshold != 0, 'NullStaleThreshold');

staleThreshold = _staleThreshold;
chainlinkFeed = IChainlinkOracle(_aggregator);
STALE_THRESHOLD = _staleThreshold;
CHAINLINK_FEED = IChainlinkOracle(_aggregator);

multiplier = int256(18) - int256(uint256(chainlinkFeed.decimals()));
symbol = chainlinkFeed.description();
MULTIPLIER = int256(18) - int256(uint256(CHAINLINK_FEED.decimals()));
symbol = CHAINLINK_FEED.description();
}

function getResultWithValidity() external view returns (uint256 _result, bool _validity) {
// Fetch values from Chainlink
(, int256 _aggregatorResult,, uint256 _aggregatorTimestamp,) = chainlinkFeed.latestRoundData();
(, int256 _aggregatorResult,, uint256 _aggregatorTimestamp,) = CHAINLINK_FEED.latestRoundData();

// Parse the quote into 18 decimals format
_result = _parseResult(_aggregatorResult);
Expand All @@ -49,7 +46,7 @@ contract ChainlinkRelayer {

function read() external view returns (uint256 _result) {
// Fetch values from Chainlink
(, int256 _aggregatorResult,, uint256 _aggregatorTimestamp,) = chainlinkFeed.latestRoundData();
(, int256 _aggregatorResult,, uint256 _aggregatorTimestamp,) = CHAINLINK_FEED.latestRoundData();

// Revert if price is invalid
require(_aggregatorResult != 0 || _isValidFeed(_aggregatorTimestamp), 'InvalidPriceFeed');
Expand All @@ -60,20 +57,20 @@ contract ChainlinkRelayer {

/// @notice Parses the result from the aggregator into 18 decimals format
function _parseResult(int256 _chainlinkResult) internal view returns (uint256 _result) {
if (multiplier == 0) {
if (MULTIPLIER == 0) {
return uint256(_chainlinkResult);
} else if (multiplier > 0) {
return uint256(_chainlinkResult) * (10 ** uint256(multiplier));
} else if (MULTIPLIER > 0) {
return uint256(_chainlinkResult) * (10 ** uint256(MULTIPLIER));
} else {
return uint256(_chainlinkResult) / (10 ** _abs(multiplier));
return uint256(_chainlinkResult) / (10 ** _abs(MULTIPLIER));
}
}

/// @notice Checks if the feed is valid, considering the staleThreshold and the feed timestamp
/// @notice Checks if the feed is valid, considering the STALE_THRESHOLD and the feed timestamp
function _isValidFeed(uint256 _feedTimestamp) internal view returns (bool _valid) {
uint256 _now = block.timestamp;
if (_feedTimestamp > _now) return false;
return _now - _feedTimestamp <= staleThreshold;
return _now - _feedTimestamp <= STALE_THRESHOLD;
}

// @notice Return the absolute value of a signed integer as an unsigned integer
Expand Down
15 changes: 6 additions & 9 deletions src/contracts/oracles/DenominatedOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,28 @@ import {Math, WAD} from '@libraries/Math.sol';
contract DenominatedOracle {
using Math for uint256;

// --- Registry ---
bool public immutable INVERTED;

// --- Registry ---
IBaseOracle public priceSource;
IBaseOracle public denominationPriceSource;

// --- Data ---

string public symbol;
bool public inverted;

// --- Init ---

/**
*
* @param _priceSource Address of the base price source that is used to calculate the price
* @param _denominationPriceSource Address of the denomination price source that is used to calculate price
* @param _inverted Flag that indicates whether the price source quote should be inverted or not
* @param _inverted Flag that indicates whether the price source quote should be INVERTED or not
*/
constructor(IBaseOracle _priceSource, IBaseOracle _denominationPriceSource, bool _inverted) {
require(address(_priceSource) != address(0), 'Denom_NullPriceSource');
require(address(_denominationPriceSource) != address(0), 'Denom_NullPriceSource');

priceSource = _priceSource;
denominationPriceSource = _denominationPriceSource;
inverted = _inverted;
INVERTED = _inverted;

if (_inverted) {
symbol = string(abi.encodePacked('(', priceSource.symbol(), ')^-1 / (', denominationPriceSource.symbol(), ')'));
Expand All @@ -49,7 +46,7 @@ contract DenominatedOracle {
(uint256 _denominationPriceSourceValue, bool _denominationPriceSourceValidity) =
denominationPriceSource.getResultWithValidity();

if (inverted) {
if (INVERTED) {
if (_priceSourceValue == 0) return (0, false);
_priceSourceValue = WAD.wdiv(_priceSourceValue);
}
Expand All @@ -62,7 +59,7 @@ contract DenominatedOracle {
uint256 _priceSourceValue = priceSource.read();
uint256 _denominationPriceSourceValue = denominationPriceSource.read();

if (inverted) {
if (INVERTED) {
if (_priceSourceValue == 0) revert('InvalidPriceFeed');
_priceSourceValue = WAD.wdiv(_priceSourceValue);
}
Expand Down
26 changes: 26 additions & 0 deletions src/contracts/utils/DataConsumerSequencerCheck.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.6;

import {IChainlinkOracle} from '@interfaces/oracles/IChainlinkOracle.sol';

contract DataConsumerSequencerCheck {
// --- Registry ---
IChainlinkOracle public immutable SEQUENCER_UPTIME_FEED;

// --- Data ---
uint256 public immutable GRACE_PERIOD;

/**
* @param _aggregator The address of the Chainlink aggregator
* @param _gracePeriod The threshold before accepting answers after an outage
*/
constructor(address _aggregator, uint256 _gracePeriod) {
require(_aggregator != address(0), 'NullAggregator');
require(_gracePeriod != 0, 'NullGracePeriod');

SEQUENCER_UPTIME_FEED = IChainlinkOracle(_aggregator);
GRACE_PERIOD = _gracePeriod;
}

function getChainlinkDataFeedLatestAnswer() external view returns (int256) {}
}

0 comments on commit e963fbe

Please sign in to comment.