From cc6ab66f3d719d030fa43028bb55b06d0e6fa62b Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 17:18:59 -0800 Subject: [PATCH 01/10] Add ePendle and Pendle address, scaffold UniswapV2 oracle factory --- script/Common.s.sol | 2 + script/DeployOracle.s.sol | 50 ++++++++++- script/Registry.s.sol | 3 +- script/predeployment/DeployRelayers.s.sol | 14 +-- .../factories/UniswapV2RelayerChild.sol | 15 ++++ .../factories/UniswapV2RelayerFactory.sol | 33 +++++++ src/contracts/oracles/UniswapV2Relayer.sol | 90 +++++++++++++++++++ test/e2e/SystemOracle.s.sol | 6 +- 8 files changed, 200 insertions(+), 13 deletions(-) create mode 100644 src/contracts/factories/UniswapV2RelayerChild.sol create mode 100644 src/contracts/factories/UniswapV2RelayerFactory.sol create mode 100644 src/contracts/oracles/UniswapV2Relayer.sol diff --git a/script/Common.s.sol b/script/Common.s.sol index e5fef49..711fd23 100644 --- a/script/Common.s.sol +++ b/script/Common.s.sol @@ -11,10 +11,12 @@ import {CamelotRelayerFactory} from '@contracts/factories/CamelotRelayerFactory. import {ChainlinkRelayerFactory} from '@contracts/factories/ChainlinkRelayerFactory.sol'; import {DenominatedOracleFactory} from '@contracts/factories/DenominatedOracleFactory.sol'; import {IDelayedOracleFactory} from '@interfaces/factories/IDelayedOracleFactory.sol'; +// import {UniswapV2RelayerFactory} from '@contracts/factories/UniswapV2RelayerFactory.sol'; abstract contract CommonMainnet is Script { ChainlinkRelayerFactory public chainlinkRelayerFactory = ChainlinkRelayerFactory(MAINNET_CHAINLINK_RELAYER_FACTORY); CamelotRelayerFactory public camelotRelayerFactory = CamelotRelayerFactory(MAINNET_CAMELOT_RELAYER_FACTORY); + // UniswapV2RelayerFactory public camelotV2RelayerFactory = UniswapV2RelayerFactory(MAINNET_CAMELOT_V2_RELAYER_FACTORY); DenominatedOracleFactory public denominatedOracleFactory = DenominatedOracleFactory(MAINNET_DENOMINATED_ORACLE_FACTORY); IDelayedOracleFactory public delayedOracleFactory = IDelayedOracleFactory(MAINNET_DELAYED_ORACLE_FACTORY); diff --git a/script/DeployOracle.s.sol b/script/DeployOracle.s.sol index 460f7b2..58283f2 100644 --- a/script/DeployOracle.s.sol +++ b/script/DeployOracle.s.sol @@ -128,7 +128,7 @@ contract DeployCamelotOdUsdOracle is Script, CommonMainnet { vm.startBroadcast(); _odEthCamelotRelayer = camelotRelayerFactory.deployAlgebraRelayer( - MAINNET_ALGEBRA_FACTORY, MAINNET_SYSTEM_COIN, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) + MAINNET_ALGEBRA_V3_FACTORY, MAINNET_SYSTEM_COIN, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) ); _odUsdOracle = denominatedOracleFactory.deployDenominatedOracle( @@ -155,7 +155,7 @@ contract DeployCamelotOdgUsdOracle is Script, CommonMainnet { vm.startBroadcast(); _odgEthCamelotRelayer = camelotRelayerFactory.deployAlgebraRelayer( - MAINNET_ALGEBRA_FACTORY, MAINNET_PROTOCOL_TOKEN, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) + MAINNET_ALGEBRA_V3_FACTORY, MAINNET_PROTOCOL_TOKEN, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) ); _odgUsdOracle = denominatedOracleFactory.deployDenominatedOracle( @@ -167,3 +167,49 @@ contract DeployCamelotOdgUsdOracle is Script, CommonMainnet { vm.stopBroadcast(); } } + +// BROADCAST +// source .env && forge script DeployCamelotEPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY --sender $DEFAULT_KEY_PUBLIC_ADDRESS --account defaultKey + +// SIMULATE +// source .env && forge script DeployCamelotEPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --sender $DEFAULT_KEY_PUBLIC_ADDRESS + +contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { + IBaseOracle public _ePendlePendleUniswapV2Relayer; + IBaseOracle public _PendleEthOracleRelayer; + IBaseOracle public _PendleUsdOracleRelayer; + IBaseOracle public _ePendleUsdOracle; + + address public MAINNET_E_PENDLE = 0x3EaBE18eAE267D1B57f917aBa085bb5906114600; + address public MAINNET_PENDLE = 0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8; + + function run() public { + vm.startBroadcast(); + + // _ePendleEthUniswapV2Relayer = uniswapV2RelayerFactory.deployAlgebraRelayer( + // MAINNET_ALGEBRA_V2_FACTORY, MAINNET_E_PENDLE, MAINNET_PENDLE, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) + // ); + + _PendleEthOracleRelayer = camelotRelayerFactory.deployAlgebraRelayer( + MAINNET_ALGEBRA_V3_FACTORY, MAINNET_PENDLE, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) + ); + + _PendleUsdOracleRelayer = denominatedOracleFactory.deployDenominatedOracle( + _PendleEthOracleRelayer, IBaseOracle(MAINNET_CHAINLINK_L2VALIDITY_ETH_USD_RELAYER), false + ); + + // _ePendleUsdOracle = denominatedOracleFactory.deployDenominatedOracle( + // _ePendleEthUniswapV2Relayer, _PendleUsdOracleRelayer, false + // ); + + // IBaseOracle ePendleDelayedOracle = + // delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); + + _PendleUsdOracleRelayer.symbol(); + _PendleUsdOracleRelayer.getResultWithValidity(); + // _ePendleUsdOracle.getResultWithValidity(); + // ePendleDelayedOracle.getResultWithValidity(); + + vm.stopBroadcast(); + } +} diff --git a/script/Registry.s.sol b/script/Registry.s.sol index 5c4011d..d19c41d 100644 --- a/script/Registry.s.sol +++ b/script/Registry.s.sol @@ -76,7 +76,8 @@ address constant ETH_ARB_POOL = 0xe51635ae8136aBAc44906A8f230C2D235E9c195F; address constant MAINNET_CAMELOT_RELAYER_FACTORY = 0x36645830479170265A154Acb726780fdaE41A28F; address constant MAINNET_CHAINLINK_RELAYER_FACTORY = 0x06C32500489C28Bd57c551afd8311Fef20bFaBB5; address constant MAINNET_DENOMINATED_ORACLE_FACTORY = 0xBF760b23d2ef3615cec549F22b95a34DB0F8f5CD; -address constant MAINNET_ALGEBRA_FACTORY = 0x1a3c9B1d2F0529D97f2afC5136Cc23e58f1FD35B; +address constant MAINNET_ALGEBRA_V3_FACTORY = 0x1a3c9B1d2F0529D97f2afC5136Cc23e58f1FD35B; +address constant MAINNET_ALGEBRA_V2_FACTORY = 0x6EcCab422D763aC031210895C81787E87B43A652; address constant MAINNET_DELAYED_ORACLE_FACTORY = 0x9Dd63fA54dEfd8820BCAb3e3cC39aeEc1aE88098; ////////// RELAYERS ////////// diff --git a/script/predeployment/DeployRelayers.s.sol b/script/predeployment/DeployRelayers.s.sol index 208addb..72de473 100644 --- a/script/predeployment/DeployRelayers.s.sol +++ b/script/predeployment/DeployRelayers.s.sol @@ -15,12 +15,12 @@ import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; // source .env && forge script DeployODGCamelotRelayerMainnet --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployODGCamelotRelayerMainnet is CommonMainnet { - IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_FACTORY); + IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_V3_FACTORY); function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); camelotRelayerFactory.deployAlgebraRelayer( - MAINNET_ALGEBRA_FACTORY, MAINNET_PROTOCOL_TOKEN, MAINNET_WETH, uint32(MAINNET_ORACLE_DELAY) + MAINNET_ALGEBRA_V3_FACTORY, MAINNET_PROTOCOL_TOKEN, MAINNET_WETH, uint32(MAINNET_ORACLE_DELAY) ); vm.stopBroadcast(); } @@ -33,7 +33,7 @@ contract DeployODGCamelotRelayerMainnet is CommonMainnet { // source .env && forge script DeployOdgUsdRelayerMainnet --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployOdgUsdRelayerMainnet is CommonMainnet { - IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_FACTORY); + IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_V3_FACTORY); function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); @@ -53,7 +53,7 @@ contract DeployOdgUsdRelayerMainnet is CommonMainnet { // source .env && forge script DeployEthUsdChainlinkRelayerMainnet --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployEthUsdChainlinkRelayerMainnet is CommonMainnet { - IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_FACTORY); + IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_V3_FACTORY); function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); @@ -69,7 +69,7 @@ contract DeployEthUsdChainlinkRelayerMainnet is CommonMainnet { // source .env && forge script DeployRethEthChainlinkRelayerMainnet --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployRethEthChainlinkRelayerMainnet is CommonMainnet { - IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_FACTORY); + IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_V3_FACTORY); function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); @@ -92,7 +92,7 @@ contract DeployRethEthChainlinkRelayerMainnet is CommonMainnet { // source .env && forge script DeployWstethEthChainlinkRelayerMainnet --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployWstethEthChainlinkRelayerMainnet is CommonMainnet { - IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_FACTORY); + IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_V3_FACTORY); function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); @@ -140,7 +140,7 @@ contract DeployEzEthUSDPriceFeed is CommonMainnet { // source .env && forge script DeployArbUsdChainlinkRelayerMainnet --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployArbUsdChainlinkRelayerMainnet is CommonMainnet { - IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_FACTORY); + IAlgebraFactory public algebraFactory = IAlgebraFactory(MAINNET_ALGEBRA_V3_FACTORY); function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); diff --git a/src/contracts/factories/UniswapV2RelayerChild.sol b/src/contracts/factories/UniswapV2RelayerChild.sol new file mode 100644 index 0000000..9532103 --- /dev/null +++ b/src/contracts/factories/UniswapV2RelayerChild.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.7.6; + +import {UniswapV2Relayer} from '@contracts/oracles/UniswapV2Relayer.sol'; +import {FactoryChild} from '@contracts/factories/FactoryChild.sol'; + +contract UniswapV2RelayerChild is UniswapV2Relayer, FactoryChild { + // --- Init --- + constructor( + address _algebraV2Factory, + address _baseToken, + address _quoteToken, + uint32 _quotePeriod + ) UniswapV2Relayer(_algebraV2Factory, _baseToken, _quoteToken, _quotePeriod) {} +} diff --git a/src/contracts/factories/UniswapV2RelayerFactory.sol b/src/contracts/factories/UniswapV2RelayerFactory.sol new file mode 100644 index 0000000..0d7cdf3 --- /dev/null +++ b/src/contracts/factories/UniswapV2RelayerFactory.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.7.6; + +import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; +import {UniswapV2RelayerChild} from '@contracts/factories/UniswapV2RelayerChild.sol'; +import {Authorizable} from '@contracts/utils/Authorizable.sol'; + +contract UniswapV2RelayerFactory is Authorizable { + uint256 public relayerId; + + // --- Events --- + event NewUniswapV2Relayer(address indexed _relayer, address _baseToken, address _quoteToken, uint32 _quotePeriod); + + // --- Data --- + mapping(uint256 => address) public relayerById; + + // --- Init --- + constructor() Authorizable(msg.sender) {} + + // --- Methods --- + + function deployUniswapV2Relayer( + address _algebraV2Factory, + address _baseToken, + address _quoteToken, + uint32 _quotePeriod + ) external isAuthorized returns (IBaseOracle _relayer) { + _relayer = IBaseOracle(address(new UniswapV2RelayerChild(_algebraV2Factory, _baseToken, _quoteToken, _quotePeriod))); + relayerId++; + relayerById[relayerId] = address(_relayer); + emit NewUniswapV2Relayer(address(_relayer), _baseToken, _quoteToken, _quotePeriod); + } +} diff --git a/src/contracts/oracles/UniswapV2Relayer.sol b/src/contracts/oracles/UniswapV2Relayer.sol new file mode 100644 index 0000000..db304a3 --- /dev/null +++ b/src/contracts/oracles/UniswapV2Relayer.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.7.6; + +import {IERC20Metadata} from '@algebra-periphery/interfaces/IERC20Metadata.sol'; +import {IAlgebraFactory} from '@algebra-core/interfaces/IAlgebraFactory.sol'; +import {IAlgebraPool} from '@algebra-core/interfaces/IAlgebraPool.sol'; +import {IDataStorageOperator} from '@algebra-core/interfaces/IDataStorageOperator.sol'; +import {DataStorageLibrary} from '@algebra-periphery/libraries/DataStorageLibrary.sol'; + +contract UniswapV2Relayer { + 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; + + constructor(address _algebraV3Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { + algebraPool = IAlgebraFactory(_algebraV3Factory).poolByPair(_baseToken, _quoteToken); + require(algebraPool != address(0)); + + address _token0 = IAlgebraPool(algebraPool).token0(); + address _token1 = IAlgebraPool(algebraPool).token1(); + + // The factory validates that both token0 and token1 are desired baseToken and quoteTokens + if (_token0 == _baseToken) { + baseToken = _token0; + quoteToken = _token1; + } else { + baseToken = _token1; + quoteToken = _token0; + } + + 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 QUOTE_PERIOD + int24 _arithmeticMeanTick = DataStorageLibrary.consult(algebraPool, QUOTE_PERIOD); + // Calculate the quote amount + uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({ + tick: _arithmeticMeanTick, + baseAmount: BASE_AMOUNT, + baseToken: baseToken, + quoteToken: quoteToken + }); + // Process the quote result to 18 decimal quote + _result = _parseResult(_quoteAmount); + _validity = true; + } + + 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, QUOTE_PERIOD); + uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({ + tick: _arithmeticMeanTick, + baseAmount: BASE_AMOUNT, + baseToken: baseToken, + quoteToken: quoteToken + }); + _result = _parseResult(_quoteAmount); + } + + function _parseResult(uint256 _quoteResult) internal view returns (uint256 _result) { + if (MULTIPLIER == 0) { + return _quoteResult; + } else if (MULTIPLIER > 0) { + return _quoteResult * (10 ** uint256(MULTIPLIER)); + } else { + return _quoteResult / (10 ** _abs(MULTIPLIER)); + } + } + + // @notice Return the absolute value of a signed integer as an unsigned integer + function _abs(int256 x) internal pure returns (uint256) { + x >= 0 ? x : -x; + return uint256(x); + } +} diff --git a/test/e2e/SystemOracle.s.sol b/test/e2e/SystemOracle.s.sol index c989b05..db1c1e8 100644 --- a/test/e2e/SystemOracle.s.sol +++ b/test/e2e/SystemOracle.s.sol @@ -3,7 +3,7 @@ pragma solidity 0.7.6; pragma abicoder v2; import { - MAINNET_ALGEBRA_FACTORY, + MAINNET_ALGEBRA_V3_FACTORY, MAINNET_CHAINLINK_ETH_USD_FEED, MAINNET_CHAINLINK_ARB_USD_FEED, MAINNET_CHAINLINK_SEQUENCER_FEED, @@ -103,8 +103,8 @@ contract OracleSetup is DSTestPlus { ); // --- Camelot --- - arbEthPriceSource = IBaseOracle(address(new CamelotRelayer(MAINNET_ALGEBRA_FACTORY, ARB, ETH, STALE_PRICE))); // correct - ethArbPriceSource = IBaseOracle(address(new CamelotRelayer(MAINNET_ALGEBRA_FACTORY, ETH, ARB, STALE_PRICE))); // inverted + arbEthPriceSource = IBaseOracle(address(new CamelotRelayer(MAINNET_ALGEBRA_V3_FACTORY, ARB, ETH, STALE_PRICE))); // correct + ethArbPriceSource = IBaseOracle(address(new CamelotRelayer(MAINNET_ALGEBRA_V3_FACTORY, ETH, ARB, STALE_PRICE))); // inverted // --- Denominated --- arbUsdPriceSource = IDenominatedOracle(address(new DenominatedOracle(arbEthPriceSource, ethUsdPriceSource, false))); From 5b0ad2c38387d2d8c1ac6ef6a8c1a69f05cab00d Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 17:34:40 -0800 Subject: [PATCH 02/10] Undo original camelot relayer changes --- src/contracts/factories/CamelotRelayerChild.sol | 4 ++-- src/contracts/factories/CamelotRelayerFactory.sol | 4 ++-- src/contracts/oracles/CamelotRelayer.sol | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/contracts/factories/CamelotRelayerChild.sol b/src/contracts/factories/CamelotRelayerChild.sol index 927d229..ff4ec40 100644 --- a/src/contracts/factories/CamelotRelayerChild.sol +++ b/src/contracts/factories/CamelotRelayerChild.sol @@ -7,9 +7,9 @@ import {FactoryChild} from '@contracts/factories/FactoryChild.sol'; contract CamelotRelayerChild is CamelotRelayer, FactoryChild { // --- Init --- constructor( - address _algebraV3Factory, + address _algebraFactory, address _baseToken, address _quoteToken, uint32 _quotePeriod - ) CamelotRelayer(_algebraV3Factory, _baseToken, _quoteToken, _quotePeriod) {} + ) CamelotRelayer(_algebraFactory, _baseToken, _quoteToken, _quotePeriod) {} } diff --git a/src/contracts/factories/CamelotRelayerFactory.sol b/src/contracts/factories/CamelotRelayerFactory.sol index 06e6c70..27f8125 100644 --- a/src/contracts/factories/CamelotRelayerFactory.sol +++ b/src/contracts/factories/CamelotRelayerFactory.sol @@ -20,12 +20,12 @@ contract CamelotRelayerFactory is Authorizable { // --- Methods --- function deployAlgebraRelayer( - address _algebraV3Factory, + address _algebraFactory, address _baseToken, address _quoteToken, uint32 _quotePeriod ) external isAuthorized returns (IBaseOracle _relayer) { - _relayer = IBaseOracle(address(new CamelotRelayerChild(_algebraV3Factory, _baseToken, _quoteToken, _quotePeriod))); + _relayer = IBaseOracle(address(new CamelotRelayerChild(_algebraFactory, _baseToken, _quoteToken, _quotePeriod))); relayerId++; relayerById[relayerId] = address(_relayer); emit NewAlgebraRelayer(address(_relayer), _baseToken, _quoteToken, _quotePeriod); diff --git a/src/contracts/oracles/CamelotRelayer.sol b/src/contracts/oracles/CamelotRelayer.sol index 0c580e4..c5bf1b2 100644 --- a/src/contracts/oracles/CamelotRelayer.sol +++ b/src/contracts/oracles/CamelotRelayer.sol @@ -20,8 +20,8 @@ contract CamelotRelayer { // --- Data --- string public symbol; - constructor(address _algebraV3Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { - algebraPool = IAlgebraFactory(_algebraV3Factory).poolByPair(_baseToken, _quoteToken); + constructor(address _algebraFactory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { + algebraPool = IAlgebraFactory(_algebraFactory).poolByPair(_baseToken, _quoteToken); require(algebraPool != address(0)); address _token0 = IAlgebraPool(algebraPool).token0(); From eeb3296925f2bcad9fe7f051ad3cb8b414addcb5 Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 17:57:18 -0800 Subject: [PATCH 03/10] Rename to camelotV2 and add interfaces --- script/Common.s.sol | 6 +- script/DeployOracle.s.sol | 22 ++--- script/Registry.s.sol | 12 ++- script/predeployment/DeployFactories.s.sol | 21 +++++ ...yerChild.sol => CamelotV2RelayerChild.sol} | 8 +- ...actory.sol => CamelotV2RelayerFactory.sol} | 14 +-- ...swapV2Relayer.sol => CamelotV2Relayer.sol} | 22 ++--- src/interfaces/camelot/ICamelotFactory.sol | 22 +++++ src/interfaces/camelot/ICamelotPair.sol | 93 +++++++++++++++++++ 9 files changed, 181 insertions(+), 39 deletions(-) rename src/contracts/factories/{UniswapV2RelayerChild.sol => CamelotV2RelayerChild.sol} (54%) rename src/contracts/factories/{UniswapV2RelayerFactory.sol => CamelotV2RelayerFactory.sol} (59%) rename src/contracts/oracles/{UniswapV2Relayer.sol => CamelotV2Relayer.sol} (79%) create mode 100644 src/interfaces/camelot/ICamelotFactory.sol create mode 100644 src/interfaces/camelot/ICamelotPair.sol diff --git a/script/Common.s.sol b/script/Common.s.sol index 711fd23..f3eaa00 100644 --- a/script/Common.s.sol +++ b/script/Common.s.sol @@ -8,15 +8,15 @@ import {IERC20Metadata} from '@algebra-periphery/interfaces/IERC20Metadata.sol'; import {IAlgebraPool} from '@algebra-core/interfaces/IAlgebraPool.sol'; import {IAuthorizable} from '@interfaces/utils/IAuthorizable.sol'; import {CamelotRelayerFactory} from '@contracts/factories/CamelotRelayerFactory.sol'; +import {CamelotV2RelayerFactory} from '@contracts/factories/CamelotV2RelayerFactory.sol'; import {ChainlinkRelayerFactory} from '@contracts/factories/ChainlinkRelayerFactory.sol'; import {DenominatedOracleFactory} from '@contracts/factories/DenominatedOracleFactory.sol'; import {IDelayedOracleFactory} from '@interfaces/factories/IDelayedOracleFactory.sol'; -// import {UniswapV2RelayerFactory} from '@contracts/factories/UniswapV2RelayerFactory.sol'; abstract contract CommonMainnet is Script { ChainlinkRelayerFactory public chainlinkRelayerFactory = ChainlinkRelayerFactory(MAINNET_CHAINLINK_RELAYER_FACTORY); - CamelotRelayerFactory public camelotRelayerFactory = CamelotRelayerFactory(MAINNET_CAMELOT_RELAYER_FACTORY); - // UniswapV2RelayerFactory public camelotV2RelayerFactory = UniswapV2RelayerFactory(MAINNET_CAMELOT_V2_RELAYER_FACTORY); + CamelotV2RelayerFactory public camelotV2RelayerFactory = CamelotV2RelayerFactory(MAINNET_CAMELOT_V2_RELAYER_FACTORY); + CamelotRelayerFactory public camelotRelayerFactory = CamelotRelayerFactory(MAINNET_CAMELOT_V3_RELAYER_FACTORY); DenominatedOracleFactory public denominatedOracleFactory = DenominatedOracleFactory(MAINNET_DENOMINATED_ORACLE_FACTORY); IDelayedOracleFactory public delayedOracleFactory = IDelayedOracleFactory(MAINNET_DELAYED_ORACLE_FACTORY); diff --git a/script/DeployOracle.s.sol b/script/DeployOracle.s.sol index 58283f2..d9a3adf 100644 --- a/script/DeployOracle.s.sol +++ b/script/DeployOracle.s.sol @@ -175,7 +175,7 @@ contract DeployCamelotOdgUsdOracle is Script, CommonMainnet { // source .env && forge script DeployCamelotEPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --sender $DEFAULT_KEY_PUBLIC_ADDRESS contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { - IBaseOracle public _ePendlePendleUniswapV2Relayer; + IBaseOracle public _ePendlePendleCamelotV2Relayer; IBaseOracle public _PendleEthOracleRelayer; IBaseOracle public _PendleUsdOracleRelayer; IBaseOracle public _ePendleUsdOracle; @@ -186,9 +186,9 @@ contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { function run() public { vm.startBroadcast(); - // _ePendleEthUniswapV2Relayer = uniswapV2RelayerFactory.deployAlgebraRelayer( - // MAINNET_ALGEBRA_V2_FACTORY, MAINNET_E_PENDLE, MAINNET_PENDLE, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) - // ); + _ePendlePendleCamelotV2Relayer = camelotV2RelayerFactory.deployCamelotV2Relayer( + MAINNET_CAMELOT_V2_FACTORY, MAINNET_E_PENDLE, MAINNET_PENDLE, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) + ); _PendleEthOracleRelayer = camelotRelayerFactory.deployAlgebraRelayer( MAINNET_ALGEBRA_V3_FACTORY, MAINNET_PENDLE, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) @@ -198,17 +198,17 @@ contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { _PendleEthOracleRelayer, IBaseOracle(MAINNET_CHAINLINK_L2VALIDITY_ETH_USD_RELAYER), false ); - // _ePendleUsdOracle = denominatedOracleFactory.deployDenominatedOracle( - // _ePendleEthUniswapV2Relayer, _PendleUsdOracleRelayer, false - // ); + _ePendleUsdOracle = + denominatedOracleFactory.deployDenominatedOracle(_ePendlePendleCamelotV2Relayer, _PendleUsdOracleRelayer, false); - // IBaseOracle ePendleDelayedOracle = - // delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); + IBaseOracle ePendleDelayedOracle = + delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); _PendleUsdOracleRelayer.symbol(); _PendleUsdOracleRelayer.getResultWithValidity(); - // _ePendleUsdOracle.getResultWithValidity(); - // ePendleDelayedOracle.getResultWithValidity(); + + ePendleDelayedOracle.symbol(); + ePendleDelayedOracle.getResultWithValidity(); vm.stopBroadcast(); } diff --git a/script/Registry.s.sol b/script/Registry.s.sol index d19c41d..d48c261 100644 --- a/script/Registry.s.sol +++ b/script/Registry.s.sol @@ -60,6 +60,9 @@ address constant SEPOLIA_ALGEBRA_FARM_CENTER = 0x04e4A5A4E4D2A5a0fb48ECde0bbD555 // -- Mainnet -- +// DAO +address constant MAINNET_TIMELOCK_CONTROLLER = 0x7A528eA3E06D85ED1C22219471Cf0b1851943903; + ////////// CONSTANTS ////////// address constant MAINNET_DEPLOYER = 0xF78dA2A37049627636546E0cFAaB2aD664950917; uint256 constant MAINNET_ORACLE_DELAY = 1 hours; @@ -73,13 +76,16 @@ address constant ARB = 0x912CE59144191C1204E64559FE8253a0e49E6548; address constant ETH_ARB_POOL = 0xe51635ae8136aBAc44906A8f230C2D235E9c195F; ////////// FACTORIES ////////// -address constant MAINNET_CAMELOT_RELAYER_FACTORY = 0x36645830479170265A154Acb726780fdaE41A28F; +address constant MAINNET_CAMELOT_V3_RELAYER_FACTORY = 0x36645830479170265A154Acb726780fdaE41A28F; +address constant MAINNET_CAMELOT_V2_RELAYER_FACTORY = address(0); // Not yet deployed address constant MAINNET_CHAINLINK_RELAYER_FACTORY = 0x06C32500489C28Bd57c551afd8311Fef20bFaBB5; address constant MAINNET_DENOMINATED_ORACLE_FACTORY = 0xBF760b23d2ef3615cec549F22b95a34DB0F8f5CD; -address constant MAINNET_ALGEBRA_V3_FACTORY = 0x1a3c9B1d2F0529D97f2afC5136Cc23e58f1FD35B; -address constant MAINNET_ALGEBRA_V2_FACTORY = 0x6EcCab422D763aC031210895C81787E87B43A652; address constant MAINNET_DELAYED_ORACLE_FACTORY = 0x9Dd63fA54dEfd8820BCAb3e3cC39aeEc1aE88098; +// External +address constant MAINNET_ALGEBRA_V3_FACTORY = 0x1a3c9B1d2F0529D97f2afC5136Cc23e58f1FD35B; +address constant MAINNET_CAMELOT_V2_FACTORY = 0x6EcCab422D763aC031210895C81787E87B43A652; + ////////// RELAYERS ////////// // Camelot address constant MAINNET_CAMELOT_ODG_WETH_RELAYER = 0x10ef7FEcf888Bc4B1F64757B77317946fFBc5873; diff --git a/script/predeployment/DeployFactories.s.sol b/script/predeployment/DeployFactories.s.sol index 5628bda..4cb18d0 100644 --- a/script/predeployment/DeployFactories.s.sol +++ b/script/predeployment/DeployFactories.s.sol @@ -4,6 +4,7 @@ pragma solidity 0.7.6; import '@script/Registry.s.sol'; import {Script} from 'forge-std/Script.sol'; import {CamelotRelayerFactory} from '@contracts/factories/CamelotRelayerFactory.sol'; +import {CamelotV2RelayerFactory} from '@contracts/factories/CamelotV2RelayerFactory.sol'; import {ChainlinkRelayerFactory} from '@contracts/factories/ChainlinkRelayerFactory.sol'; import {DenominatedOracleFactory} from '@contracts/factories/DenominatedOracleFactory.sol'; @@ -50,3 +51,23 @@ contract DeployFactoriesSepolia is Script { vm.stopBroadcast(); } } + +// BROADCAST +// source .env && forge script DeployCamelotV2FactoryMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY + +// SIMULATE +// source .env && forge script DeployCamelotV2FactoryMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC + +contract DeployCamelotV2FactoryMain is Script { + CamelotV2RelayerFactory internal _camelotV2RelayerFactory; + + function run() public { + vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); + _camelotV2RelayerFactory = new CamelotRelayerV2Factory(); + + _camelotV2RelayerFactory.addAuthorization(MAINNET_TIMELOCK_CONTROLLER); + _camelotV2RelayerFactory.removeAuthorization(MAINNET_DEPLOYER); + + vm.stopBroadcast(); + } +} diff --git a/src/contracts/factories/UniswapV2RelayerChild.sol b/src/contracts/factories/CamelotV2RelayerChild.sol similarity index 54% rename from src/contracts/factories/UniswapV2RelayerChild.sol rename to src/contracts/factories/CamelotV2RelayerChild.sol index 9532103..8f78519 100644 --- a/src/contracts/factories/UniswapV2RelayerChild.sol +++ b/src/contracts/factories/CamelotV2RelayerChild.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.7.6; -import {UniswapV2Relayer} from '@contracts/oracles/UniswapV2Relayer.sol'; +import {CamelotV2Relayer} from '@contracts/oracles/CamelotV2Relayer.sol'; import {FactoryChild} from '@contracts/factories/FactoryChild.sol'; -contract UniswapV2RelayerChild is UniswapV2Relayer, FactoryChild { +contract CamelotV2RelayerChild is CamelotV2Relayer, FactoryChild { // --- Init --- constructor( - address _algebraV2Factory, + address _camelotV2Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod - ) UniswapV2Relayer(_algebraV2Factory, _baseToken, _quoteToken, _quotePeriod) {} + ) CamelotV2Relayer(_camelotV2Factory, _baseToken, _quoteToken, _quotePeriod) {} } diff --git a/src/contracts/factories/UniswapV2RelayerFactory.sol b/src/contracts/factories/CamelotV2RelayerFactory.sol similarity index 59% rename from src/contracts/factories/UniswapV2RelayerFactory.sol rename to src/contracts/factories/CamelotV2RelayerFactory.sol index 0d7cdf3..8203f3b 100644 --- a/src/contracts/factories/UniswapV2RelayerFactory.sol +++ b/src/contracts/factories/CamelotV2RelayerFactory.sol @@ -2,14 +2,14 @@ pragma solidity 0.7.6; import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; -import {UniswapV2RelayerChild} from '@contracts/factories/UniswapV2RelayerChild.sol'; +import {CamelotV2RelayerChild} from '@contracts/factories/CamelotV2RelayerChild.sol'; import {Authorizable} from '@contracts/utils/Authorizable.sol'; -contract UniswapV2RelayerFactory is Authorizable { +contract CamelotV2RelayerFactory is Authorizable { uint256 public relayerId; // --- Events --- - event NewUniswapV2Relayer(address indexed _relayer, address _baseToken, address _quoteToken, uint32 _quotePeriod); + event NewCamelotV2Relayer(address indexed _relayer, address _baseToken, address _quoteToken, uint32 _quotePeriod); // --- Data --- mapping(uint256 => address) public relayerById; @@ -19,15 +19,15 @@ contract UniswapV2RelayerFactory is Authorizable { // --- Methods --- - function deployUniswapV2Relayer( - address _algebraV2Factory, + function deployCamelotV2Relayer( + address _camelotV2Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod ) external isAuthorized returns (IBaseOracle _relayer) { - _relayer = IBaseOracle(address(new UniswapV2RelayerChild(_algebraV2Factory, _baseToken, _quoteToken, _quotePeriod))); + _relayer = IBaseOracle(address(new CamelotV2RelayerChild(_camelotV2Factory, _baseToken, _quoteToken, _quotePeriod))); relayerId++; relayerById[relayerId] = address(_relayer); - emit NewUniswapV2Relayer(address(_relayer), _baseToken, _quoteToken, _quotePeriod); + emit NewCamelotV2Relayer(address(_relayer), _baseToken, _quoteToken, _quotePeriod); } } diff --git a/src/contracts/oracles/UniswapV2Relayer.sol b/src/contracts/oracles/CamelotV2Relayer.sol similarity index 79% rename from src/contracts/oracles/UniswapV2Relayer.sol rename to src/contracts/oracles/CamelotV2Relayer.sol index db304a3..c978aa3 100644 --- a/src/contracts/oracles/UniswapV2Relayer.sol +++ b/src/contracts/oracles/CamelotV2Relayer.sol @@ -2,30 +2,30 @@ pragma solidity 0.7.6; import {IERC20Metadata} from '@algebra-periphery/interfaces/IERC20Metadata.sol'; -import {IAlgebraFactory} from '@algebra-core/interfaces/IAlgebraFactory.sol'; -import {IAlgebraPool} from '@algebra-core/interfaces/IAlgebraPool.sol'; import {IDataStorageOperator} from '@algebra-core/interfaces/IDataStorageOperator.sol'; import {DataStorageLibrary} from '@algebra-periphery/libraries/DataStorageLibrary.sol'; +import {ICamelotFactory} from '@interfaces/camelot/ICamelotFactory.sol'; +import {ICamelotPair} from '@interfaces/camelot/ICamelotPair.sol'; -contract UniswapV2Relayer { +contract CamelotV2Relayer { int256 public immutable MULTIPLIER; uint32 public immutable QUOTE_PERIOD; uint128 public immutable BASE_AMOUNT; // --- Registry --- - address public algebraPool; + address public camelotV2Pool; address public baseToken; address public quoteToken; // --- Data --- string public symbol; - constructor(address _algebraV3Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { - algebraPool = IAlgebraFactory(_algebraV3Factory).poolByPair(_baseToken, _quoteToken); - require(algebraPool != address(0)); + constructor(address _camelotV2Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { + camelotV2Pool = ICamelotFactory(_camelotV2Factory).getPair(_baseToken, _quoteToken); + require(camelotV2Pool != address(0)); - address _token0 = IAlgebraPool(algebraPool).token0(); - address _token1 = IAlgebraPool(algebraPool).token1(); + address _token0 = ICamelotPair(camelotV2Pool).token0(); + address _token1 = ICamelotPair(camelotV2Pool).token1(); // The factory validates that both token0 and token1 are desired baseToken and quoteTokens if (_token0 == _baseToken) { @@ -47,7 +47,7 @@ contract UniswapV2Relayer { // TODO: add catch if the pool doesn't have enough history - return false // Consult the query with a TWAP period of QUOTE_PERIOD - int24 _arithmeticMeanTick = DataStorageLibrary.consult(algebraPool, QUOTE_PERIOD); + int24 _arithmeticMeanTick = DataStorageLibrary.consult(camelotV2Pool, QUOTE_PERIOD); // Calculate the quote amount uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({ tick: _arithmeticMeanTick, @@ -62,7 +62,7 @@ contract UniswapV2Relayer { 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, QUOTE_PERIOD); + int24 _arithmeticMeanTick = DataStorageLibrary.consult(camelotV2Pool, QUOTE_PERIOD); uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({ tick: _arithmeticMeanTick, baseAmount: BASE_AMOUNT, diff --git a/src/interfaces/camelot/ICamelotFactory.sol b/src/interfaces/camelot/ICamelotFactory.sol new file mode 100644 index 0000000..8360fbc --- /dev/null +++ b/src/interfaces/camelot/ICamelotFactory.sol @@ -0,0 +1,22 @@ +pragma solidity 0.7.6; + +interface ICamelotFactory { + event PairCreated(address indexed token0, address indexed token1, address pair, uint256); + + function owner() external view returns (address); + function feePercentOwner() external view returns (address); + function setStableOwner() external view returns (address); + function feeTo() external view returns (address); + + function ownerFeeShare() external view returns (uint256); + function referrersFeeShare(address) external view returns (uint256); + + function getPair(address tokenA, address tokenB) external view returns (address pair); + function allPairs(uint256) external view returns (address pair); + function allPairsLength() external view returns (uint256); + + function createPair(address tokenA, address tokenB) external returns (address pair); + + function setFeeTo(address) external; + function feeInfo() external view returns (uint _ownerFeeShare, address _feeTo); +} \ No newline at end of file diff --git a/src/interfaces/camelot/ICamelotPair.sol b/src/interfaces/camelot/ICamelotPair.sol new file mode 100644 index 0000000..7c9ed26 --- /dev/null +++ b/src/interfaces/camelot/ICamelotPair.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +pragma solidity 0.7.6; + +interface ICamelotPair { + event Approval(address indexed owner, address indexed spender, uint256 value); + event Transfer(address indexed from, address indexed to, uint256 value); + + function name() external pure returns (string memory); + + function symbol() external pure returns (string memory); + + function decimals() external pure returns (uint8); + + function totalSupply() external view returns (uint256); + + function balanceOf(address owner) external view returns (uint256); + + function allowance(address owner, address spender) external view returns (uint256); + + function approve(address spender, uint256 value) external returns (bool); + + function transfer(address to, uint256 value) external returns (bool); + + function transferFrom(address from, address to, uint256 value) external returns (bool); + + function DOMAIN_SEPARATOR() external view returns (bytes32); + + function PERMIT_TYPEHASH() external pure returns (bytes32); + + function nonces(address owner) external view returns (uint256); + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + event Mint(address indexed sender, uint256 amount0, uint256 amount1); + event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); + event Swap( + address indexed sender, + uint256 amount0In, + uint256 amount1In, + uint256 amount0Out, + uint256 amount1Out, + address indexed to + ); + event Sync(uint112 reserve0, uint112 reserve1); + + function precisionMultiplier0() external pure returns (uint256); + + function precisionMultiplier1() external pure returns (uint256); + + function MINIMUM_LIQUIDITY() external pure returns (uint256); + + function factory() external view returns (address); + + function token0() external view returns (address); + + function token1() external view returns (address); + + function getReserves() + external + view + returns (uint112 reserve0, uint112 reserve1, uint16 token0feePercent, uint16 token1FeePercent); + + function getAmountOut(uint256 amountIn, address tokenIn) external view returns (uint256); + + function kLast() external view returns (uint256); + + function setFeePercent(uint16 token0FeePercent, uint16 token1FeePercent) external; + + function mint(address to) external returns (uint256 liquidity); + + function burn(address to) external returns (uint256 amount0, uint256 amount1); + + function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; + + function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data, address referrer) external; + + function skim(address to) external; + + function sync() external; + + function initialize(address, address) external; + + function stableSwap() external view returns (bool); +} From 28410bda897d226ced42fc70abc209ccbaba049d Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 18:02:11 -0800 Subject: [PATCH 04/10] CamelotV2RelayerFactory --- script/predeployment/DeployFactories.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/predeployment/DeployFactories.s.sol b/script/predeployment/DeployFactories.s.sol index 4cb18d0..4ffcc9a 100644 --- a/script/predeployment/DeployFactories.s.sol +++ b/script/predeployment/DeployFactories.s.sol @@ -63,7 +63,7 @@ contract DeployCamelotV2FactoryMain is Script { function run() public { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); - _camelotV2RelayerFactory = new CamelotRelayerV2Factory(); + _camelotV2RelayerFactory = new CamelotV2RelayerFactory(); _camelotV2RelayerFactory.addAuthorization(MAINNET_TIMELOCK_CONTROLLER); _camelotV2RelayerFactory.removeAuthorization(MAINNET_DEPLOYER); From aab56ff5820d232a7724896dd8ab12b5d0166a65 Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 18:06:23 -0800 Subject: [PATCH 05/10] lint ICamelotFactory --- src/interfaces/camelot/ICamelotFactory.sol | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/interfaces/camelot/ICamelotFactory.sol b/src/interfaces/camelot/ICamelotFactory.sol index 8360fbc..0b6b101 100644 --- a/src/interfaces/camelot/ICamelotFactory.sol +++ b/src/interfaces/camelot/ICamelotFactory.sol @@ -1,22 +1,22 @@ pragma solidity 0.7.6; interface ICamelotFactory { - event PairCreated(address indexed token0, address indexed token1, address pair, uint256); + event PairCreated(address indexed token0, address indexed token1, address pair, uint256); - function owner() external view returns (address); - function feePercentOwner() external view returns (address); - function setStableOwner() external view returns (address); - function feeTo() external view returns (address); + function owner() external view returns (address); + function feePercentOwner() external view returns (address); + function setStableOwner() external view returns (address); + function feeTo() external view returns (address); - function ownerFeeShare() external view returns (uint256); - function referrersFeeShare(address) external view returns (uint256); + function ownerFeeShare() external view returns (uint256); + function referrersFeeShare(address) external view returns (uint256); - function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint256) external view returns (address pair); - function allPairsLength() external view returns (uint256); + function getPair(address tokenA, address tokenB) external view returns (address pair); + function allPairs(uint256) external view returns (address pair); + function allPairsLength() external view returns (uint256); - function createPair(address tokenA, address tokenB) external returns (address pair); + function createPair(address tokenA, address tokenB) external returns (address pair); - function setFeeTo(address) external; - function feeInfo() external view returns (uint _ownerFeeShare, address _feeTo); -} \ No newline at end of file + function setFeeTo(address) external; + function feeInfo() external view returns (uint256 _ownerFeeShare, address _feeTo); +} From 96f3272b7874ae8532fc2983383682f92870008e Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 18:13:27 -0800 Subject: [PATCH 06/10] add comment --- package.json | 3 ++- src/contracts/oracles/CamelotV2Relayer.sol | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 856fba2..d031251 100644 --- a/package.json +++ b/package.json @@ -29,5 +29,6 @@ "solhint": "^4.5.2", "solhint-plugin-defi-wonderland": "^1.1.3", "sort-package-json": "^2.8.0" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/src/contracts/oracles/CamelotV2Relayer.sol b/src/contracts/oracles/CamelotV2Relayer.sol index c978aa3..9b33d9a 100644 --- a/src/contracts/oracles/CamelotV2Relayer.sol +++ b/src/contracts/oracles/CamelotV2Relayer.sol @@ -13,7 +13,7 @@ contract CamelotV2Relayer { uint128 public immutable BASE_AMOUNT; // --- Registry --- - address public camelotV2Pool; + address public camelotV2Pair; address public baseToken; address public quoteToken; @@ -21,11 +21,12 @@ contract CamelotV2Relayer { string public symbol; constructor(address _camelotV2Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { - camelotV2Pool = ICamelotFactory(_camelotV2Factory).getPair(_baseToken, _quoteToken); - require(camelotV2Pool != address(0)); + camelotV2Pair = ICamelotFactory(_camelotV2Factory).getPair(_baseToken, _quoteToken); + require(camelotV2Pair != address(0)); + require(camelotV2Pair.stableSwap() == false); - address _token0 = ICamelotPair(camelotV2Pool).token0(); - address _token1 = ICamelotPair(camelotV2Pool).token1(); + address _token0 = ICamelotPair(camelotV2Pair).token0(); + address _token1 = ICamelotPair(camelotV2Pair).token1(); // The factory validates that both token0 and token1 are desired baseToken and quoteTokens if (_token0 == _baseToken) { @@ -43,6 +44,8 @@ contract CamelotV2Relayer { symbol = string(abi.encodePacked(IERC20Metadata(_baseToken).symbol(), ' / ', IERC20Metadata(_quoteToken).symbol())); } + // TODO: Update calculation for V2 + function getResultWithValidity() external view returns (uint256 _result, bool _validity) { // TODO: add catch if the pool doesn't have enough history - return false From bb893217f24dd5f9555d7a3feaf8f18c25111f2a Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 20:11:56 -0800 Subject: [PATCH 07/10] Working prototype --- script/DeployOracle.s.sol | 14 +++-- script/predeployment/DeployFactories.s.sol | 3 -- src/contracts/oracles/CamelotV2Relayer.sol | 63 +++++++++++++--------- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/script/DeployOracle.s.sol b/script/DeployOracle.s.sol index d9a3adf..dcce999 100644 --- a/script/DeployOracle.s.sol +++ b/script/DeployOracle.s.sol @@ -5,6 +5,7 @@ import '@script/Registry.s.sol'; import {Script} from 'forge-std/Script.sol'; import {CommonMainnet} from '@script/Common.s.sol'; import 'forge-std/console2.sol'; +import {CamelotV2RelayerFactory} from '@contracts/factories/CamelotV2RelayerFactory.sol'; import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; @@ -179,14 +180,19 @@ contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { IBaseOracle public _PendleEthOracleRelayer; IBaseOracle public _PendleUsdOracleRelayer; IBaseOracle public _ePendleUsdOracle; + IBaseOracle public _ePendleDelayedOracle; address public MAINNET_E_PENDLE = 0x3EaBE18eAE267D1B57f917aBa085bb5906114600; address public MAINNET_PENDLE = 0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8; + CamelotV2RelayerFactory internal _camelotV2RelayerFactory; function run() public { vm.startBroadcast(); - _ePendlePendleCamelotV2Relayer = camelotV2RelayerFactory.deployCamelotV2Relayer( + // TODO: remove factory deployment + _camelotV2RelayerFactory = new CamelotV2RelayerFactory(); + + _ePendlePendleCamelotV2Relayer = _camelotV2RelayerFactory.deployCamelotV2Relayer( MAINNET_CAMELOT_V2_FACTORY, MAINNET_E_PENDLE, MAINNET_PENDLE, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) ); @@ -201,14 +207,14 @@ contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { _ePendleUsdOracle = denominatedOracleFactory.deployDenominatedOracle(_ePendlePendleCamelotV2Relayer, _PendleUsdOracleRelayer, false); - IBaseOracle ePendleDelayedOracle = + _ePendleDelayedOracle = delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); _PendleUsdOracleRelayer.symbol(); _PendleUsdOracleRelayer.getResultWithValidity(); - ePendleDelayedOracle.symbol(); - ePendleDelayedOracle.getResultWithValidity(); + _ePendleDelayedOracle.symbol(); + _ePendleDelayedOracle.getResultWithValidity(); vm.stopBroadcast(); } diff --git a/script/predeployment/DeployFactories.s.sol b/script/predeployment/DeployFactories.s.sol index 4ffcc9a..5615888 100644 --- a/script/predeployment/DeployFactories.s.sol +++ b/script/predeployment/DeployFactories.s.sol @@ -65,9 +65,6 @@ contract DeployCamelotV2FactoryMain is Script { vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); _camelotV2RelayerFactory = new CamelotV2RelayerFactory(); - _camelotV2RelayerFactory.addAuthorization(MAINNET_TIMELOCK_CONTROLLER); - _camelotV2RelayerFactory.removeAuthorization(MAINNET_DEPLOYER); - vm.stopBroadcast(); } } diff --git a/src/contracts/oracles/CamelotV2Relayer.sol b/src/contracts/oracles/CamelotV2Relayer.sol index 9b33d9a..86b09a4 100644 --- a/src/contracts/oracles/CamelotV2Relayer.sol +++ b/src/contracts/oracles/CamelotV2Relayer.sol @@ -23,7 +23,12 @@ contract CamelotV2Relayer { constructor(address _camelotV2Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { camelotV2Pair = ICamelotFactory(_camelotV2Factory).getPair(_baseToken, _quoteToken); require(camelotV2Pair != address(0)); - require(camelotV2Pair.stableSwap() == false); + require(ICamelotPair(camelotV2Pair).stableSwap() == false); + + uint112 reserve0; + uint112 reserve1; + (reserve0, reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); + require(reserve0 != 0 && reserve1 != 0, 'CamelotV2Relayer: INSUFFICIENT_RESERVES'); address _token0 = ICamelotPair(camelotV2Pair).token0(); address _token1 = ICamelotPair(camelotV2Pair).token1(); @@ -44,35 +49,43 @@ contract CamelotV2Relayer { symbol = string(abi.encodePacked(IERC20Metadata(_baseToken).symbol(), ' / ', IERC20Metadata(_quoteToken).symbol())); } - // TODO: Update calculation for V2 - 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 QUOTE_PERIOD - int24 _arithmeticMeanTick = DataStorageLibrary.consult(camelotV2Pool, QUOTE_PERIOD); - // Calculate the quote amount - uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({ - tick: _arithmeticMeanTick, - baseAmount: BASE_AMOUNT, - baseToken: baseToken, - quoteToken: quoteToken - }); - // Process the quote result to 18 decimal quote - _result = _parseResult(_quoteAmount); + uint112 _reserve0; + uint112 _reserve1; + (_reserve0, _reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); + + require(_reserve0 > 0 && _reserve1 > 0, 'CamelotPair: INSUFFICIENT_RESERVES'); + + uint256 price; + if (baseToken == ICamelotPair(camelotV2Pair).token0()) { + // baseToken is token0, quoteToken is token1 + price = uint256(_reserve1) * BASE_AMOUNT / uint256(_reserve0); + } else { + // baseToken is token1, quoteToken is token0 + price = uint256(_reserve0) * BASE_AMOUNT / uint256(_reserve1); + } + + _result = _parseResult(price); _validity = true; } 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(camelotV2Pool, QUOTE_PERIOD); - uint256 _quoteAmount = DataStorageLibrary.getQuoteAtTick({ - tick: _arithmeticMeanTick, - baseAmount: BASE_AMOUNT, - baseToken: baseToken, - quoteToken: quoteToken - }); - _result = _parseResult(_quoteAmount); + uint112 _reserve0; + uint112 _reserve1; + (_reserve0, _reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); + + require(_reserve0 > 0 && _reserve1 > 0, 'CamelotPair: INSUFFICIENT_RESERVES'); + + uint256 price; + if (baseToken == ICamelotPair(camelotV2Pair).token0()) { + // baseToken is token0, quoteToken is token1 + price = uint256(_reserve1) * BASE_AMOUNT / uint256(_reserve0); + } else { + // baseToken is token1, quoteToken is token0 + price = uint256(_reserve0) * BASE_AMOUNT / uint256(_reserve1); + } + + _result = _parseResult(price); } function _parseResult(uint256 _quoteResult) internal view returns (uint256 _result) { From 443c9ba824adb357119a0c8a938e8c976e52974f Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 20:53:53 -0800 Subject: [PATCH 08/10] very unreliable twap --- src/contracts/oracles/CamelotV2Relayer.sol | 70 +++++++++++++++------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/src/contracts/oracles/CamelotV2Relayer.sol b/src/contracts/oracles/CamelotV2Relayer.sol index 86b09a4..1049f8e 100644 --- a/src/contracts/oracles/CamelotV2Relayer.sol +++ b/src/contracts/oracles/CamelotV2Relayer.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.7.6; +import '@cryptoalgebra/v1.9-core/contracts/libraries/FullMath.sol'; +import '@cryptoalgebra/v1.9-core/contracts/libraries/LowGasSafeMath.sol'; + import {IERC20Metadata} from '@algebra-periphery/interfaces/IERC20Metadata.sol'; -import {IDataStorageOperator} from '@algebra-core/interfaces/IDataStorageOperator.sol'; -import {DataStorageLibrary} from '@algebra-periphery/libraries/DataStorageLibrary.sol'; import {ICamelotFactory} from '@interfaces/camelot/ICamelotFactory.sol'; import {ICamelotPair} from '@interfaces/camelot/ICamelotPair.sol'; @@ -20,6 +21,11 @@ contract CamelotV2Relayer { // --- Data --- string public symbol; + // TWAP state variables + uint256[] public priceHistory; // Array to store historical prices + uint256[] public timestampHistory; // Array to store corresponding timestamps + uint256 public constant MAX_HISTORY_LENGTH = 100; // Maximum number of price entries to store + constructor(address _camelotV2Factory, address _baseToken, address _quoteToken, uint32 _quotePeriod) { camelotV2Pair = ICamelotFactory(_camelotV2Factory).getPair(_baseToken, _quoteToken); require(camelotV2Pair != address(0)); @@ -50,42 +56,64 @@ contract CamelotV2Relayer { } function getResultWithValidity() external view returns (uint256 _result, bool _validity) { - uint112 _reserve0; - uint112 _reserve1; - (_reserve0, _reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); + updatePrice(); - require(_reserve0 > 0 && _reserve1 > 0, 'CamelotPair: INSUFFICIENT_RESERVES'); - - uint256 price; - if (baseToken == ICamelotPair(camelotV2Pair).token0()) { - // baseToken is token0, quoteToken is token1 - price = uint256(_reserve1) * BASE_AMOUNT / uint256(_reserve0); - } else { - // baseToken is token1, quoteToken is token0 - price = uint256(_reserve0) * BASE_AMOUNT / uint256(_reserve1); - } + // TODO _result = _parseResult(price); _validity = true; } function read() external view returns (uint256 _result) { - uint112 _reserve0; - uint112 _reserve1; - (_reserve0, _reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); + _result = getCurrentPrice(); + } + + function getCurrentPrice() internal view returns (uint256) { + uint112 reserve0; + uint112 reserve1; + (reserve0, reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); require(_reserve0 > 0 && _reserve1 > 0, 'CamelotPair: INSUFFICIENT_RESERVES'); uint256 price; if (baseToken == ICamelotPair(camelotV2Pair).token0()) { // baseToken is token0, quoteToken is token1 - price = uint256(_reserve1) * BASE_AMOUNT / uint256(_reserve0); + price = FullMath.mulDiv(reserve1, BASE_AMOUNT, reserve0); } else { // baseToken is token1, quoteToken is token0 - price = uint256(_reserve0) * BASE_AMOUNT / uint256(_reserve1); + price = FullMath.mulDiv(reserve0, BASE_AMOUNT, reserve1); } - _result = _parseResult(price); + return _parseResult(price); + } + + // Function to calculate the TWAP + function getTWAP(uint32 period) external view returns (uint256 twap) { + uint256 totalWeightedPrice = 0; + uint256 totalTime = 0; + + for (uint256 i = 0; i < priceHistory.length; i++) { + if (block.timestamp - timestampHistory[i] <= period) { + totalWeightedPrice += priceHistory[i] * (block.timestamp - timestampHistory[i]); + totalTime += (block.timestamp - timestampHistory[i]); + } + } + + require(totalTime > 0, 'No price data available for the specified period'); + twap = totalWeightedPrice / totalTime; + } + + function _updatePrice() internal { + uint256 currentPrice = getCurrentPrice(); + uint256 currentTime = block.timestamp; + + priceHistory.push(currentPrice); + timestampHistory.push(currentTime); + + if (priceHistory.length > MAX_HISTORY_LENGTH) { + priceHistory.pop(); + timestampHistory.pop(); + } } function _parseResult(uint256 _quoteResult) internal view returns (uint256 _result) { From 8e7c762392f3fa95b01abfd288d401a4736ed214 Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Thu, 12 Dec 2024 21:22:21 -0800 Subject: [PATCH 09/10] twap working --- script/DeployOracle.s.sol | 19 ++++++--- .../factories/CamelotV2RelayerFactory.sol | 4 +- src/contracts/oracles/CamelotV2Relayer.sol | 18 ++++---- src/interfaces/oracles/ICamelotV2Relayer.sol | 41 +++++++++++++++++++ 4 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 src/interfaces/oracles/ICamelotV2Relayer.sol diff --git a/script/DeployOracle.s.sol b/script/DeployOracle.s.sol index dcce999..c75385b 100644 --- a/script/DeployOracle.s.sol +++ b/script/DeployOracle.s.sol @@ -8,6 +8,7 @@ import 'forge-std/console2.sol'; import {CamelotV2RelayerFactory} from '@contracts/factories/CamelotV2RelayerFactory.sol'; import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; +import {ICamelotV2Relayer} from '@interfaces/oracles/ICamelotV2Relayer.sol'; // BROADCAST // source .env && forge script DeployEthUsdRelayer --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY --account defaultKey --sender $DEFAULT_KEY_PUBLIC_ADDRESS @@ -207,14 +208,20 @@ contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { _ePendleUsdOracle = denominatedOracleFactory.deployDenominatedOracle(_ePendlePendleCamelotV2Relayer, _PendleUsdOracleRelayer, false); - _ePendleDelayedOracle = - delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); + ICamelotV2Relayer(address(_ePendlePendleCamelotV2Relayer)).updatePrice(); + vm.warp(block.timestamp + 30 minutes); + ICamelotV2Relayer(address(_ePendlePendleCamelotV2Relayer)).updatePrice(); + _ePendlePendleCamelotV2Relayer.getResultWithValidity(); - _PendleUsdOracleRelayer.symbol(); - _PendleUsdOracleRelayer.getResultWithValidity(); + // _ePendleDelayedOracle = + // delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); - _ePendleDelayedOracle.symbol(); - _ePendleDelayedOracle.getResultWithValidity(); + // _PendleUsdOracleRelayer.symbol(); + // _PendleUsdOracleRelayer.getResultWithValidity(); + + // _ePendleDelayedOracle.symbol(); + // ICamelotV2Relayer(address(_ePendlePendleCamelotV2Relayer)).updatePrice(); + // _ePendleDelayedOracle.getResultWithValidity(); vm.stopBroadcast(); } diff --git a/src/contracts/factories/CamelotV2RelayerFactory.sol b/src/contracts/factories/CamelotV2RelayerFactory.sol index 8203f3b..47eb59a 100644 --- a/src/contracts/factories/CamelotV2RelayerFactory.sol +++ b/src/contracts/factories/CamelotV2RelayerFactory.sol @@ -2,6 +2,7 @@ pragma solidity 0.7.6; import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; +import {ICamelotV2Relayer} from '@interfaces/oracles/ICamelotV2Relayer.sol'; import {CamelotV2RelayerChild} from '@contracts/factories/CamelotV2RelayerChild.sol'; import {Authorizable} from '@contracts/utils/Authorizable.sol'; @@ -25,7 +26,8 @@ contract CamelotV2RelayerFactory is Authorizable { address _quoteToken, uint32 _quotePeriod ) external isAuthorized returns (IBaseOracle _relayer) { - _relayer = IBaseOracle(address(new CamelotV2RelayerChild(_camelotV2Factory, _baseToken, _quoteToken, _quotePeriod))); + _relayer = + ICamelotV2Relayer(address(new CamelotV2RelayerChild(_camelotV2Factory, _baseToken, _quoteToken, _quotePeriod))); relayerId++; relayerById[relayerId] = address(_relayer); emit NewCamelotV2Relayer(address(_relayer), _baseToken, _quoteToken, _quotePeriod); diff --git a/src/contracts/oracles/CamelotV2Relayer.sol b/src/contracts/oracles/CamelotV2Relayer.sol index 1049f8e..4fabf24 100644 --- a/src/contracts/oracles/CamelotV2Relayer.sol +++ b/src/contracts/oracles/CamelotV2Relayer.sol @@ -56,9 +56,7 @@ contract CamelotV2Relayer { } function getResultWithValidity() external view returns (uint256 _result, bool _validity) { - updatePrice(); - - // TODO + uint256 price = getTWAP(QUOTE_PERIOD); _result = _parseResult(price); _validity = true; @@ -69,26 +67,26 @@ contract CamelotV2Relayer { } function getCurrentPrice() internal view returns (uint256) { - uint112 reserve0; - uint112 reserve1; - (reserve0, reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); + uint112 _reserve0; + uint112 _reserve1; + (_reserve0, _reserve1,,) = ICamelotPair(camelotV2Pair).getReserves(); require(_reserve0 > 0 && _reserve1 > 0, 'CamelotPair: INSUFFICIENT_RESERVES'); uint256 price; if (baseToken == ICamelotPair(camelotV2Pair).token0()) { // baseToken is token0, quoteToken is token1 - price = FullMath.mulDiv(reserve1, BASE_AMOUNT, reserve0); + price = FullMath.mulDiv(_reserve1, BASE_AMOUNT, _reserve0); } else { // baseToken is token1, quoteToken is token0 - price = FullMath.mulDiv(reserve0, BASE_AMOUNT, reserve1); + price = FullMath.mulDiv(_reserve0, BASE_AMOUNT, _reserve1); } return _parseResult(price); } // Function to calculate the TWAP - function getTWAP(uint32 period) external view returns (uint256 twap) { + function getTWAP(uint32 period) internal view returns (uint256 twap) { uint256 totalWeightedPrice = 0; uint256 totalTime = 0; @@ -103,7 +101,7 @@ contract CamelotV2Relayer { twap = totalWeightedPrice / totalTime; } - function _updatePrice() internal { + function updatePrice() external { uint256 currentPrice = getCurrentPrice(); uint256 currentTime = block.timestamp; diff --git a/src/interfaces/oracles/ICamelotV2Relayer.sol b/src/interfaces/oracles/ICamelotV2Relayer.sol new file mode 100644 index 0000000..6b6240a --- /dev/null +++ b/src/interfaces/oracles/ICamelotV2Relayer.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.7.6; + +import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; + +interface ICamelotV2Relayer is IBaseOracle { + /** + * @dev Address of the AlgebraPair used to consult the TWAP + */ + function updatePrice() external; + + /** + * @dev Address of the AlgebraPair used to consult the TWAP + */ + function camelotPool() external view returns (address _camelotPool); + + /** + * @dev Address of the base token used to consult the quote + */ + function baseToken() external view returns (address _baseToken); + + /** + * @dev Address of the token used as a quote reference + */ + function quoteToken() external view returns (address _quoteToken); + + /** + * @dev The amount in wei of the base token used to consult the pool for a quote + */ + function baseAmount() external view returns (uint128 _baseAmount); + + /** + * @dev The multiplier used to convert the quote into an 18 decimals format + */ + function multiplier() external view returns (int256 _multiplier); + + /** + * @dev The length of the TWAP used to consult the pool + */ + function quotePeriod() external view returns (uint32 _quotePeriod); +} From 275849ed42169b5a39cc516b204d62eaf9d1613b Mon Sep 17 00:00:00 2001 From: Patrick Gallagher Date: Wed, 18 Dec 2024 16:37:50 -0800 Subject: [PATCH 10/10] Change to Pendle/USD oracle. ePendle oracle in separate repo --- script/DeployOracle.s.sol | 50 ++++++---------------- script/predeployment/DeployFactories.s.sol | 22 +++++----- 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/script/DeployOracle.s.sol b/script/DeployOracle.s.sol index c75385b..fb3795d 100644 --- a/script/DeployOracle.s.sol +++ b/script/DeployOracle.s.sol @@ -5,10 +5,11 @@ import '@script/Registry.s.sol'; import {Script} from 'forge-std/Script.sol'; import {CommonMainnet} from '@script/Common.s.sol'; import 'forge-std/console2.sol'; -import {CamelotV2RelayerFactory} from '@contracts/factories/CamelotV2RelayerFactory.sol'; + +import {CamelotRelayerFactory} from '@contracts/factories/CamelotRelayerFactory.sol'; +import {DenominatedOracleFactory} from '@contracts/factories/DenominatedOracleFactory.sol'; import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol'; -import {ICamelotV2Relayer} from '@interfaces/oracles/ICamelotV2Relayer.sol'; // BROADCAST // source .env && forge script DeployEthUsdRelayer --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY --account defaultKey --sender $DEFAULT_KEY_PUBLIC_ADDRESS @@ -171,57 +172,34 @@ contract DeployCamelotOdgUsdOracle is Script, CommonMainnet { } // BROADCAST -// source .env && forge script DeployCamelotEPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY --sender $DEFAULT_KEY_PUBLIC_ADDRESS --account defaultKey +// source .env && forge script DeployCamelotPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY --sender $DEFAULT_KEY_PUBLIC_ADDRESS --account defaultKey // SIMULATE -// source .env && forge script DeployCamelotEPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --sender $DEFAULT_KEY_PUBLIC_ADDRESS +// source .env && forge script DeployCamelotPendleUsdOracle --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --sender $DEFAULT_KEY_PUBLIC_ADDRESS -contract DeployCamelotEPendleUsdOracle is Script, CommonMainnet { - IBaseOracle public _ePendlePendleCamelotV2Relayer; +contract DeployCamelotPendleUsdOracle is Script, CommonMainnet { IBaseOracle public _PendleEthOracleRelayer; IBaseOracle public _PendleUsdOracleRelayer; - IBaseOracle public _ePendleUsdOracle; - IBaseOracle public _ePendleDelayedOracle; - address public MAINNET_E_PENDLE = 0x3EaBE18eAE267D1B57f917aBa085bb5906114600; address public MAINNET_PENDLE = 0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8; - CamelotV2RelayerFactory internal _camelotV2RelayerFactory; + CamelotRelayerFactory public _camelotRelayerFactory = + CamelotRelayerFactory(0xC4E3cE2941476faCC2447497731A6050eEfa25C8); + DenominatedOracleFactory public _denominatedOracleFactory = + DenominatedOracleFactory(0x7028f637d5340da4bC8D3Ef9DfeC5D4D79dE8116); function run() public { vm.startBroadcast(); - // TODO: remove factory deployment - _camelotV2RelayerFactory = new CamelotV2RelayerFactory(); - - _ePendlePendleCamelotV2Relayer = _camelotV2RelayerFactory.deployCamelotV2Relayer( - MAINNET_CAMELOT_V2_FACTORY, MAINNET_E_PENDLE, MAINNET_PENDLE, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) - ); - - _PendleEthOracleRelayer = camelotRelayerFactory.deployAlgebraRelayer( + _PendleEthOracleRelayer = _camelotRelayerFactory.deployAlgebraRelayer( MAINNET_ALGEBRA_V3_FACTORY, MAINNET_PENDLE, MAINNET_WETH, uint32(MAINNET_CAMELOT_QUOTE_PERIOD) ); - _PendleUsdOracleRelayer = denominatedOracleFactory.deployDenominatedOracle( + _PendleUsdOracleRelayer = _denominatedOracleFactory.deployDenominatedOracle( _PendleEthOracleRelayer, IBaseOracle(MAINNET_CHAINLINK_L2VALIDITY_ETH_USD_RELAYER), false ); - _ePendleUsdOracle = - denominatedOracleFactory.deployDenominatedOracle(_ePendlePendleCamelotV2Relayer, _PendleUsdOracleRelayer, false); - - ICamelotV2Relayer(address(_ePendlePendleCamelotV2Relayer)).updatePrice(); - vm.warp(block.timestamp + 30 minutes); - ICamelotV2Relayer(address(_ePendlePendleCamelotV2Relayer)).updatePrice(); - _ePendlePendleCamelotV2Relayer.getResultWithValidity(); - - // _ePendleDelayedOracle = - // delayedOracleFactory.deployDelayedOracle(IBaseOracle(_ePendleUsdOracle), MAINNET_ORACLE_DELAY); - - // _PendleUsdOracleRelayer.symbol(); - // _PendleUsdOracleRelayer.getResultWithValidity(); - - // _ePendleDelayedOracle.symbol(); - // ICamelotV2Relayer(address(_ePendlePendleCamelotV2Relayer)).updatePrice(); - // _ePendleDelayedOracle.getResultWithValidity(); + _PendleUsdOracleRelayer.symbol(); + _PendleUsdOracleRelayer.getResultWithValidity(); vm.stopBroadcast(); } diff --git a/script/predeployment/DeployFactories.s.sol b/script/predeployment/DeployFactories.s.sol index 5615888..5f2096e 100644 --- a/script/predeployment/DeployFactories.s.sol +++ b/script/predeployment/DeployFactories.s.sol @@ -15,14 +15,14 @@ import {DenominatedOracleFactory} from '@contracts/factories/DenominatedOracleFa // source .env && forge script DeployFactoriesMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC contract DeployFactoriesMain is Script { - CamelotRelayerFactory internal _camelotRelayerFactory; - ChainlinkRelayerFactory internal _chainlinkRelayerFactory; + // CamelotRelayerFactory internal _camelotRelayerFactory; + // ChainlinkRelayerFactory internal _chainlinkRelayerFactory; DenominatedOracleFactory internal _denominatedOracleFactory; function run() public { - vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); - _camelotRelayerFactory = new CamelotRelayerFactory(); - _chainlinkRelayerFactory = new ChainlinkRelayerFactory(); + vm.startBroadcast(); + // _camelotRelayerFactory = new CamelotRelayerFactory(); + // _chainlinkRelayerFactory = new ChainlinkRelayerFactory(); _denominatedOracleFactory = new DenominatedOracleFactory(); //_camelotRelayerFactory.addAuthorization(MAINNET_DEPLOYER); @@ -53,17 +53,17 @@ contract DeployFactoriesSepolia is Script { } // BROADCAST -// source .env && forge script DeployCamelotV2FactoryMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY +// source .env && forge script DeployCamelotFactoryMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC --broadcast --verify --etherscan-api-key $ARB_ETHERSCAN_API_KEY // SIMULATE -// source .env && forge script DeployCamelotV2FactoryMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC +// source .env && forge script DeployCamelotFactoryMain --with-gas-price 2000000000 -vvvvv --rpc-url $ARB_MAINNET_RPC -contract DeployCamelotV2FactoryMain is Script { - CamelotV2RelayerFactory internal _camelotV2RelayerFactory; +contract DeployCamelotFactoryMain is Script { + CamelotRelayerFactory internal _camelotRelayerFactory; function run() public { - vm.startBroadcast(vm.envUint('ARB_MAINNET_DEPLOYER_PK')); - _camelotV2RelayerFactory = new CamelotV2RelayerFactory(); + vm.startBroadcast(); + _camelotRelayerFactory = new CamelotRelayerFactory(); vm.stopBroadcast(); }