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); +}