diff --git a/Makefile b/Makefile index bf3bb30..cf8d47b 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,12 @@ deploy-rseth-mainnet :; forge script scripts/DeployEthereum.s.sol:DeployRsEthEth deploy-ausd-avalanche :; forge script scripts/DeployAvalanche.s.sol:DeployAUSDAvalanche --rpc-url avalanche $(common-flags) +deploy-weeth-linea :; FOUNDRY_PROFILE=linea forge script scripts/DeployLinea.s.sol:DeployWeEthLinea --rpc-url linea $(common-flags) +deploy-ezeth-linea :; FOUNDRY_PROFILE=linea forge script scripts/DeployLinea.s.sol:DeployEzEthLinea --rpc-url linea $(common-flags) +deploy-usdc-linea :; FOUNDRY_PROFILE=linea forge script scripts/DeployLinea.s.sol:DeployUSDCLinea --rpc-url linea $(common-flags) +deploy-usdt-linea :; FOUNDRY_PROFILE=linea forge script scripts/DeployLinea.s.sol:DeployUSDTLinea --rpc-url linea $(common-flags) +deploy-wsteth-linea :; FOUNDRY_PROFILE=linea forge script scripts/DeployLinea.s.sol:DeployWstETHLinea --rpc-url linea $(common-flags) + # Utilities download :; cast etherscan-source --chain ${chain} -d src/etherscan/${chain}_${address} ${address} git-diff : diff --git a/foundry.toml b/foundry.toml index 4f53306..125139a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,6 +9,7 @@ remappings = [ ffi = true fs_permissions = [{ access = "write", path = "./reports" }] evm_version = 'shanghai' +optimizer = true [profile.zksync] src = 'zksync/src' @@ -27,6 +28,9 @@ fallback_oz = true mode = '3' zksolc = '1.5.3' +[profile.linea] +evm_version = 'london' + [rpc_endpoints] mainnet = "${RPC_MAINNET}" optimism = "${RPC_OPTIMISM}" @@ -42,6 +46,7 @@ gnosis = "${RPC_GNOSIS}" bnb = "${RPC_BNB}" scroll="${RPC_SCROLL}" zksync = "${RPC_ZKSYNC}" +linea = "${RPC_LINEA}" [etherscan] mainnet = { key="${ETHERSCAN_API_KEY_MAINNET}", chainId=1 } @@ -54,8 +59,9 @@ metis = { key="any", chainId=1088, url='https://andromeda-explorer.metis.io/' } base = { key="${ETHERSCAN_API_KEY_BASE}", chainId=8453 } zkevm = { key="${ETHERSCAN_API_KEY_ZKEVM}", chainId=1101 } gnosis = { key="${ETHERSCAN_API_KEY_GNOSIS}", chainId=100 } -bnb= { key="${ETHERSCAN_API_KEY_BNB}",chainId=56,url='https://api.bscscan.com/api'} -scroll={key="${ETHERSCAN_API_KEY_SCROLL}",chainId=534352} +bnb = { key="${ETHERSCAN_API_KEY_BNB}", chainId=56,url='https://api.bscscan.com/api' } +scroll = { key="${ETHERSCAN_API_KEY_SCROLL}", chainId=534352 } zksync = { key="${ETHERSCAN_API_KEY_ZKSYNC}", chain = 324 } +linea = { key="${ETHERSCAN_API_KEY_LINEA}", chain = 59144 } # See more config options https://github.com/gakonst/foundry/tree/master/config diff --git a/lib/aave-address-book b/lib/aave-address-book index e1861d9..d22bc78 160000 --- a/lib/aave-address-book +++ b/lib/aave-address-book @@ -1 +1 @@ -Subproject commit e1861d9e12ff96fd774b89a5236d16ea2e15792b +Subproject commit d22bc78386303517252c8ec28761274259ce33c1 diff --git a/lib/aave-helpers b/lib/aave-helpers index 8a96ac9..1821d62 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit 8a96ac9cd75ff83c8c259b04197875311df6e41e +Subproject commit 1821d62ccddb4d9d66ad35405cbaaeec795bd1b2 diff --git a/remappings.txt b/remappings.txt index 3cabf90..b100c8f 100644 --- a/remappings.txt +++ b/remappings.txt @@ -2,5 +2,5 @@ forge-std/=lib/forge-std/src/ aave-address-book/=lib/aave-address-book/src/ cl-synchronicity-price-adapter/=lib/cl-synchronicity-price-adapter/src/ aave-helpers/=lib/aave-helpers/src/ -solidity-utils/=lib/aave-helpers/lib/solidity-utils/src/ -aave-v3-origin/=lib/aave-address-book/lib/aave-v3-origin/src/ \ No newline at end of file +solidity-utils/=lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/src/ +aave-v3-origin/=lib/aave-address-book/lib/aave-v3-origin/src/ diff --git a/reports/ezETH_linea.md b/reports/ezETH_linea.md new file mode 100644 index 0000000..0b274c4 --- /dev/null +++ b/reports/ezETH_linea.md @@ -0,0 +1,32 @@ +# Capo Report + +| Capped ezETH / ETH / USD | ETH / USD | Diff | Date | 14-day growth in yearly % | +| --- | --- | --- | --- | --- | +| 3770.00194197 | 3665.15 | 2.82% | 30 Nov 2024 | 3.84% | +| 3830.48882182 | 3723.96 | 2.82% | 01 Dec 2024 | 3.78% | +| 3691.41415862 | 3586.89 | 2.87% | 02 Dec 2024 | 4.64% | +| 3675.49770077 | 3570.45 | 2.90% | 03 Dec 2024 | 5.20% | +| 3995.78720977 | 3880.863962 | 2.92% | 04 Dec 2024 | 5.28% | +| 3915.10724598 | 3802.457848 | 2.92% | 05 Dec 2024 | 4.93% | +| 4134.6643822 | 4015.57 | 2.92% | 07 Dec 2024 | 4.98% | +| 4114.15503156 | 3995.1925 | 2.93% | 08 Dec 2024 | 4.81% | +| 4039.40938764 | 3923.11 | 2.92% | 09 Dec 2024 | 4.37% | +| 3814.86076741 | 3704.76 | 2.93% | 10 Dec 2024 | 4.29% | +| 3767.95106589 | 3661.364462 | 2.87% | 11 Dec 2024 | 2.63% | +| 4042.97361668 | 3925.7999 | 2.94% | 12 Dec 2024 | 3.91% | +| 4005.24119365 | 3889.3902 | 2.93% | 13 Dec 2024 | 3.09% | +| 4039.57381507 | 3922.39255063 | 2.94% | 14 Dec 2024 | 3.16% | +| 3971.70756371 | 3855.595517 | 2.97% | 15 Dec 2024 | 3.63% | +| 4063.83857341 | 3944.28190958 | 2.99% | 16 Dec 2024 | 4.11% | +| 4145.21152209 | 4023.19 | 2.99% | 17 Dec 2024 | 2.87% | + + +* 14-day growth is calculated as an annualized percentage relative to the value of the rate 14 days prior. + + +| Max Yearly % | Max Day-to-day yearly % | Max 14-day yearly % | +| --- | --- | --- | +| 10.89% | 25.28% | 5.28% | + + +* Max day-to-day yearly % indicates the maximum growth between two emissions as an annualized percentage. diff --git a/reports/weETH_linea.md b/reports/weETH_linea.md new file mode 100644 index 0000000..604b1a5 --- /dev/null +++ b/reports/weETH_linea.md @@ -0,0 +1,39 @@ +# Capo Report + +| Capped weETH / ETH / USD | ETH / USD | Diff | Date | 7-day growth in yearly % | +| --- | --- | --- | --- | --- | +| 3542.34792694 | 3362.53 | 5.21% | 23 Nov 2024 | 3.00% | +| 3557.09776461 | 3376.23 | 5.22% | 24 Nov 2024 | 3.04% | +| 3689.00188804 | 3501.18 | 5.22% | 25 Nov 2024 | 3.11% | +| 3490.27678812 | 3312.314206 | 5.23% | 26 Nov 2024 | 2.85% | +| 3681.32213097 | 3493.3843 | 5.24% | 27 Nov 2024 | 2.73% | +| 3785.35901733 | 3591.88 | 5.25% | 28 Nov 2024 | 2.79% | +| 3806.40678324 | 3611.63 | 5.25% | 29 Nov 2024 | 2.66% | +| 3863.16783347 | 3665.15 | 5.26% | 30 Nov 2024 | 2.63% | +| 3925.42373546 | 3723.96 | 5.27% | 01 Dec 2024 | 2.51% | +| 3781.19041512 | 3586.89 | 5.27% | 02 Dec 2024 | 2.49% | +| 3764.15002086 | 3570.45 | 5.28% | 03 Dec 2024 | 2.49% | +| 4092.06323209 | 3880.863962 | 5.30% | 04 Dec 2024 | 2.95% | +| 4009.69891287 | 3802.457848 | 5.31% | 05 Dec 2024 | 2.99% | +| 4234.64152435 | 4015.57 | 5.31% | 07 Dec 2024 | 2.93% | +| 4213.57352699 | 3995.1925 | 5.32% | 08 Dec 2024 | 2.96% | +| 4137.86255022 | 3923.11 | 5.33% | 09 Dec 2024 | 2.98% | +| 3907.88047386 | 3704.76 | 5.34% | 10 Dec 2024 | 3.05% | +| 3862.43345114 | 3661.364462 | 5.34% | 11 Dec 2024 | 3.10% | +| 4141.70158988 | 3925.7999 | 5.35% | 12 Dec 2024 | 2.69% | +| 4103.6040573 | 3889.3902 | 5.36% | 13 Dec 2024 | 2.70% | +| 4138.73258428 | 3922.39255063 | 5.37% | 14 Dec 2024 | 2.83% | +| 4068.53623873 | 3855.595517 | 5.37% | 15 Dec 2024 | 2.69% | +| 4162.45361466 | 3944.28190958 | 5.38% | 16 Dec 2024 | 2.73% | +| 4246.04269628 | 4023.19 | 5.39% | 17 Dec 2024 | 2.69% | + + +* 7-day growth is calculated as an annualized percentage relative to the value of the rate 7 days prior. + + +| Max Yearly % | Max Day-to-day yearly % | Max 7-day yearly % | +| --- | --- | --- | +| 8.75% | 5.53% | 3.11% | + + +* Max day-to-day yearly % indicates the maximum growth between two emissions as an annualized percentage. diff --git a/reports/wstETH_Linea.md b/reports/wstETH_Linea.md new file mode 100644 index 0000000..d1dc60b --- /dev/null +++ b/reports/wstETH_Linea.md @@ -0,0 +1,15 @@ +# Capo Report + +| Capped wstETH / stETH(ETH) / USD | ETH / USD | Diff | Date | 7-day growth in yearly % | +| --- | --- | --- | --- | --- | + + +* 7-day growth is calculated as an annualized percentage relative to the value of the rate 7 days prior. + + +| Max Yearly % | Max Day-to-day yearly % | Max 7-day yearly % | +| --- | --- | --- | +| 9.68% | 3.04% | 0.00% | + + +* Max day-to-day yearly % indicates the maximum growth between two emissions as an annualized percentage. diff --git a/scripts/DeployLinea.s.sol b/scripts/DeployLinea.s.sol new file mode 100644 index 0000000..1da0efd --- /dev/null +++ b/scripts/DeployLinea.s.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {GovV3Helpers} from 'aave-helpers/GovV3Helpers.sol'; +import {LineaScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol'; +import {AaveV3Linea} from 'aave-address-book/AaveV3Linea.sol'; +import {CLRatePriceCapAdapter} from '../src/contracts/CLRatePriceCapAdapter.sol'; +import {PriceCapAdapterStable, IPriceCapAdapterStable} from '../src/contracts/PriceCapAdapterStable.sol'; +import {IPriceCapAdapter, IChainlinkAggregator} from '../src/interfaces/IPriceCapAdapter.sol'; + +library CapAdaptersCodeLinea { + address public constant ezETH_ETH_AGGREGATOR = 0xb71F79770BA599940F454c70e63d4DE0E8606731; + address public constant weETH_eETH_AGGREGATOR = 0x1FBc7d24654b10c71fd74d3730d9Df17836181EF; + address public constant wstETH_stETH_AGGREGATOR = 0x3C8A95F2264bB3b52156c766b738357008d87cB7; + address public constant WETH_PRICE_FEED = 0x3c6Cd9Cc7c7a4c2Cf5a82734CD249D7D593354dA; + address public constant USDC_PRICE_FEED = 0xAADAa473C1bDF7317ec07c915680Af29DeBfdCb5; + address public constant USDT_PRICE_FEED = 0xefCA2bbe0EdD0E22b2e0d2F8248E99F4bEf4A7dB; + + function weETHAdapterCode() internal pure returns (bytes memory) { + return + abi.encodePacked( + type(CLRatePriceCapAdapter).creationCode, + abi.encode( + IPriceCapAdapter.CapAdapterParams({ + aclManager: AaveV3Linea.ACL_MANAGER, + baseAggregatorAddress: WETH_PRICE_FEED, + ratioProviderAddress: weETH_eETH_AGGREGATOR, + pairDescription: 'Capped weETH / eETH(ETH) / USD', + minimumSnapshotDelay: 7 days, + priceCapParams: IPriceCapAdapter.PriceCapUpdateParams({ + snapshotRatio: 1054169605180649721, + snapshotTimestamp: 1733109809, + maxYearlyRatioGrowthPercent: 8_75 + }) + }) + ) + ); + } + + function ezETHAdapterCode() internal pure returns (bytes memory) { + return + abi.encodePacked( + type(CLRatePriceCapAdapter).creationCode, + abi.encode( + IPriceCapAdapter.CapAdapterParams({ + aclManager: AaveV3Linea.ACL_MANAGER, + baseAggregatorAddress: WETH_PRICE_FEED, + ratioProviderAddress: ezETH_ETH_AGGREGATOR, + pairDescription: 'Capped ezETH / ETH / USD', + minimumSnapshotDelay: 14 days, + priceCapParams: IPriceCapAdapter.PriceCapUpdateParams({ + snapshotRatio: 1029140608890425422, + snapshotTimestamp: 1733109809, + maxYearlyRatioGrowthPercent: 10_89 + }) + }) + ) + ); + } + + function wstETHAdapterCode() internal pure returns (bytes memory) { + return + abi.encodePacked( + type(CLRatePriceCapAdapter).creationCode, + abi.encode( + IPriceCapAdapter.CapAdapterParams({ + aclManager: AaveV3Linea.ACL_MANAGER, + baseAggregatorAddress: WETH_PRICE_FEED, + ratioProviderAddress: wstETH_stETH_AGGREGATOR, + pairDescription: 'Capped wstETH / stETH(ETH) / USD', + minimumSnapshotDelay: 7 days, + priceCapParams: IPriceCapAdapter.PriceCapUpdateParams({ + snapshotRatio: 1190272828525538502, + snapshotTimestamp: 1736592058, // Jan-11-2025 + maxYearlyRatioGrowthPercent: 9_68 + }) + }) + ) + ); + } + + function USDCAdapterCode() internal pure returns (bytes memory) { + return + abi.encodePacked( + type(PriceCapAdapterStable).creationCode, + abi.encode( + IPriceCapAdapterStable.CapAdapterStableParams({ + aclManager: AaveV3Linea.ACL_MANAGER, + assetToUsdAggregator: IChainlinkAggregator(USDC_PRICE_FEED), + adapterDescription: 'Capped USDC/USD', + priceCap: int256(1.04 * 1e8) + }) + ) + ); + } + + function USDTAdapterCode() internal pure returns (bytes memory) { + return + abi.encodePacked( + type(PriceCapAdapterStable).creationCode, + abi.encode( + IPriceCapAdapterStable.CapAdapterStableParams({ + aclManager: AaveV3Linea.ACL_MANAGER, + assetToUsdAggregator: IChainlinkAggregator(USDT_PRICE_FEED), + adapterDescription: 'Capped USDT/USD', + priceCap: int256(1.04 * 1e8) + }) + ) + ); + } +} + +contract DeployWeEthLinea is LineaScript { + function run() external broadcast { + GovV3Helpers.deployDeterministic(CapAdaptersCodeLinea.weETHAdapterCode()); + } +} + +contract DeployEzEthLinea is LineaScript { + function run() external broadcast { + GovV3Helpers.deployDeterministic(CapAdaptersCodeLinea.ezETHAdapterCode()); + } +} + +contract DeployUSDCLinea is LineaScript { + function run() external broadcast { + GovV3Helpers.deployDeterministic(CapAdaptersCodeLinea.USDCAdapterCode()); + } +} + +contract DeployUSDTLinea is LineaScript { + function run() external broadcast { + GovV3Helpers.deployDeterministic(CapAdaptersCodeLinea.USDTAdapterCode()); + } +} + +contract DeployWstETHLinea is LineaScript { + function run() external broadcast { + GovV3Helpers.deployDeterministic(CapAdaptersCodeLinea.wstETHAdapterCode()); + } +} diff --git a/tests/linea/USDCPriceCapAdapterTest.t.sol b/tests/linea/USDCPriceCapAdapterTest.t.sol new file mode 100644 index 0000000..5253524 --- /dev/null +++ b/tests/linea/USDCPriceCapAdapterTest.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import '../BaseStableTest.sol'; +import {CapAdaptersCodeLinea} from '../../scripts/DeployLinea.s.sol'; + +contract USDCLineaPriceCapAdapterTest is BaseStableTest { + constructor() + BaseStableTest( + CapAdaptersCodeLinea.USDCAdapterCode(), + 10, + ForkParams({network: 'linea', blockNumber: 13432357}) + ) + {} +} diff --git a/tests/linea/USDTPriceCapAdapterTest.t.sol b/tests/linea/USDTPriceCapAdapterTest.t.sol new file mode 100644 index 0000000..5254297 --- /dev/null +++ b/tests/linea/USDTPriceCapAdapterTest.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import '../BaseStableTest.sol'; +import {CapAdaptersCodeLinea} from '../../scripts/DeployLinea.s.sol'; + +contract USDTLineaPriceCapAdapterTest is BaseStableTest { + constructor() + BaseStableTest( + CapAdaptersCodeLinea.USDTAdapterCode(), + 10, + ForkParams({network: 'linea', blockNumber: 13432357}) + ) + {} +} diff --git a/tests/linea/ezETHLineaPriceCapAdapterTest.t.sol b/tests/linea/ezETHLineaPriceCapAdapterTest.t.sol new file mode 100644 index 0000000..2013894 --- /dev/null +++ b/tests/linea/ezETHLineaPriceCapAdapterTest.t.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {CLAdapterBaseTest} from '../CLAdapterBaseTest.sol'; +import {CapAdaptersCodeLinea} from '../../scripts/DeployLinea.s.sol'; + +contract ezETHLineaPriceCapAdapterTest is CLAdapterBaseTest { + constructor() + CLAdapterBaseTest( + CapAdaptersCodeLinea.ezETHAdapterCode(), + 30, + ForkParams({network: 'linea', blockNumber: 13423434}), + 'ezETH_Linea' + ) + {} +} diff --git a/tests/linea/weETHLineaPriceCapAdapterTest.t.sol b/tests/linea/weETHLineaPriceCapAdapterTest.t.sol new file mode 100644 index 0000000..7037a99 --- /dev/null +++ b/tests/linea/weETHLineaPriceCapAdapterTest.t.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {CLAdapterBaseTest} from '../CLAdapterBaseTest.sol'; +import {CapAdaptersCodeLinea} from '../../scripts/DeployLinea.s.sol'; + +contract weETHLineaPriceCapAdapterTest is CLAdapterBaseTest { + constructor() + CLAdapterBaseTest( + CapAdaptersCodeLinea.weETHAdapterCode(), + 30, + ForkParams({network: 'linea', blockNumber: 13423434}), + 'weETH_Linea' + ) + {} +} diff --git a/tests/linea/wstETHPriceCapAdapterTest.t.sol b/tests/linea/wstETHPriceCapAdapterTest.t.sol new file mode 100644 index 0000000..a2d4742 --- /dev/null +++ b/tests/linea/wstETHPriceCapAdapterTest.t.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import '../BaseTest.sol'; + +import {CapAdaptersCodeLinea, CLRatePriceCapAdapter} from '../../scripts/DeployLinea.s.sol'; + +contract wstETHPriceCapAdapterTestL is BaseTest { + constructor() + BaseTest( + CapAdaptersCodeLinea.wstETHAdapterCode(), + 1, + ForkParams({network: 'linea', blockNumber: 14810572}), + 'wstETH_Linea' + ) + {} + + function _createAdapter( + IPriceCapAdapter.CapAdapterParams memory capAdapterParams + ) internal override returns (IPriceCapAdapter) { + return new CLRatePriceCapAdapter(capAdapterParams); + } +} diff --git a/tests/utils/BlockUtils.sol b/tests/utils/BlockUtils.sol index dfc9767..77e84c9 100644 --- a/tests/utils/BlockUtils.sol +++ b/tests/utils/BlockUtils.sol @@ -56,6 +56,10 @@ library BlockUtils { return 80_000; } + if (keccak256(bytes(network)) == keccak256(bytes('linea'))) { + return 43_200; + } + return 7300; } } diff --git a/tests/utils/GetExchangeRatesTest.t.sol b/tests/utils/GetExchangeRatesTest.t.sol index b4ce9d3..bfc27f0 100644 --- a/tests/utils/GetExchangeRatesTest.t.sol +++ b/tests/utils/GetExchangeRatesTest.t.sol @@ -38,6 +38,7 @@ import {CapAdaptersCodeBase} from '../../scripts/DeployBase.s.sol'; import {CapAdaptersCodeScroll} from '../../scripts/DeployScroll.s.sol'; import {CapAdaptersCodeBNB} from '../../scripts/DeployBnb.s.sol'; import {CapAdaptersCodeZkSync} from '../../scripts/DeployZkSync.s.sol'; +import {CapAdaptersCodeLinea} from '../../scripts/DeployLinea.s.sol'; contract ExchangeRatesEth is Test { function setUp() public { @@ -281,3 +282,29 @@ contract ExchangeRatesZKSync is Test { console.log(block.timestamp); } } + +contract ExchangeRatesLinea is Test { + function setUp() public { + vm.createSelectFork(vm.rpcUrl('linea'), 14450000); // Jan-11-2025 + } + + function test_getExchangeRate() public view { + uint256 ezETHRate = uint256( + IChainlinkAggregator(CapAdaptersCodeLinea.ezETH_ETH_AGGREGATOR).latestAnswer() + ); + + uint256 weETHRate = uint256( + IChainlinkAggregator(CapAdaptersCodeLinea.weETH_eETH_AGGREGATOR).latestAnswer() + ); + + uint256 wstEthRate = uint256( + IChainlinkAggregator(CapAdaptersCodeLinea.wstETH_stETH_AGGREGATOR).latestAnswer() + ); + + console.log('Linea'); + console.log('ezETHRate', ezETHRate); + console.log('weETHRate', weETHRate); + console.log('wstEthRate', wstEthRate); + console.log(block.timestamp); + } +}