From 24a3f7d23e03aca479c43c3f5d8a26c06d2686e8 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 6 Dec 2023 03:34:57 +0530 Subject: [PATCH 01/57] Add proposal for Gho Incident Report 20231113 (#1) * chore: add payload and deploy script for update of GHO variable debt token * forge install: gho-core * chore: add gho-core to dependency * test: Add tests for update of gho variable token * test: Add tests for update of gho variable token * fix: add modifier in method of interface * fix: remove gho dependency from repo and fix test * fix: Remove unnecesary dependency * fix: Add latest details --------- Co-authored-by: miguelmtzinf --- remappings.txt | 2 +- ...veV3Ethereum_GhoIncidentReport_20231113.md | 28 +++++++++ ...3Ethereum_GhoIncidentReport_20231113.s.sol | 58 +++++++++++++++++++ ...eV3Ethereum_GhoIncidentReport_20231113.sol | 33 +++++++++++ ...3Ethereum_GhoIncidentReport_20231113.t.sol | 44 ++++++++++++++ 5 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md create mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol create mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol create mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol diff --git a/remappings.txt b/remappings.txt index b3b219556..620a76fc2 100644 --- a/remappings.txt +++ b/remappings.txt @@ -6,4 +6,4 @@ aave-v3-core/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-core/ aave-v3-periphery/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-periphery/ ds-test/=lib/aave-helpers/lib/forge-std/lib/ds-test/src/ forge-std/=lib/aave-helpers/lib/forge-std/src/ -solidity-utils/=lib/aave-helpers/lib/solidity-utils/src/ +solidity-utils/=lib/aave-helpers/lib/solidity-utils/src/ \ No newline at end of file diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md new file mode 100644 index 000000000..98d6ad0c4 --- /dev/null +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md @@ -0,0 +1,28 @@ +--- +title: "GHO update on Aave V3 Ethereum Pool for 13/11/2023 Report" +author: "Aave Labs @aave" +discussions: "https://governance.aave.com/t/arfc-gho-technical-incident-13-11-2023/15642" +--- + +## Simple Summary + +This proposal patches the GHO integration with the Aave V3 Pool, fixing an issue reported by Immunefi on November 13, 2023. The patch, developed by Aave Labs in collaboration with Certora, upholds the highest safety standards. + +## Motivation + +A resolution for the identified technical issue identified in the GHO integration with the Aave V3 Ethereum Pool. The patch guarantees a permanent solution without altering any of the existing GHO features within the Aave Pool. + +## Specification + +The proposal payload upgrades the implementation of GhoVariableDebtToken. + +## References + +- GhoVariableDebtToken implementation: [GhoVariableDebtToken](https://etherscan.io/address/0x20cb2f303ede313e2cc44549ad8653a5e8c0050e#code) +- Implementation: [Payload]() +- [Discussion](https://governance.aave.com/t/arfc-gho-technical-incident-13-11-2023/15642) + + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol new file mode 100644 index 000000000..89ea31bb9 --- /dev/null +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum_GhoIncidentReport_20231113} from './AaveV3Ethereum_GhoIncidentReport_20231113.sol'; +import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/GovV3Helpers.sol'; +import {EthereumScript} from 'aave-helpers/ScriptUtils.sol'; + +/** + * @dev Deploy AaveV3Ethereum_GhoIncidentReport_20231113 + * command: make deploy-ledger contract=src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol:DeployEthereum chain=mainnet + */ +contract DeployEthereum is EthereumScript { + address constant NEW_VGHO_IMPL = 0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e; + + function run() external broadcast { + // deploy payloads + AaveV3Ethereum_GhoIncidentReport_20231113 payload = new AaveV3Ethereum_GhoIncidentReport_20231113( + NEW_VGHO_IMPL + ); + + // compose action + IPayloadsControllerCore.ExecutionAction[] + memory actions = new IPayloadsControllerCore.ExecutionAction[](1); + actions[0] = GovV3Helpers.buildAction(address(payload)); + + // register action at payloadsController + GovV3Helpers.createPayload(actions); + } +} + +/** + * @dev Create Proposal + * command: make deploy-ledger contract=src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol:CreateProposal chain=mainnet + */ +contract CreateProposal is EthereumScript { + function run() external { + // create payloads + PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](1); + + // compose actions for validation + IPayloadsControllerCore.ExecutionAction[] + memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); + //TODO: Replace this address with payload address + actionsEthereum[0] = GovV3Helpers.buildAction(0xfb1163CD80850CD107bB134C15E5dfDF284F63FE); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal2_5( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md' + ) + ); + } +} diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol new file mode 100644 index 000000000..b80e50a1d --- /dev/null +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfiguratorInputTypes} from 'aave-address-book/AaveV3.sol'; +import {IERC20} from 'forge-std/interfaces/IERC20.sol'; +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; + +/** + * @title GHO update on Aave V3 Ethereum Pool for 13/11/2023 Report + * @dev Upgrades the implementation of the GhoVariableDebtToken contract + * @author Aave Labs (@aave) + * - Discussion: https://governance.aave.com/t/arfc-gho-technical-incident-13-11-2023/15642 + */ +contract AaveV3Ethereum_GhoIncidentReport_20231113 { + address public immutable NEW_VGHO_IMPL; + + constructor(address newVGhoImpl) { + NEW_VGHO_IMPL = newVGhoImpl; + } + + function execute() external { + AaveV3Ethereum.POOL_CONFIGURATOR.updateVariableDebtToken( + ConfiguratorInputTypes.UpdateDebtTokenInput({ + asset: AaveV3EthereumAssets.GHO_UNDERLYING, + incentivesController: AaveV3Ethereum.DEFAULT_INCENTIVES_CONTROLLER, + name: IERC20(AaveV3EthereumAssets.GHO_V_TOKEN).name(), + symbol: IERC20(AaveV3EthereumAssets.GHO_V_TOKEN).symbol(), + implementation: NEW_VGHO_IMPL, + params: bytes('') + }) + ); + } +} diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol new file mode 100644 index 000000000..344b71a41 --- /dev/null +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Test.sol'; +import {AaveV3EthereumAssets, AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/ProtocolV3TestBase.sol'; +import {AaveV3Ethereum_GhoIncidentReport_20231113} from './AaveV3Ethereum_GhoIncidentReport_20231113.sol'; + +interface IGhoVariableDebtTokenHelper { + function DEBT_TOKEN_REVISION() external view returns (uint256); +} + +/** + * @dev Test for AaveV3Ethereum_GhoIncidentReport_20231113 + * command: make test-contract filter=AaveV3Ethereum_GhoIncidentReport_20231113 + */ +contract AaveV3Ethereum_GhoIncidentReport_20231113_Test is ProtocolV3TestBase { + address constant NEW_VGHO_IMPL = 0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e; + + AaveV3Ethereum_GhoIncidentReport_20231113 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 18722500); + proposal = new AaveV3Ethereum_GhoIncidentReport_20231113(NEW_VGHO_IMPL); + } + + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_GhoIncidentReport_20231113', + AaveV3Ethereum.POOL, + address(proposal) + ); + } + + function test_debtTokenRevisionUpdate() public { + assertTrue( + IGhoVariableDebtTokenHelper(AaveV3EthereumAssets.GHO_V_TOKEN).DEBT_TOKEN_REVISION() == 0x2 + ); + executePayload(vm, address(proposal)); + assertTrue( + IGhoVariableDebtTokenHelper(AaveV3EthereumAssets.GHO_V_TOKEN).DEBT_TOKEN_REVISION() == 0x3 + ); + } +} From 4aa6143b87b5e26d980cba5079de79f5210b7ccc Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Wed, 6 Dec 2023 11:13:37 +0100 Subject: [PATCH 02/57] fix: Make new impl constant (#3) --- .../AaveV3Ethereum_GhoIncidentReport_20231113.s.sol | 6 ++---- .../AaveV3Ethereum_GhoIncidentReport_20231113.sol | 6 +----- .../AaveV3Ethereum_GhoIncidentReport_20231113.t.sol | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol index 89ea31bb9..d197070fa 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol @@ -14,9 +14,7 @@ contract DeployEthereum is EthereumScript { function run() external broadcast { // deploy payloads - AaveV3Ethereum_GhoIncidentReport_20231113 payload = new AaveV3Ethereum_GhoIncidentReport_20231113( - NEW_VGHO_IMPL - ); + AaveV3Ethereum_GhoIncidentReport_20231113 payload = new AaveV3Ethereum_GhoIncidentReport_20231113(); // compose action IPayloadsControllerCore.ExecutionAction[] @@ -47,7 +45,7 @@ contract CreateProposal is EthereumScript { // create proposal vm.startBroadcast(); GovV3Helpers.createProposal2_5( - vm, + vm, payloads, GovV3Helpers.ipfsHashFile( vm, diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol index b80e50a1d..08fc96cec 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol @@ -12,11 +12,7 @@ import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethe * - Discussion: https://governance.aave.com/t/arfc-gho-technical-incident-13-11-2023/15642 */ contract AaveV3Ethereum_GhoIncidentReport_20231113 { - address public immutable NEW_VGHO_IMPL; - - constructor(address newVGhoImpl) { - NEW_VGHO_IMPL = newVGhoImpl; - } + address public constant NEW_VGHO_IMPL = 0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e; function execute() external { AaveV3Ethereum.POOL_CONFIGURATOR.updateVariableDebtToken( diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol index 344b71a41..f3286efb8 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol @@ -21,7 +21,7 @@ contract AaveV3Ethereum_GhoIncidentReport_20231113_Test is ProtocolV3TestBase { function setUp() public { vm.createSelectFork(vm.rpcUrl('mainnet'), 18722500); - proposal = new AaveV3Ethereum_GhoIncidentReport_20231113(NEW_VGHO_IMPL); + proposal = new AaveV3Ethereum_GhoIncidentReport_20231113(); } function test_defaultProposalExecution() public { From 27dd485e2f2fb5ceb42ba5c67f5e1cc95b0ae3ec Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Wed, 6 Dec 2023 11:17:54 +0100 Subject: [PATCH 03/57] fix: Amend AIP text (#4) * fix: Make new impl constant * fix: Fix AIP text --- .../AaveV3Ethereum_GhoIncidentReport_20231113.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md index 98d6ad0c4..21902514e 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md @@ -10,7 +10,7 @@ This proposal patches the GHO integration with the Aave V3 Pool, fixing an issue ## Motivation -A resolution for the identified technical issue identified in the GHO integration with the Aave V3 Ethereum Pool. The patch guarantees a permanent solution without altering any of the existing GHO features within the Aave Pool. +The proposed patch guarantees a permanent solution for the technical issue that was identified and reported by Immunefi with the GHO integration with the Aave V3 Ethereum Pool. The fix will be implemented without altering any of the existing GHO features within the Aave V3 Pool. ## Specification From 2f242a671075a02ca4b1d2e08556c67295fb1088 Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:53:57 +0100 Subject: [PATCH 04/57] test: Tweak default tests with borrow cap update (#5) --- .../AaveV3Ethereum_GhoIncidentReport_20231113.t.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol index f3286efb8..dcbfb4659 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; import {AaveV3EthereumAssets, AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/ProtocolV3TestBase.sol'; +import {IPoolConfigurator} from 'aave-address-book/AaveV3.sol'; import {AaveV3Ethereum_GhoIncidentReport_20231113} from './AaveV3Ethereum_GhoIncidentReport_20231113.sol'; interface IGhoVariableDebtTokenHelper { @@ -25,6 +26,9 @@ contract AaveV3Ethereum_GhoIncidentReport_20231113_Test is ProtocolV3TestBase { } function test_defaultProposalExecution() public { + // increase GHO borrow cap so test borrows can succeed + vm.prank(AaveV3Ethereum.CAPS_PLUS_RISK_STEWARD); + AaveV3Ethereum.POOL_CONFIGURATOR.setBorrowCap(AaveV3Ethereum.GHO_TOKEN, 36_000_000); defaultTest( 'AaveV3Ethereum_GhoIncidentReport_20231113', AaveV3Ethereum.POOL, From 4812d01dc7f76975ffb20b80f30251f8f2a70924 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Dec 2023 00:10:52 +0530 Subject: [PATCH 05/57] fix: lint issue (#6) --- .../AaveV3Ethereum_GhoIncidentReport_20231113.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md index 21902514e..21e9b39ec 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md @@ -22,7 +22,6 @@ The proposal payload upgrades the implementation of GhoVariableDebtToken. - Implementation: [Payload]() - [Discussion](https://governance.aave.com/t/arfc-gho-technical-incident-13-11-2023/15642) - ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 43a7687a4c629f11d1c3be19bbafb59b8d12d70e Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Thu, 7 Dec 2023 19:44:59 +0100 Subject: [PATCH 06/57] test: Add diffs from test running (#7) --- ...hereum_GhoIncidentReport_20231113_after.md | 25 +++++++++++++++++++ ...hereum_GhoIncidentReport_20231126_after.md | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 diffs/AaveV3Ethereum_GhoIncidentReport_20231113_before_AaveV3Ethereum_GhoIncidentReport_20231113_after.md create mode 100644 diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md diff --git a/diffs/AaveV3Ethereum_GhoIncidentReport_20231113_before_AaveV3Ethereum_GhoIncidentReport_20231113_after.md b/diffs/AaveV3Ethereum_GhoIncidentReport_20231113_before_AaveV3Ethereum_GhoIncidentReport_20231113_after.md new file mode 100644 index 000000000..1088d0e5d --- /dev/null +++ b/diffs/AaveV3Ethereum_GhoIncidentReport_20231113_before_AaveV3Ethereum_GhoIncidentReport_20231113_after.md @@ -0,0 +1,25 @@ +## Reserve changes + +### Reserves altered + +#### GHO ([0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f](https://etherscan.io/address/0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f)) + +| description | value before | value after | +| --- | --- | --- | +| variableDebtTokenImpl | [0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775](https://etherscan.io/address/0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775) | [0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e](https://etherscan.io/address/0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e) | + + +## Raw diff + +```json +{ + "reserves": { + "0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f": { + "variableDebtTokenImpl": { + "from": "0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775", + "to": "0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e" + } + } + } +} +``` \ No newline at end of file diff --git a/diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md b/diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md new file mode 100644 index 000000000..1088d0e5d --- /dev/null +++ b/diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md @@ -0,0 +1,25 @@ +## Reserve changes + +### Reserves altered + +#### GHO ([0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f](https://etherscan.io/address/0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f)) + +| description | value before | value after | +| --- | --- | --- | +| variableDebtTokenImpl | [0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775](https://etherscan.io/address/0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775) | [0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e](https://etherscan.io/address/0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e) | + + +## Raw diff + +```json +{ + "reserves": { + "0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f": { + "variableDebtTokenImpl": { + "from": "0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775", + "to": "0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e" + } + } + } +} +``` \ No newline at end of file From 4c79bb9fd4120ff068eaa946cc01961d51b6a892 Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Thu, 7 Dec 2023 20:15:32 +0100 Subject: [PATCH 07/57] fix: Add payload address (#8) --- .../AaveV3Ethereum_GhoIncidentReport_20231113.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md index 21e9b39ec..2cf269d2a 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md @@ -19,7 +19,7 @@ The proposal payload upgrades the implementation of GhoVariableDebtToken. ## References - GhoVariableDebtToken implementation: [GhoVariableDebtToken](https://etherscan.io/address/0x20cb2f303ede313e2cc44549ad8653a5e8c0050e#code) -- Implementation: [Payload]() +- Implementation: [Payload](https://etherscan.io/address/0xbc9ffee8d18d75a412474b92192257d3c18471ff#code) - [Discussion](https://governance.aave.com/t/arfc-gho-technical-incident-13-11-2023/15642) ## Copyright From 76cd4b62ea788ce12259adcc565128bcea4a1181 Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Thu, 7 Dec 2023 20:40:00 +0100 Subject: [PATCH 08/57] fix: Fix payload address in script (#9) --- .../AaveV3Ethereum_GhoIncidentReport_20231113.s.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol index d197070fa..4345823a2 100644 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol +++ b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol @@ -38,8 +38,7 @@ contract CreateProposal is EthereumScript { // compose actions for validation IPayloadsControllerCore.ExecutionAction[] memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); - //TODO: Replace this address with payload address - actionsEthereum[0] = GovV3Helpers.buildAction(0xfb1163CD80850CD107bB134C15E5dfDF284F63FE); + actionsEthereum[0] = GovV3Helpers.buildAction(0xbC9ffee8d18d75a412474B92192257d3c18471FF); payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); // create proposal From 120f5649187b1f70d39e37d3f4ca88416968aece Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Thu, 7 Dec 2023 20:53:41 +0100 Subject: [PATCH 09/57] fix: Remove unneeded diff file (#10) --- ...hereum_GhoIncidentReport_20231126_after.md | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md diff --git a/diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md b/diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md deleted file mode 100644 index 1088d0e5d..000000000 --- a/diffs/AaveV3Ethereum_GhoIncidentReport_20231126_before_AaveV3Ethereum_GhoIncidentReport_20231126_after.md +++ /dev/null @@ -1,25 +0,0 @@ -## Reserve changes - -### Reserves altered - -#### GHO ([0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f](https://etherscan.io/address/0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f)) - -| description | value before | value after | -| --- | --- | --- | -| variableDebtTokenImpl | [0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775](https://etherscan.io/address/0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775) | [0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e](https://etherscan.io/address/0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e) | - - -## Raw diff - -```json -{ - "reserves": { - "0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f": { - "variableDebtTokenImpl": { - "from": "0x7aa606b1B341fFEeAfAdbbE4A2992EFB35972775", - "to": "0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e" - } - } - } -} -``` \ No newline at end of file From faf2023409830ef7ec2c499dcc0ea032437b2ebf Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:43:38 +0530 Subject: [PATCH 10/57] feat: install aave-ccip at latest commit on aave/ccip#18 --- .gitmodules | 3 +++ lib/aave-ccip | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/aave-ccip diff --git a/.gitmodules b/.gitmodules index f7316a1d6..d34bc9729 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/aave-helpers"] path = lib/aave-helpers url = https://github.com/bgd-labs/aave-helpers +[submodule "lib/aave-ccip"] + path = lib/aave-ccip + url = https://github.com/aave/ccip diff --git a/lib/aave-ccip b/lib/aave-ccip new file mode 160000 index 000000000..623c10c20 --- /dev/null +++ b/lib/aave-ccip @@ -0,0 +1 @@ +Subproject commit 623c10c203d5187eeb82a998ce3c01ea94bce6d9 From 488d8464d0f7b5a862a7bcb56a800eb5668142de Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:48:45 +0530 Subject: [PATCH 11/57] chore: upd remappings, lib/aave-helpers, .assets --- .assets/02a040db3fc4a88618783a9156e7fb51928e1ede.svg | 1 + .assets/03dc42930b2b94af37ef869d012c4734aedb52e6.svg | 1 + .assets/0afe490affc1bc77fe6675127b18e9aeeb4b1404.svg | 1 + .assets/0fcfb1e84443509c42e21db9e4320c00e1db6098.svg | 1 + .assets/1899e5ae4f4fd5b0d2565edd912a160acb2d0b78.svg | 1 + .assets/18e6ba583d4d35e38cb678120492b2b4d52d19ea.svg | 1 + .assets/1aa0fb636d34a35d35ce67919bc0d7d2e36d3839.svg | 1 + .assets/1c1fbd79406b4b3a8c64ec79ef429f7c422d0387.svg | 1 + .assets/2e9d5ba5e949c7896bc79e7fdd98872cb43375b0.svg | 1 + .assets/39a3707c0ded91bbfde8953567853db55452a227.svg | 1 + .assets/39d5ff798c0771402486c6f1ca63f2a1868d80d9.svg | 1 + .assets/4820a9e881eaa3f3def4916e47e0c330b34ab151.svg | 1 + .assets/5dbd5b9335471c83b44949206c9b2186657b836f.svg | 1 + .assets/5f455cedf818a43aba043e71714721fd1e844501.svg | 1 + .assets/75cdb567a41d55d63ab2bb1326ea702df0bfacf4.svg | 1 + .assets/7bc797fb2b1f421fa40a6d9a0028d1f78db71dc0.svg | 1 + .assets/7ee454df22dbd82f0c1929bc14104d54c7081a49.svg | 1 + .assets/8aa25c38caec024924773d1a5c7c63ab45c4eecf.svg | 1 + .assets/8fc705464b3515a654de9893168a1b1321feccb4.svg | 1 + .assets/9c784d12784a084406c3794fbe177e93da4c3479.svg | 1 + .assets/a4faa118ed690be4e95fae01b8535036cda67e3d.svg | 1 + .assets/a9a0275265838d424840d721917e0a4e3a5d8044.svg | 1 + .assets/ac33ca939f6fc30c2fd799aaa6f59b0521c19e9f.svg | 1 + .assets/c229e34ea67f12eea11bf5403763207eeab38cff.svg | 1 + .assets/c277de9f9a155f6a0e47e0443845a3c9de5f6b84.svg | 1 + .assets/ceb223a18f5aad36d9f6087d1d468b4dd5ba56a1.svg | 1 + .assets/d8d51b9f960b17304a3bdcaf8922d3ae84b3c30f.svg | 1 + .assets/dcedb30554ccb68f317b952113777790df5ca547.svg | 1 + .assets/e6c7eef36a7e70a1f1b35633097516fe5e21508b.svg | 1 + .assets/ec2b4dc8236ac87f8058f121d86de1d99e029c5c.svg | 1 + .assets/fb6ebf3fa05cf980f374598b56757dbc5cae3662.svg | 1 + .assets/fe79e1c7a3e943262824d4f683059c85d91a233d.svg | 1 + lib/aave-helpers | 2 +- remappings.txt | 1 + 34 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 .assets/02a040db3fc4a88618783a9156e7fb51928e1ede.svg create mode 100644 .assets/03dc42930b2b94af37ef869d012c4734aedb52e6.svg create mode 100644 .assets/0afe490affc1bc77fe6675127b18e9aeeb4b1404.svg create mode 100644 .assets/0fcfb1e84443509c42e21db9e4320c00e1db6098.svg create mode 100644 .assets/1899e5ae4f4fd5b0d2565edd912a160acb2d0b78.svg create mode 100644 .assets/18e6ba583d4d35e38cb678120492b2b4d52d19ea.svg create mode 100644 .assets/1aa0fb636d34a35d35ce67919bc0d7d2e36d3839.svg create mode 100644 .assets/1c1fbd79406b4b3a8c64ec79ef429f7c422d0387.svg create mode 100644 .assets/2e9d5ba5e949c7896bc79e7fdd98872cb43375b0.svg create mode 100644 .assets/39a3707c0ded91bbfde8953567853db55452a227.svg create mode 100644 .assets/39d5ff798c0771402486c6f1ca63f2a1868d80d9.svg create mode 100644 .assets/4820a9e881eaa3f3def4916e47e0c330b34ab151.svg create mode 100644 .assets/5dbd5b9335471c83b44949206c9b2186657b836f.svg create mode 100644 .assets/5f455cedf818a43aba043e71714721fd1e844501.svg create mode 100644 .assets/75cdb567a41d55d63ab2bb1326ea702df0bfacf4.svg create mode 100644 .assets/7bc797fb2b1f421fa40a6d9a0028d1f78db71dc0.svg create mode 100644 .assets/7ee454df22dbd82f0c1929bc14104d54c7081a49.svg create mode 100644 .assets/8aa25c38caec024924773d1a5c7c63ab45c4eecf.svg create mode 100644 .assets/8fc705464b3515a654de9893168a1b1321feccb4.svg create mode 100644 .assets/9c784d12784a084406c3794fbe177e93da4c3479.svg create mode 100644 .assets/a4faa118ed690be4e95fae01b8535036cda67e3d.svg create mode 100644 .assets/a9a0275265838d424840d721917e0a4e3a5d8044.svg create mode 100644 .assets/ac33ca939f6fc30c2fd799aaa6f59b0521c19e9f.svg create mode 100644 .assets/c229e34ea67f12eea11bf5403763207eeab38cff.svg create mode 100644 .assets/c277de9f9a155f6a0e47e0443845a3c9de5f6b84.svg create mode 100644 .assets/ceb223a18f5aad36d9f6087d1d468b4dd5ba56a1.svg create mode 100644 .assets/d8d51b9f960b17304a3bdcaf8922d3ae84b3c30f.svg create mode 100644 .assets/dcedb30554ccb68f317b952113777790df5ca547.svg create mode 100644 .assets/e6c7eef36a7e70a1f1b35633097516fe5e21508b.svg create mode 100644 .assets/ec2b4dc8236ac87f8058f121d86de1d99e029c5c.svg create mode 100644 .assets/fb6ebf3fa05cf980f374598b56757dbc5cae3662.svg create mode 100644 .assets/fe79e1c7a3e943262824d4f683059c85d91a233d.svg diff --git a/.assets/02a040db3fc4a88618783a9156e7fb51928e1ede.svg b/.assets/02a040db3fc4a88618783a9156e7fb51928e1ede.svg new file mode 100644 index 000000000..db81caacb --- /dev/null +++ b/.assets/02a040db3fc4a88618783a9156e7fb51928e1ede.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/03dc42930b2b94af37ef869d012c4734aedb52e6.svg b/.assets/03dc42930b2b94af37ef869d012c4734aedb52e6.svg new file mode 100644 index 000000000..95de9c4ed --- /dev/null +++ b/.assets/03dc42930b2b94af37ef869d012c4734aedb52e6.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 30%Optimal utilization 30% \ No newline at end of file diff --git a/.assets/0afe490affc1bc77fe6675127b18e9aeeb4b1404.svg b/.assets/0afe490affc1bc77fe6675127b18e9aeeb4b1404.svg new file mode 100644 index 000000000..85a5bf372 --- /dev/null +++ b/.assets/0afe490affc1bc77fe6675127b18e9aeeb4b1404.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/0fcfb1e84443509c42e21db9e4320c00e1db6098.svg b/.assets/0fcfb1e84443509c42e21db9e4320c00e1db6098.svg new file mode 100644 index 000000000..5283877c6 --- /dev/null +++ b/.assets/0fcfb1e84443509c42e21db9e4320c00e1db6098.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/1899e5ae4f4fd5b0d2565edd912a160acb2d0b78.svg b/.assets/1899e5ae4f4fd5b0d2565edd912a160acb2d0b78.svg new file mode 100644 index 000000000..de0657eb7 --- /dev/null +++ b/.assets/1899e5ae4f4fd5b0d2565edd912a160acb2d0b78.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/18e6ba583d4d35e38cb678120492b2b4d52d19ea.svg b/.assets/18e6ba583d4d35e38cb678120492b2b4d52d19ea.svg new file mode 100644 index 000000000..db81caacb --- /dev/null +++ b/.assets/18e6ba583d4d35e38cb678120492b2b4d52d19ea.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/1aa0fb636d34a35d35ce67919bc0d7d2e36d3839.svg b/.assets/1aa0fb636d34a35d35ce67919bc0d7d2e36d3839.svg new file mode 100644 index 000000000..f05c3fb39 --- /dev/null +++ b/.assets/1aa0fb636d34a35d35ce67919bc0d7d2e36d3839.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/1c1fbd79406b4b3a8c64ec79ef429f7c422d0387.svg b/.assets/1c1fbd79406b4b3a8c64ec79ef429f7c422d0387.svg new file mode 100644 index 000000000..d003381d1 --- /dev/null +++ b/.assets/1c1fbd79406b4b3a8c64ec79ef429f7c422d0387.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/2e9d5ba5e949c7896bc79e7fdd98872cb43375b0.svg b/.assets/2e9d5ba5e949c7896bc79e7fdd98872cb43375b0.svg new file mode 100644 index 000000000..c752baefc --- /dev/null +++ b/.assets/2e9d5ba5e949c7896bc79e7fdd98872cb43375b0.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%2%4%Optimal utilization 99%Optimal utilization 99% \ No newline at end of file diff --git a/.assets/39a3707c0ded91bbfde8953567853db55452a227.svg b/.assets/39a3707c0ded91bbfde8953567853db55452a227.svg new file mode 100644 index 000000000..01584d9c0 --- /dev/null +++ b/.assets/39a3707c0ded91bbfde8953567853db55452a227.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/39d5ff798c0771402486c6f1ca63f2a1868d80d9.svg b/.assets/39d5ff798c0771402486c6f1ca63f2a1868d80d9.svg new file mode 100644 index 000000000..df2260094 --- /dev/null +++ b/.assets/39d5ff798c0771402486c6f1ca63f2a1868d80d9.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/4820a9e881eaa3f3def4916e47e0c330b34ab151.svg b/.assets/4820a9e881eaa3f3def4916e47e0c330b34ab151.svg new file mode 100644 index 000000000..403a5e0f3 --- /dev/null +++ b/.assets/4820a9e881eaa3f3def4916e47e0c330b34ab151.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/5dbd5b9335471c83b44949206c9b2186657b836f.svg b/.assets/5dbd5b9335471c83b44949206c9b2186657b836f.svg new file mode 100644 index 000000000..d348fb2d6 --- /dev/null +++ b/.assets/5dbd5b9335471c83b44949206c9b2186657b836f.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/5f455cedf818a43aba043e71714721fd1e844501.svg b/.assets/5f455cedf818a43aba043e71714721fd1e844501.svg new file mode 100644 index 000000000..5dff1554b --- /dev/null +++ b/.assets/5f455cedf818a43aba043e71714721fd1e844501.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/75cdb567a41d55d63ab2bb1326ea702df0bfacf4.svg b/.assets/75cdb567a41d55d63ab2bb1326ea702df0bfacf4.svg new file mode 100644 index 000000000..0bd7d00f7 --- /dev/null +++ b/.assets/75cdb567a41d55d63ab2bb1326ea702df0bfacf4.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 92%Optimal utilization 92% \ No newline at end of file diff --git a/.assets/7bc797fb2b1f421fa40a6d9a0028d1f78db71dc0.svg b/.assets/7bc797fb2b1f421fa40a6d9a0028d1f78db71dc0.svg new file mode 100644 index 000000000..e673fbc39 --- /dev/null +++ b/.assets/7bc797fb2b1f421fa40a6d9a0028d1f78db71dc0.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 92%Optimal utilization 92% \ No newline at end of file diff --git a/.assets/7ee454df22dbd82f0c1929bc14104d54c7081a49.svg b/.assets/7ee454df22dbd82f0c1929bc14104d54c7081a49.svg new file mode 100644 index 000000000..3c15ce1a6 --- /dev/null +++ b/.assets/7ee454df22dbd82f0c1929bc14104d54c7081a49.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/8aa25c38caec024924773d1a5c7c63ab45c4eecf.svg b/.assets/8aa25c38caec024924773d1a5c7c63ab45c4eecf.svg new file mode 100644 index 000000000..5283877c6 --- /dev/null +++ b/.assets/8aa25c38caec024924773d1a5c7c63ab45c4eecf.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/8fc705464b3515a654de9893168a1b1321feccb4.svg b/.assets/8fc705464b3515a654de9893168a1b1321feccb4.svg new file mode 100644 index 000000000..5212f2d4a --- /dev/null +++ b/.assets/8fc705464b3515a654de9893168a1b1321feccb4.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/9c784d12784a084406c3794fbe177e93da4c3479.svg b/.assets/9c784d12784a084406c3794fbe177e93da4c3479.svg new file mode 100644 index 000000000..081891402 --- /dev/null +++ b/.assets/9c784d12784a084406c3794fbe177e93da4c3479.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/a4faa118ed690be4e95fae01b8535036cda67e3d.svg b/.assets/a4faa118ed690be4e95fae01b8535036cda67e3d.svg new file mode 100644 index 000000000..93fde991f --- /dev/null +++ b/.assets/a4faa118ed690be4e95fae01b8535036cda67e3d.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%150%200%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/a9a0275265838d424840d721917e0a4e3a5d8044.svg b/.assets/a9a0275265838d424840d721917e0a4e3a5d8044.svg new file mode 100644 index 000000000..6af590b85 --- /dev/null +++ b/.assets/a9a0275265838d424840d721917e0a4e3a5d8044.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/ac33ca939f6fc30c2fd799aaa6f59b0521c19e9f.svg b/.assets/ac33ca939f6fc30c2fd799aaa6f59b0521c19e9f.svg new file mode 100644 index 000000000..3c15ce1a6 --- /dev/null +++ b/.assets/ac33ca939f6fc30c2fd799aaa6f59b0521c19e9f.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/c229e34ea67f12eea11bf5403763207eeab38cff.svg b/.assets/c229e34ea67f12eea11bf5403763207eeab38cff.svg new file mode 100644 index 000000000..771e3e22e --- /dev/null +++ b/.assets/c229e34ea67f12eea11bf5403763207eeab38cff.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/c277de9f9a155f6a0e47e0443845a3c9de5f6b84.svg b/.assets/c277de9f9a155f6a0e47e0443845a3c9de5f6b84.svg new file mode 100644 index 000000000..5212f2d4a --- /dev/null +++ b/.assets/c277de9f9a155f6a0e47e0443845a3c9de5f6b84.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/ceb223a18f5aad36d9f6087d1d468b4dd5ba56a1.svg b/.assets/ceb223a18f5aad36d9f6087d1d468b4dd5ba56a1.svg new file mode 100644 index 000000000..95de9c4ed --- /dev/null +++ b/.assets/ceb223a18f5aad36d9f6087d1d468b4dd5ba56a1.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 30%Optimal utilization 30% \ No newline at end of file diff --git a/.assets/d8d51b9f960b17304a3bdcaf8922d3ae84b3c30f.svg b/.assets/d8d51b9f960b17304a3bdcaf8922d3ae84b3c30f.svg new file mode 100644 index 000000000..ad84fcb3b --- /dev/null +++ b/.assets/d8d51b9f960b17304a3bdcaf8922d3ae84b3c30f.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 80%Optimal utilization 80% \ No newline at end of file diff --git a/.assets/dcedb30554ccb68f317b952113777790df5ca547.svg b/.assets/dcedb30554ccb68f317b952113777790df5ca547.svg new file mode 100644 index 000000000..b5810667c --- /dev/null +++ b/.assets/dcedb30554ccb68f317b952113777790df5ca547.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%20%40%60%80%Optimal utilization 92%Optimal utilization 92% \ No newline at end of file diff --git a/.assets/e6c7eef36a7e70a1f1b35633097516fe5e21508b.svg b/.assets/e6c7eef36a7e70a1f1b35633097516fe5e21508b.svg new file mode 100644 index 000000000..6af590b85 --- /dev/null +++ b/.assets/e6c7eef36a7e70a1f1b35633097516fe5e21508b.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%50%100%Optimal utilization 90%Optimal utilization 90% \ No newline at end of file diff --git a/.assets/ec2b4dc8236ac87f8058f121d86de1d99e029c5c.svg b/.assets/ec2b4dc8236ac87f8058f121d86de1d99e029c5c.svg new file mode 100644 index 000000000..f9bccbdd6 --- /dev/null +++ b/.assets/ec2b4dc8236ac87f8058f121d86de1d99e029c5c.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 70%Optimal utilization 70% \ No newline at end of file diff --git a/.assets/fb6ebf3fa05cf980f374598b56757dbc5cae3662.svg b/.assets/fb6ebf3fa05cf980f374598b56757dbc5cae3662.svg new file mode 100644 index 000000000..df2260094 --- /dev/null +++ b/.assets/fb6ebf3fa05cf980f374598b56757dbc5cae3662.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/.assets/fe79e1c7a3e943262824d4f683059c85d91a233d.svg b/.assets/fe79e1c7a3e943262824d4f683059c85d91a233d.svg new file mode 100644 index 000000000..5dff1554b --- /dev/null +++ b/.assets/fe79e1c7a3e943262824d4f683059c85d91a233d.svg @@ -0,0 +1 @@ + Borrow APR, variableBorrow APR, stable0%25%50%75%100%0%100%200%300%Optimal utilization 45%Optimal utilization 45% \ No newline at end of file diff --git a/lib/aave-helpers b/lib/aave-helpers index afd8bc415..7bbdb8bdd 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit afd8bc4153f5f9e1480f53e14ef7a764649c3a35 +Subproject commit 7bbdb8bddf62d45bfb6a91f3ad10bba23a4b8f0a diff --git a/remappings.txt b/remappings.txt index 03cc8b08c..e0fd78518 100644 --- a/remappings.txt +++ b/remappings.txt @@ -5,3 +5,4 @@ aave-v3-periphery/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src aave-v3-origin/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src/ forge-std/=lib/aave-helpers/lib/forge-std/src/ solidity-utils/=lib/aave-helpers/lib/solidity-utils/src/ +aave-ccip/=lib/aave-ccip/contracts/src/ From 19279210b1437936672e4c2efb5ab4bb3280f316 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:49:19 +0530 Subject: [PATCH 12/57] new: add proposal for eth & arb --- ...aintenanceCCIPV15Upgrade_20241017_after.md | 7 ++ ...aintenanceCCIPV15Upgrade_20241017_after.md | 7 ++ ...tionMaintenanceCCIPV15Upgrade_20241017.sol | 44 +++++++++ ...onMaintenanceCCIPV15Upgrade_20241017.t.sol | 86 ++++++++++++++++++ ...tionMaintenanceCCIPV15Upgrade_20241017.sol | 46 ++++++++++ ...onMaintenanceCCIPV15Upgrade_20241017.t.sol | 90 +++++++++++++++++++ ...CIPIntegrationMaintenanceCCIPV15Upgrade.md | 22 +++++ ...onMaintenanceCCIPV15Upgrade_20241017.s.sol | 90 +++++++++++++++++++ .../config.ts | 17 ++++ 9 files changed, 409 insertions(+) create mode 100644 diffs/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md create mode 100644 diffs/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol create mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts diff --git a/diffs/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md b/diffs/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md new file mode 100644 index 000000000..dbd03dce4 --- /dev/null +++ b/diffs/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md @@ -0,0 +1,7 @@ +## Emodes changes + +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/diffs/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md b/diffs/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md new file mode 100644 index 000000000..dbd03dce4 --- /dev/null +++ b/diffs/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md @@ -0,0 +1,7 @@ +## Emodes changes + +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol new file mode 100644 index 000000000..53ae5181c --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; + +/** + * @title GHO CCIP Integration Maintenance (CCIP v1.5 upgrade) + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 is + IProposalGenericExecutor +{ + function execute() external override { + // ProxyPool deployed by chainlink + address proxyPool = address(1337); // todo: MiscArbitrum.GHO_CCIP_PROXY_POOL + + UpgradeableBurnMintTokenPool tokenPoolProxy = UpgradeableBurnMintTokenPool( + MiscArbitrum.GHO_CCIP_TOKEN_POOL + ); + + // Deploy new tokenPool implementation, retain existing immutable configuration + address tokenPool = address( + new UpgradeableBurnMintTokenPool( + address(tokenPoolProxy.getToken()), + tokenPoolProxy.getArmProxy(), + tokenPoolProxy.getAllowListEnabled() + ) + ); + + ProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( + TransparentUpgradeableProxy(payable(address(tokenPoolProxy))), + tokenPool + ); + + // Update proxyPool address + tokenPoolProxy.setProxyPool(proxyPool); + } +} diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol new file mode 100644 index 000000000..fa63fe6b1 --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; + +/** + * @dev Test for AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 + * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol -vv --contracts src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade + */ +contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Test is + ProtocolV3TestBase +{ + AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 internal proposal; + address internal proxyPool; + UpgradeableBurnMintTokenPool internal tokenPoolProxy; + + uint64 internal constant ARB_ETH_CHAIN_SELECTOR = 5009297550715157269; + + event Burned(address indexed sender, uint256 amount); + + error CallerIsNotARampOnRouter(address caller); + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('arbitrum'), 264780207); + proposal = new AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017(); + + // ProxyPool deployed by chainlink + proxyPool = address(1337); // todo: MiscArbitrum.GHO_CCIP_PROXY_POOL + tokenPoolProxy = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017', + AaveV3Arbitrum.POOL, + address(proposal) + ); + } + + function test_getProxyPool() public { + // proxyPool getter does not exist before the upgrade + vm.expectRevert(); + tokenPoolProxy.getProxyPool(); + + executePayload(vm, address(proposal)); + + assertEq(tokenPoolProxy.getProxyPool(), proxyPool); + } + + function test_proxyPoolCanOnRamp() public { + address alice = makeAddr('alice'); + uint256 amount = 1337e18; + + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); + vm.prank(proxyPool); + tokenPoolProxy.lockOrBurn( + alice, + abi.encode(alice), + amount, + ARB_ETH_CHAIN_SELECTOR, + new bytes(0) + ); + + executePayload(vm, address(proposal)); + + vm.expectEmit(); + emit Burned(proxyPool, amount); + vm.prank(proxyPool); + tokenPoolProxy.lockOrBurn( + alice, + abi.encode(alice), + amount, + ARB_ETH_CHAIN_SELECTOR, + new bytes(0) + ); + } +} diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol new file mode 100644 index 000000000..5274b7e81 --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; + +/** + + * @title GHO CCIP Integration Maintenance (CCIP v1.5 upgrade) + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 is + IProposalGenericExecutor +{ + function execute() external override { + // ProxyPool deployed by chainlink + address proxyPool = address(1337); // todo: MiscEthereum.GHO_CCIP_PROXY_POOL + + UpgradeableLockReleaseTokenPool tokenPoolProxy = UpgradeableLockReleaseTokenPool( + MiscEthereum.GHO_CCIP_TOKEN_POOL + ); + + // Deploy new tokenPool implementation, retain existing immutable configuration + address tokenPool = address( + new UpgradeableLockReleaseTokenPool( + address(tokenPoolProxy.getToken()), + tokenPoolProxy.getArmProxy(), + tokenPoolProxy.getAllowListEnabled(), + tokenPoolProxy.canAcceptLiquidity() + ) + ); + + ProxyAdmin(MiscEthereum.PROXY_ADMIN).upgrade( + TransparentUpgradeableProxy(payable(address(tokenPoolProxy))), + tokenPool + ); + + // Update proxyPool address + tokenPoolProxy.setProxyPool(proxyPool); + } +} diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol new file mode 100644 index 000000000..50fba4874 --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; + +/** + * @dev Test for AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 + * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol -vv --contracts src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade + */ +contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Test is + ProtocolV3TestBase +{ + AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 internal proposal; + address internal proxyPool; + UpgradeableLockReleaseTokenPool internal tokenPoolProxy; + + uint64 internal constant ETH_ARB_CHAIN_SELECTOR = 4949039107694359620; + + event Locked(address indexed sender, uint256 amount); + + error CallerIsNotARampOnRouter(address caller); + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 20985823); + proposal = new AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017(); + + // ProxyPool deployed by chainlink + proxyPool = address(1337); // todo: MiscEthereum.GHO_CCIP_PROXY_POOL + tokenPoolProxy = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017', + AaveV3Ethereum.POOL, + address(proposal) + ); + } + + function test_getProxyPool() public { + // proxyPool getter does not exist before the upgrade + vm.expectRevert(); + tokenPoolProxy.getProxyPool(); + + executePayload(vm, address(proposal)); + + assertEq(tokenPoolProxy.getProxyPool(), proxyPool); + } + + function test_proxyPoolCanOnRamp() public { + address alice = makeAddr('alice'); + uint256 amount = 1337e18; + + uint256 bridgedAmount = tokenPoolProxy.getCurrentBridgedAmount(); + + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); + vm.prank(proxyPool); + tokenPoolProxy.lockOrBurn( + alice, + abi.encode(alice), + amount, + ETH_ARB_CHAIN_SELECTOR, + new bytes(0) + ); + + executePayload(vm, address(proposal)); + + vm.expectEmit(); + emit Locked(proxyPool, amount); + vm.prank(proxyPool); + tokenPoolProxy.lockOrBurn( + alice, + abi.encode(alice), + amount, + ETH_ARB_CHAIN_SELECTOR, + new bytes(0) + ); + + assertEq(tokenPoolProxy.getCurrentBridgedAmount(), bridgedAmount + amount); + } +} diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md new file mode 100644 index 000000000..39ebe5faa --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md @@ -0,0 +1,22 @@ +--- +title: "GHO CCIP Integration Maintenance (CCIP v1.5 upgrade)" +author: "Aave Labs" +discussions: "" +--- + +## Simple Summary + +## Motivation + +## Specification + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol) +- [Snapshot](TODO) +- [Discussion](TODO) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol new file mode 100644 index 000000000..816453303 --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/src/GovV3Helpers.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {EthereumScript, ArbitrumScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol'; +import {AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; +import {AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol:DeployEthereum chain=mainnet + * verify-command: FOUNDRY_PROFILE=mainnet npx catapulta-verify -b broadcast/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + ); + + // compose action + IPayloadsControllerCore.ExecutionAction[] + memory actions = new IPayloadsControllerCore.ExecutionAction[](1); + actions[0] = GovV3Helpers.buildAction(payload0); + + // register action at payloadsController + GovV3Helpers.createPayload(actions); + } +} + +/** + * @dev Deploy Arbitrum + * deploy-command: make deploy-ledger contract=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol:DeployArbitrum chain=arbitrum + * verify-command: FOUNDRY_PROFILE=arbitrum npx catapulta-verify -b broadcast/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol/42161/run-latest.json + */ +contract DeployArbitrum is ArbitrumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + ); + + // compose action + IPayloadsControllerCore.ExecutionAction[] + memory actions = new IPayloadsControllerCore.ExecutionAction[](1); + actions[0] = GovV3Helpers.buildAction(payload0); + + // register action at payloadsController + GovV3Helpers.createPayload(actions); + } +} + +/** + * @dev Create Proposal + * command: make deploy-ledger contract=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol:CreateProposal chain=mainnet + */ +contract CreateProposal is EthereumScript { + function run() external { + // create payloads + PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](2); + + // compose actions for validation + IPayloadsControllerCore.ExecutionAction[] + memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsEthereum[0] = GovV3Helpers.buildAction( + type(AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + IPayloadsControllerCore.ExecutionAction[] + memory actionsArbitrum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsArbitrum[0] = GovV3Helpers.buildAction( + type(AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + ); + payloads[1] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovernanceV3Ethereum.VOTING_PORTAL_ETH_POL, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md' + ) + ); + } +} diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts new file mode 100644 index 000000000..4b3436f76 --- /dev/null +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts @@ -0,0 +1,17 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum', 'AaveV3Arbitrum'], + title: 'GHO CCIP Integration Maintenance (CCIP v1.5 upgrade)', + shortName: 'GHOCCIPIntegrationMaintenanceCCIPV15Upgrade', + date: '20241017', + author: 'Aave Labs', + discussion: '', + snapshot: '', + votingNetwork: 'POLYGON', + }, + poolOptions: { + AaveV3Ethereum: {configs: {}, cache: {blockNumber: 20985823}}, + AaveV3Arbitrum: {configs: {}, cache: {blockNumber: 264780207}}, + }, +}; From 9cc57694e5c609c50ea2cb3d05ce66e6d36c3046 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:06:39 +0530 Subject: [PATCH 13/57] fix: arb test supply locked invariant --- ..._GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol index fa63fe6b1..507987a4b 100644 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol +++ b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol @@ -60,6 +60,9 @@ contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Tes address alice = makeAddr('alice'); uint256 amount = 1337e18; + // mock previously bridged gho on token pool + deal(address(tokenPoolProxy.getToken()), address(tokenPoolProxy), amount); + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); vm.prank(proxyPool); tokenPoolProxy.lockOrBurn( From 58e177d21c2c6c993f7463c579f90157b218bb90 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 22 Oct 2024 00:10:34 +0530 Subject: [PATCH 14/57] fix: rename, add discussion link --- ...itrum_GHOCCIP150Upgrade_20241021_after.md} | 0 ...ereum_GHOCCIP150Upgrade_20241021_after.md} | 0 ...CIPIntegrationMaintenanceCCIPV15Upgrade.md | 22 --------------- .../config.ts | 17 ------------ ...V3Arbitrum_GHOCCIP150Upgrade_20241021.sol} | 19 ++++++------- ...Arbitrum_GHOCCIP150Upgrade_20241021.t.sol} | 27 ++++++++----------- ...V3Ethereum_GHOCCIP150Upgrade_20241021.sol} | 20 ++++++-------- ...Ethereum_GHOCCIP150Upgrade_20241021.t.sol} | 27 ++++++++----------- .../GHOCCIP150Upgrade.md | 22 +++++++++++++++ .../GHOCCIP150Upgrade_20241021.s.sol} | 27 +++++++++---------- .../config.ts | 17 ++++++++++++ 11 files changed, 89 insertions(+), 109 deletions(-) rename diffs/{AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md => AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_before_AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_after.md} (100%) rename diffs/{AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md => AaveV3Ethereum_GHOCCIP150Upgrade_20241021_before_AaveV3Ethereum_GHOCCIP150Upgrade_20241021_after.md} (100%) delete mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md delete mode 100644 src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts rename src/{20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol => 20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol} (71%) rename src/{20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol => 20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol} (68%) rename src/{20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol => 20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol} (72%) rename src/{20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol => 20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol} (68%) create mode 100644 src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md rename src/{20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol => 20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol} (59%) create mode 100644 src/20241021_Multi_GHOCCIP150Upgrade/config.ts diff --git a/diffs/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md b/diffs/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_before_AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_after.md similarity index 100% rename from diffs/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md rename to diffs/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_before_AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_after.md diff --git a/diffs/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md b/diffs/AaveV3Ethereum_GHOCCIP150Upgrade_20241021_before_AaveV3Ethereum_GHOCCIP150Upgrade_20241021_after.md similarity index 100% rename from diffs/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_before_AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_after.md rename to diffs/AaveV3Ethereum_GHOCCIP150Upgrade_20241021_before_AaveV3Ethereum_GHOCCIP150Upgrade_20241021_after.md diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md deleted file mode 100644 index 39ebe5faa..000000000 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "GHO CCIP Integration Maintenance (CCIP v1.5 upgrade)" -author: "Aave Labs" -discussions: "" ---- - -## Simple Summary - -## Motivation - -## Specification - -## References - -- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol) -- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol) -- [Snapshot](TODO) -- [Discussion](TODO) - -## Copyright - -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts b/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts deleted file mode 100644 index 4b3436f76..000000000 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/config.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {ConfigFile} from '../../generator/types'; -export const config: ConfigFile = { - rootOptions: { - pools: ['AaveV3Ethereum', 'AaveV3Arbitrum'], - title: 'GHO CCIP Integration Maintenance (CCIP v1.5 upgrade)', - shortName: 'GHOCCIPIntegrationMaintenanceCCIPV15Upgrade', - date: '20241017', - author: 'Aave Labs', - discussion: '', - snapshot: '', - votingNetwork: 'POLYGON', - }, - poolOptions: { - AaveV3Ethereum: {configs: {}, cache: {blockNumber: 20985823}}, - AaveV3Arbitrum: {configs: {}, cache: {blockNumber: 264780207}}, - }, -}; diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol similarity index 71% rename from src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol rename to src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 53ae5181c..d3e96153b 100644 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -8,24 +8,21 @@ import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin. import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; /** - * @title GHO CCIP Integration Maintenance (CCIP v1.5 upgrade) + * @title GHO CCIP 1.50 Upgrade * @author Aave Labs * - Snapshot: TODO - * - Discussion: TODO + * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ -contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 is - IProposalGenericExecutor -{ - function execute() external override { - // ProxyPool deployed by chainlink - address proxyPool = address(1337); // todo: MiscArbitrum.GHO_CCIP_PROXY_POOL +contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { + address public constant GHO_CCIP_PROXY_POOL = address(1337); // placeholder: pending chainlink deployment + function execute() external { UpgradeableBurnMintTokenPool tokenPoolProxy = UpgradeableBurnMintTokenPool( MiscArbitrum.GHO_CCIP_TOKEN_POOL ); // Deploy new tokenPool implementation, retain existing immutable configuration - address tokenPool = address( + address tokenPoolImpl = address( new UpgradeableBurnMintTokenPool( address(tokenPoolProxy.getToken()), tokenPoolProxy.getArmProxy(), @@ -35,10 +32,10 @@ contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 is ProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( TransparentUpgradeableProxy(payable(address(tokenPoolProxy))), - tokenPool + tokenPoolImpl ); // Update proxyPool address - tokenPoolProxy.setProxyPool(proxyPool); + tokenPoolProxy.setProxyPool(GHO_CCIP_PROXY_POOL); } } diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol similarity index 68% rename from src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol rename to src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 507987a4b..2592f6052 100644 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -1,24 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; - import 'forge-std/Test.sol'; +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; /** - * @dev Test for AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 - * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol -vv --contracts src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade + * @dev Test for AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 + * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol -vv */ -contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Test is - ProtocolV3TestBase -{ - AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 internal proposal; - address internal proxyPool; +contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { + AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 internal proposal; UpgradeableBurnMintTokenPool internal tokenPoolProxy; + address internal proxyPool; uint64 internal constant ARB_ETH_CHAIN_SELECTOR = 5009297550715157269; @@ -27,12 +24,10 @@ contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Tes error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 264780207); - proposal = new AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017(); - - // ProxyPool deployed by chainlink - proxyPool = address(1337); // todo: MiscArbitrum.GHO_CCIP_PROXY_POOL + vm.createSelectFork(vm.rpcUrl('arbitrum'), 266210927); + proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); tokenPoolProxy = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + proxyPool = proposal.GHO_CCIP_PROXY_POOL(); } /** @@ -40,7 +35,7 @@ contract AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Tes */ function test_defaultProposalExecution() public { defaultTest( - 'AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017', + 'AaveV3Arbitrum_GHOCCIP150Upgrade_20241021', AaveV3Arbitrum.POOL, address(proposal) ); diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol similarity index 72% rename from src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol rename to src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 5274b7e81..0ec1e12b5 100644 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -8,25 +8,21 @@ import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin. import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; /** - - * @title GHO CCIP Integration Maintenance (CCIP v1.5 upgrade) + * @title GHO CCIP 1.50 Upgrade * @author Aave Labs * - Snapshot: TODO - * - Discussion: TODO + * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ -contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 is - IProposalGenericExecutor -{ - function execute() external override { - // ProxyPool deployed by chainlink - address proxyPool = address(1337); // todo: MiscEthereum.GHO_CCIP_PROXY_POOL +contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { + address public constant GHO_CCIP_PROXY_POOL = address(1337); // placeholder: pending chainlink deployment + function execute() external { UpgradeableLockReleaseTokenPool tokenPoolProxy = UpgradeableLockReleaseTokenPool( MiscEthereum.GHO_CCIP_TOKEN_POOL ); // Deploy new tokenPool implementation, retain existing immutable configuration - address tokenPool = address( + address tokenPoolImpl = address( new UpgradeableLockReleaseTokenPool( address(tokenPoolProxy.getToken()), tokenPoolProxy.getArmProxy(), @@ -37,10 +33,10 @@ contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 is ProxyAdmin(MiscEthereum.PROXY_ADMIN).upgrade( TransparentUpgradeableProxy(payable(address(tokenPoolProxy))), - tokenPool + tokenPoolImpl ); // Update proxyPool address - tokenPoolProxy.setProxyPool(proxyPool); + tokenPoolProxy.setProxyPool(GHO_CCIP_PROXY_POOL); } } diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol similarity index 68% rename from src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol rename to src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 50fba4874..b5f08c17c 100644 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -1,24 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; - import 'forge-std/Test.sol'; +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; /** - * @dev Test for AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 - * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.t.sol -vv --contracts src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade + * @dev Test for AaveV3Ethereum_GHOCCIP150Upgrade_20241021 + * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol -vv */ -contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Test is - ProtocolV3TestBase -{ - AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017 internal proposal; - address internal proxyPool; +contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { + AaveV3Ethereum_GHOCCIP150Upgrade_20241021 internal proposal; UpgradeableLockReleaseTokenPool internal tokenPoolProxy; + address internal proxyPool; uint64 internal constant ETH_ARB_CHAIN_SELECTOR = 4949039107694359620; @@ -27,12 +24,10 @@ contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Tes error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 20985823); - proposal = new AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017(); - - // ProxyPool deployed by chainlink - proxyPool = address(1337); // todo: MiscEthereum.GHO_CCIP_PROXY_POOL + vm.createSelectFork(vm.rpcUrl('mainnet'), 21015645); + proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); tokenPoolProxy = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + proxyPool = proposal.GHO_CCIP_PROXY_POOL(); } /** @@ -40,7 +35,7 @@ contract AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017_Tes */ function test_defaultProposalExecution() public { defaultTest( - 'AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017', + 'AaveV3Ethereum_GHOCCIP150Upgrade_20241021', AaveV3Ethereum.POOL, address(proposal) ); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md new file mode 100644 index 000000000..de8f4b8b5 --- /dev/null +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -0,0 +1,22 @@ +--- +title: "GHO CCIP 1.50 Upgrade" +author: "Aave Labs" +discussions: "https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51" +--- + +## Simple Summary + +## Motivation + +## Specification + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol) +- [Snapshot](TODO) +- [Discussion](https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol similarity index 59% rename from src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol rename to src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol index 816453303..728f912ec 100644 --- a/src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol @@ -4,19 +4,19 @@ pragma solidity ^0.8.0; import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/src/GovV3Helpers.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {EthereumScript, ArbitrumScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol'; -import {AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; -import {AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017} from './AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.sol'; +import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; +import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; /** * @dev Deploy Ethereum - * deploy-command: make deploy-ledger contract=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol:DeployEthereum chain=mainnet - * verify-command: FOUNDRY_PROFILE=mainnet npx catapulta-verify -b broadcast/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol/1/run-latest.json + * deploy-command: make deploy-ledger contract=src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol:DeployEthereum chain=mainnet + * verify-command: FOUNDRY_PROFILE=mainnet npx catapulta-verify -b broadcast/GHOCCIP150Upgrade_20241021.s.sol/1/run-latest.json */ contract DeployEthereum is EthereumScript { function run() external broadcast { // deploy payloads address payload0 = GovV3Helpers.deployDeterministic( - type(AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + type(AaveV3Ethereum_GHOCCIP150Upgrade_20241021).creationCode ); // compose action @@ -31,14 +31,14 @@ contract DeployEthereum is EthereumScript { /** * @dev Deploy Arbitrum - * deploy-command: make deploy-ledger contract=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol:DeployArbitrum chain=arbitrum - * verify-command: FOUNDRY_PROFILE=arbitrum npx catapulta-verify -b broadcast/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol/42161/run-latest.json + * deploy-command: make deploy-ledger contract=src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol:DeployArbitrum chain=arbitrum + * verify-command: FOUNDRY_PROFILE=arbitrum npx catapulta-verify -b broadcast/GHOCCIP150Upgrade_20241021.s.sol/42161/run-latest.json */ contract DeployArbitrum is ArbitrumScript { function run() external broadcast { // deploy payloads address payload0 = GovV3Helpers.deployDeterministic( - type(AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + type(AaveV3Arbitrum_GHOCCIP150Upgrade_20241021).creationCode ); // compose action @@ -53,7 +53,7 @@ contract DeployArbitrum is ArbitrumScript { /** * @dev Create Proposal - * command: make deploy-ledger contract=src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017.s.sol:CreateProposal chain=mainnet + * command: make deploy-ledger contract=src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol:CreateProposal chain=mainnet */ contract CreateProposal is EthereumScript { function run() external { @@ -64,14 +64,14 @@ contract CreateProposal is EthereumScript { IPayloadsControllerCore.ExecutionAction[] memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); actionsEthereum[0] = GovV3Helpers.buildAction( - type(AaveV3Ethereum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + type(AaveV3Ethereum_GHOCCIP150Upgrade_20241021).creationCode ); payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); IPayloadsControllerCore.ExecutionAction[] memory actionsArbitrum = new IPayloadsControllerCore.ExecutionAction[](1); actionsArbitrum[0] = GovV3Helpers.buildAction( - type(AaveV3Arbitrum_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade_20241017).creationCode + type(AaveV3Arbitrum_GHOCCIP150Upgrade_20241021).creationCode ); payloads[1] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum); @@ -81,10 +81,7 @@ contract CreateProposal is EthereumScript { vm, payloads, GovernanceV3Ethereum.VOTING_PORTAL_ETH_POL, - GovV3Helpers.ipfsHashFile( - vm, - 'src/20241017_Multi_GHOCCIPIntegrationMaintenanceCCIPV15Upgrade/GHOCCIPIntegrationMaintenanceCCIPV15Upgrade.md' - ) + GovV3Helpers.ipfsHashFile(vm, 'src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md') ); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts new file mode 100644 index 000000000..bbdd55c2f --- /dev/null +++ b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts @@ -0,0 +1,17 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum', 'AaveV3Arbitrum'], + title: 'GHO CCIP 1.50 Upgrade', + shortName: 'GHOCCIP150Upgrade', + date: '20241021', + author: 'Aave Labs', + discussion: 'https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51', + snapshot: '', + votingNetwork: 'POLYGON', + }, + poolOptions: { + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21015645}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 266210927}}, + }, +}; From a3310b80d946ac114fb4b3be1fd819a29f1cf48c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:44:50 +0530 Subject: [PATCH 15/57] upd: aave-ccip module --- lib/aave-ccip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aave-ccip b/lib/aave-ccip index 623c10c20..47a535bb3 160000 --- a/lib/aave-ccip +++ b/lib/aave-ccip @@ -1 +1 @@ -Subproject commit 623c10c203d5187eeb82a998ce3c01ea94bce6d9 +Subproject commit 47a535bb3b5829c6d015fcdf8ccdc1357520a2c1 From a78018df740760cc625646969ca89dabea9580fc Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:46:00 +0530 Subject: [PATCH 16/57] feat: add proxy pool deployments --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 2 +- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index d3e96153b..273048d87 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -14,7 +14,7 @@ import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/Upgrad * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { - address public constant GHO_CCIP_PROXY_POOL = address(1337); // placeholder: pending chainlink deployment + address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; function execute() external { UpgradeableBurnMintTokenPool tokenPoolProxy = UpgradeableBurnMintTokenPool( diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 0ec1e12b5..3722ccc9b 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -14,7 +14,7 @@ import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/Upg * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { - address public constant GHO_CCIP_PROXY_POOL = address(1337); // placeholder: pending chainlink deployment + address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; function execute() external { UpgradeableLockReleaseTokenPool tokenPoolProxy = UpgradeableLockReleaseTokenPool( From f962303602ae84344561a67914b35198c2f93804 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:47:33 +0530 Subject: [PATCH 17/57] feat: add e2e tests --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 289 +++++++- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 653 ++++++++++++++++++ ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 325 ++++++++- .../utils/CCIPUtils.sol | 152 ++++ src/interfaces/IERC20.sol | 78 +++ src/interfaces/ccip/IEVM2EVMOffRamp.sol | 16 +- src/interfaces/ccip/IEVM2EVMOnRamp.sol | 32 + src/interfaces/ccip/IInternal.sol | 5 + src/interfaces/ccip/IProxyPool.sol | 22 + src/interfaces/ccip/IRateLimiter.sol | 11 + src/interfaces/ccip/IRouter.sol | 42 +- src/interfaces/ccip/ITokenAdminRegistry.sol | 13 + src/interfaces/ccip/ITypeAndVersion.sol | 6 + 13 files changed, 1573 insertions(+), 71 deletions(-) create mode 100644 src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol create mode 100644 src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol create mode 100644 src/interfaces/IERC20.sol create mode 100644 src/interfaces/ccip/IEVM2EVMOnRamp.sol create mode 100644 src/interfaces/ccip/IProxyPool.sol create mode 100644 src/interfaces/ccip/IRateLimiter.sol create mode 100644 src/interfaces/ccip/ITokenAdminRegistry.sol create mode 100644 src/interfaces/ccip/ITypeAndVersion.sol diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 2592f6052..dfcd23816 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -3,9 +3,20 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; +import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; +import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IERC20} from 'src/interfaces/IERC20.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {CCIPUtils} from './utils/CCIPUtils.sol'; + import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; /** @@ -13,72 +24,292 @@ import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCI * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol -vv */ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { + struct CCIPSendParams { + IRouter router; + uint256 amount; + bool migrated; + } + AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 internal proposal; - UpgradeableBurnMintTokenPool internal tokenPoolProxy; - address internal proxyPool; + UpgradeableBurnMintTokenPool internal ghoTokenPool; + IProxyPool internal proxyPool; - uint64 internal constant ARB_ETH_CHAIN_SELECTOR = 5009297550715157269; + address internal alice = makeAddr('alice'); + + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + address internal constant ARB_GHO_TOKEN = 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33; + address internal constant ETH_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + + address internal constant ON_RAMP_1_2 = 0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE; + address internal constant ON_RAMP_1_5 = 0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3; + address internal constant OFF_RAMP_1_2 = 0x542ba1902044069330e8c5b36A84EC503863722f; + address internal constant OFF_RAMP_1_5 = 0x91e46cc5590A4B9182e47f40006140A7077Dec31; event Burned(address indexed sender, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + event CCIPSendRequested(IInternal.EVM2EVMMessage message); error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 266210927); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 267660907); proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); - tokenPoolProxy = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); - proxyPool = proposal.GHO_CCIP_PROXY_POOL(); + ghoTokenPool = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); + + _validateConstants(); } /** * @dev executes the generic test suite including e2e and config snapshots */ function test_defaultProposalExecution() public { + bytes memory dynamicParamsBefore = _getDynamicParams(); + bytes memory staticParamsBefore = _getStaticParams(); + defaultTest( 'AaveV3Arbitrum_GHOCCIP150Upgrade_20241021', AaveV3Arbitrum.POOL, address(proposal) ); + assertEq(keccak256(_getDynamicParams()), keccak256(dynamicParamsBefore)); + assertEq(keccak256(_getStaticParams()), keccak256(staticParamsBefore)); } function test_getProxyPool() public { // proxyPool getter does not exist before the upgrade vm.expectRevert(); - tokenPoolProxy.getProxyPool(); + ghoTokenPool.getProxyPool(); executePayload(vm, address(proposal)); - assertEq(tokenPoolProxy.getProxyPool(), proxyPool); + assertEq(ghoTokenPool.getProxyPool(), address(proxyPool)); + } + + function test_tokenPoolCannotBeInitializedAgain() public { + vm.expectRevert('Initializable: contract is already initialized'); + ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); + /// proxy implementation is initialized + assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); + + executePayload(vm, address(proposal)); + + vm.expectRevert('Initializable: contract is already initialized'); + ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); + /// proxy implementation is initialized + assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); + } + + function test_sendMessagePreCCIPMigration() public { + executePayload(vm, address(proposal)); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + IRouter router = IRouter(ghoTokenPool.getRouter()); + uint256 amount = 500_000e18; + vm.prank(alice); + gho.approve(address(router), amount); + deal(address(gho), alice, amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: false})); + + vm.expectEmit(); + emit Burned(ON_RAMP_1_2, amount); + vm.expectEmit(); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + + assertEq(gho.balanceOf(alice), 0); + } + + function test_sendMessagePostCCIPMigration() public { + executePayload(vm, address(proposal)); + + _mockCCIPMigration(); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + IRouter router = IRouter(ghoTokenPool.getRouter()); + uint256 amount = 500_000e18; + vm.prank(alice); + gho.approve(address(router), amount); + deal(address(gho), alice, amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: true})); + + vm.expectEmit(); + emit Burned(ON_RAMP_1_5, amount); + vm.expectEmit(); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + + assertEq(gho.balanceOf(alice), 0); + } + + function test_executeMessagePreCCIPMigration() public { + executePayload(vm, address(proposal)); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + uint256 amount = 500_000e18; + // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) + deal(address(gho), address(ghoTokenPool), amount); + + vm.expectEmit(); + emit Minted(OFF_RAMP_1_2, alice, amount); + vm.prank(OFF_RAMP_1_2); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); + + assertEq(gho.balanceOf(alice), amount); + } + + function test_executeMessagePostCCIPMigration() public { + executePayload(vm, address(proposal)); + + _mockCCIPMigration(); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + uint256 amount = 500_000e18; + // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) + deal(address(gho), address(ghoTokenPool), amount); + + vm.expectEmit(); + emit Minted(OFF_RAMP_1_5, alice, amount); + vm.prank(OFF_RAMP_1_5); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); + + assertEq(gho.balanceOf(alice), amount); } function test_proxyPoolCanOnRamp() public { - address alice = makeAddr('alice'); uint256 amount = 1337e18; - // mock previously bridged gho on token pool - deal(address(tokenPoolProxy.getToken()), address(tokenPoolProxy), amount); - vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); - vm.prank(proxyPool); - tokenPoolProxy.lockOrBurn( - alice, - abi.encode(alice), - amount, - ARB_ETH_CHAIN_SELECTOR, - new bytes(0) - ); + vm.prank(address(proxyPool)); + ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ETH_CHAIN_SELECTOR, new bytes(0)); executePayload(vm, address(proposal)); + // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) + deal(ARB_GHO_TOKEN, address(ghoTokenPool), amount); vm.expectEmit(); - emit Burned(proxyPool, amount); - vm.prank(proxyPool); - tokenPoolProxy.lockOrBurn( - alice, - abi.encode(alice), - amount, - ARB_ETH_CHAIN_SELECTOR, - new bytes(0) + emit Burned(address(proxyPool), amount); + vm.prank(address(proxyPool)); + ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ETH_CHAIN_SELECTOR, new bytes(0)); + } + + function _mockCCIPMigration() private { + IRouter router = IRouter(ghoTokenPool.getRouter()); + // token registry not set for 1.5 migration + assertEq(TOKEN_ADMIN_REGISTRY.getPool(ARB_GHO_TOKEN), address(0)); + vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.proposeAdministrator(ARB_GHO_TOKEN, TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(ARB_GHO_TOKEN); + TOKEN_ADMIN_REGISTRY.setPool(ARB_GHO_TOKEN, address(proxyPool)); + vm.stopPrank(); + assertEq(TOKEN_ADMIN_REGISTRY.getPool(ARB_GHO_TOKEN), address(proxyPool)); + + assertEq(proxyPool.getRouter(), address(router)); + + IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); + chains[0] = IProxyPool.ChainUpdate({ + remoteChainSelector: ETH_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(ETH_PROXY_POOL), + remoteTokenAddress: abi.encode(address(MiscEthereum.GHO_TOKEN)), + allowed: true, + outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + vm.prank(proxyPool.owner()); + proxyPool.applyChainUpdates(chains); + + assertTrue(proxyPool.isSupportedChain(ETH_CHAIN_SELECTOR)); + + IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); + onRampUpdates[0] = IRouter.OnRamp({ + destChainSelector: ETH_CHAIN_SELECTOR, + onRamp: ON_RAMP_1_5 // new onRamp + }); + IRouter.OffRamp[] memory offRampUpdates = new IRouter.OffRamp[](1); + offRampUpdates[0] = IRouter.OffRamp({ + sourceChainSelector: ARB_CHAIN_SELECTOR, + offRamp: OFF_RAMP_1_5 // new offRamp + }); + + vm.prank(router.owner()); + router.applyRampUpdates(onRampUpdates, new IRouter.OffRamp[](0), offRampUpdates); + } + + function _getTokenMessage( + CCIPSendParams memory params + ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { + IClient.EVM2AnyMessage memory message = CCIPUtils.generateMessage(alice, 1); + message.tokenAmounts[0] = IClient.EVMTokenAmount({token: ARB_GHO_TOKEN, amount: params.amount}); + + uint256 feeAmount = params.router.getFee(ETH_CHAIN_SELECTOR, message); + deal(alice, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: params.router, + sourceChainSelector: ARB_CHAIN_SELECTOR, + feeTokenAmount: feeAmount, + originalSender: alice, + destinationToken: MiscEthereum.GHO_TOKEN, + migrated: params.migrated + }) ); + + return (message, eventArg); + } + + function _getImplementation(address proxy) private view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) private view returns (uint8) { + /// slot 0 + // <1 byte ^ 1 byte ^ ---------- 20 bytes ----------> + // initialized initializing owner + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function _getStaticParams() private view returns (bytes memory) { + return + abi.encode( + address(ghoTokenPool.getToken()), + ghoTokenPool.getAllowList(), + ghoTokenPool.getArmProxy(), + ghoTokenPool.getRouter() + ); + } + + function _getDynamicParams() private view returns (bytes memory) { + return + abi.encode( + ghoTokenPool.owner(), + ghoTokenPool.getSupportedChains(), + ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR) + ); + } + + function _validateConstants() private pure { + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(ITypeAndVersion(ON_RAMP_1_2).typeAndVersion(), 'EVM2EVMOnRamp 1.2.0'); + assertEq(ITypeAndVersion(ON_RAMP_1_5).typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); + assertEq(ITypeAndVersion(OFF_RAMP_1_5).typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol new file mode 100644 index 000000000..07dbb0b08 --- /dev/null +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -0,0 +1,653 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Test.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; +import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; +import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IEVM2EVMOffRamp_1_2, IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {IERC20} from 'src/interfaces/IERC20.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {CCIPUtils} from './utils/CCIPUtils.sol'; +import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; +import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; + +/** + * @dev Test for AaveV3E2E_GHOCCIP150Upgrade_20241021 + * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol -vv + */ +contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { + error CallerIsNotARampOnRouter(address caller); + error NotACompatiblePool(address pool); + + struct CCIPSendParams { + IRouter router; + IERC20 token; + uint256 amount; + uint64 sourceChainSelector; + uint64 destinationChainSelector; + address sender; + bool migrated; + } + + struct Common { + IRouter router; + IERC20 token; + IEVM2EVMOnRamp EVM2EVMOnRamp1_2; + IEVM2EVMOnRamp EVM2EVMOnRamp1_5; + IEVM2EVMOffRamp_1_2 EVM2EVMOffRamp1_2; + IEVM2EVMOffRamp_1_5 EVM2EVMOffRamp1_5; + ITokenAdminRegistry tokenAdminRegistry; + IProxyPool proxyPool; + uint64 chainSelector; + uint256 forkId; + } + + struct L1 { + AaveV3Ethereum_GHOCCIP150Upgrade_20241021 proposal; + UpgradeableLockReleaseTokenPool tokenPool; + Common c; + } + + struct L2 { + AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 proposal; + UpgradeableBurnMintTokenPool tokenPool; + Common c; + } + + L1 internal l1; + L2 internal l2; + address internal alice = makeAddr('alice'); + + event CCIPSendRequested(IInternal.EVM2EVMMessage message); + event Locked(address indexed sender, uint256 amount); + event Burned(address indexed sender, uint256 amount); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + + function setUp() public virtual { + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21045560); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 267660907); + + vm.selectFork(l1.c.forkId); + l1.proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); + l1.c.proxyPool = IProxyPool(l1.proposal.GHO_CCIP_PROXY_POOL()); + l1.tokenPool = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + l1.c.router = IRouter(l1.tokenPool.getRouter()); + l2.c.chainSelector = l1.tokenPool.getSupportedChains()[0]; + l1.c.token = IERC20(address(l1.tokenPool.getToken())); + l1.c.EVM2EVMOnRamp1_2 = IEVM2EVMOnRamp(l1.c.router.getOnRamp(l2.c.chainSelector)); + l1.c.EVM2EVMOnRamp1_5 = IEVM2EVMOnRamp(0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284); // new onramp + l1.c.EVM2EVMOffRamp1_2 = IEVM2EVMOffRamp_1_2(0xeFC4a18af59398FF23bfe7325F2401aD44286F4d); + l1.c.EVM2EVMOffRamp1_5 = IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); // new offramp + l1.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + + vm.selectFork(l2.c.forkId); + l2.proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); + l2.c.proxyPool = IProxyPool(l2.proposal.GHO_CCIP_PROXY_POOL()); + l2.tokenPool = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + l2.c.router = IRouter(l2.tokenPool.getRouter()); + l1.c.chainSelector = l2.tokenPool.getSupportedChains()[0]; + l2.c.token = IERC20(address(l2.tokenPool.getToken())); + l2.c.EVM2EVMOnRamp1_2 = IEVM2EVMOnRamp(l2.c.router.getOnRamp(l1.c.chainSelector)); + l2.c.EVM2EVMOnRamp1_5 = IEVM2EVMOnRamp(0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3); // new onramp + l2.c.EVM2EVMOffRamp1_2 = IEVM2EVMOffRamp_1_2(0x542ba1902044069330e8c5b36A84EC503863722f); + l2.c.EVM2EVMOffRamp1_5 = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); // new offramp + l2.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + + _validateConfig({migrated: false}); + } + + function _getTokenMessage( + CCIPSendParams memory params + ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { + IClient.EVM2AnyMessage memory message = CCIPUtils.generateMessage(params.sender, 1); + message.tokenAmounts[0] = IClient.EVMTokenAmount({ + token: address(params.token), + amount: params.amount + }); + + uint256 feeAmount = params.router.getFee(params.destinationChainSelector, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: params.router, + sourceChainSelector: params.sourceChainSelector, + feeTokenAmount: feeAmount, + originalSender: params.sender, + destinationToken: address(params.token == l1.c.token ? l2.c.token : l1.c.token), + migrated: params.migrated + }) + ); + + return (message, eventArg); + } + + function _validateConfig(bool migrated) internal { + vm.selectFork(l1.c.forkId); + assertEq(l1.c.chainSelector, 5009297550715157269); + assertEq(address(l1.c.token), MiscEthereum.GHO_TOKEN); + assertEq(ITypeAndVersion(address(l1.c.router)).typeAndVersion(), 'Router 1.2.0'); + assertEq( + ITypeAndVersion(address(l1.c.EVM2EVMOnRamp1_2)).typeAndVersion(), + 'EVM2EVMOnRamp 1.2.0' + ); + assertEq( + ITypeAndVersion(address(l1.c.EVM2EVMOnRamp1_5)).typeAndVersion(), + 'EVM2EVMOnRamp 1.5.0' + ); + assertEq( + ITypeAndVersion(address(l1.c.EVM2EVMOffRamp1_2)).typeAndVersion(), + 'EVM2EVMOffRamp 1.2.0' + ); + assertEq( + ITypeAndVersion(address(l1.c.EVM2EVMOffRamp1_5)).typeAndVersion(), + 'EVM2EVMOffRamp 1.5.0' + ); + assertEq(l1.c.proxyPool.typeAndVersion(), 'LockReleaseTokenPoolAndProxy 1.5.0'); + assertEq(l1.tokenPool.typeAndVersion(), 'LockReleaseTokenPool 1.4.0'); + assertEq(l1.c.tokenAdminRegistry.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertTrue(l1.c.router.isOffRamp(l2.c.chainSelector, address(l1.c.EVM2EVMOffRamp1_2))); + assertTrue(l1.c.router.isOffRamp(l2.c.chainSelector, address(l1.c.EVM2EVMOffRamp1_5))); + + IRouter.OffRamp[] memory offRamps = l1.c.router.getOffRamps(); + for (uint256 i; i < offRamps.length; ++i) { + if (offRamps[i].sourceChainSelector == l2.c.chainSelector) { + assertTrue( + offRamps[i].offRamp == address(l1.c.EVM2EVMOffRamp1_2) || + offRamps[i].offRamp == address(l1.c.EVM2EVMOffRamp1_5) + ); + } + } + + if (migrated) { + assertEq(l1.c.router.getOnRamp(l2.c.chainSelector), address(l1.c.EVM2EVMOnRamp1_5)); + } else { + assertEq(l1.c.router.getOnRamp(l2.c.chainSelector), address(l1.c.EVM2EVMOnRamp1_2)); + } + + vm.selectFork(l2.c.forkId); + assertEq(l2.c.chainSelector, 4949039107694359620); + assertEq(address(l2.c.token), 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33); + assertEq(ITypeAndVersion(address(l2.c.router)).typeAndVersion(), 'Router 1.2.0'); + assertEq( + ITypeAndVersion(address(l2.c.EVM2EVMOnRamp1_2)).typeAndVersion(), + 'EVM2EVMOnRamp 1.2.0' + ); + assertEq( + ITypeAndVersion(address(l2.c.EVM2EVMOnRamp1_5)).typeAndVersion(), + 'EVM2EVMOnRamp 1.5.0' + ); + assertEq( + ITypeAndVersion(address(l2.c.EVM2EVMOffRamp1_2)).typeAndVersion(), + 'EVM2EVMOffRamp 1.2.0' + ); + assertEq( + ITypeAndVersion(address(l2.c.EVM2EVMOffRamp1_5)).typeAndVersion(), + 'EVM2EVMOffRamp 1.5.0' + ); + assertEq(l2.c.proxyPool.typeAndVersion(), 'BurnMintTokenPoolAndProxy 1.5.0'); + assertEq(l2.tokenPool.typeAndVersion(), 'BurnMintTokenPool 1.4.0'); + assertEq(l2.c.tokenAdminRegistry.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertTrue(l2.c.router.isOffRamp(l1.c.chainSelector, address(l2.c.EVM2EVMOffRamp1_2))); + assertTrue(l2.c.router.isOffRamp(l1.c.chainSelector, address(l2.c.EVM2EVMOffRamp1_5))); + + offRamps = l2.c.router.getOffRamps(); + for (uint256 i; i < offRamps.length; ++i) { + if (offRamps[i].sourceChainSelector == l1.c.chainSelector) { + assertTrue( + offRamps[i].offRamp == address(l2.c.EVM2EVMOffRamp1_2) || + offRamps[i].offRamp == address(l2.c.EVM2EVMOffRamp1_5) + ); + } + } + + if (migrated) { + assertEq(l2.c.router.getOnRamp(l1.c.chainSelector), address(l2.c.EVM2EVMOnRamp1_5)); + } else { + assertEq(l2.c.router.getOnRamp(l1.c.chainSelector), address(l2.c.EVM2EVMOnRamp1_2)); + } + } +} + +contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is + AaveV3E2E_GHOCCIP150Upgrade_20241021_Base +{ + function setUp() public override { + super.setUp(); + + vm.selectFork(l1.c.forkId); + executePayload(vm, address(l1.proposal)); + vm.selectFork(l2.c.forkId); + executePayload(vm, address(l2.proposal)); + + _validateConfig({migrated: false}); + } + + function test_E2E() public { + uint256 amount = 500e18; + // ETH (=> ARB) sendMessage + { + vm.selectFork(l1.c.forkId); + deal(address(l1.c.token), alice, amount, true); + vm.prank(alice); + l1.c.token.approve(address(l1.c.router), amount); + + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.tokenPool)); + uint256 bridgedAmount = l1.tokenPool.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l1.c.router, + token: l1.c.token, + amount: amount, + sourceChainSelector: l1.c.chainSelector, + destinationChainSelector: l2.c.chainSelector, + sender: alice, + migrated: false + }) + ); + + vm.expectEmit(address(l1.tokenPool)); + emit Locked(address(l1.c.EVM2EVMOnRamp1_2), amount); + vm.expectEmit(address(l1.c.EVM2EVMOnRamp1_2)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l1.c.router.ccipSend{value: eventArg.feeTokenAmount}(l2.c.chainSelector, message); + + assertEq(l1.c.token.balanceOf(address(l1.tokenPool)), tokenPoolBalance + amount); + assertEq(l1.tokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + + // ARB executeMessage + vm.selectFork(l2.c.forkId); + + uint256 aliceBalanceBefore = l2.c.token.balanceOf(alice); + + vm.expectEmit(address(l2.tokenPool)); + emit Minted(address(l2.c.EVM2EVMOffRamp1_2), alice, amount); + vm.prank(address(l2.c.EVM2EVMOffRamp1_2)); + l2.c.EVM2EVMOffRamp1_2.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length) + ); + + assertEq(l2.c.token.balanceOf(alice), aliceBalanceBefore + amount); + } + + // ARB (=> ETH) sendMessage + { + vm.selectFork(l2.c.forkId); + + vm.prank(alice); + l2.c.token.approve(address(l2.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l2.c.router, + token: l2.c.token, + amount: amount, + sourceChainSelector: l2.c.chainSelector, + destinationChainSelector: l1.c.chainSelector, + sender: alice, + migrated: false + }) + ); + + vm.expectEmit(address(l2.tokenPool)); + emit Burned(address(l2.c.EVM2EVMOnRamp1_2), amount); + vm.expectEmit(address(l2.c.EVM2EVMOnRamp1_2)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l2.c.router.ccipSend{value: eventArg.feeTokenAmount}(l1.c.chainSelector, message); + + assertEq(l2.c.token.balanceOf(alice), 0); + + // ETH executeMessage + vm.selectFork(l1.c.forkId); + + uint256 tokenPoolBalanceBefore = l1.c.token.balanceOf(address(l1.tokenPool)); + + vm.expectEmit(address(l1.tokenPool)); + emit Released(address(l1.c.EVM2EVMOffRamp1_2), alice, amount); + vm.prank(address(l1.c.EVM2EVMOffRamp1_2)); + l1.c.EVM2EVMOffRamp1_2.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length) + ); + + assertEq(l1.c.token.balanceOf(address(l1.tokenPool)), tokenPoolBalanceBefore - amount); + assertEq(l1.c.token.balanceOf(alice), amount); + } + } +} + +contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is + AaveV3E2E_GHOCCIP150Upgrade_20241021_Base +{ + function setUp() public override { + super.setUp(); + + // execute proposal + vm.selectFork(l1.c.forkId); + executePayload(vm, address(l1.proposal)); + vm.selectFork(l2.c.forkId); + executePayload(vm, address(l2.proposal)); + + _mockCCIPMigration(l1.c, l2.c); + _mockCCIPMigration(l2.c, l1.c); + + _validateConfig({migrated: true}); + } + + function test_E2E() public { + uint256 amount = 500e18; + // ETH (=> ARB) sendMessage + { + vm.selectFork(l1.c.forkId); + deal(address(l1.c.token), alice, amount, true); + vm.prank(alice); + l1.c.token.approve(address(l1.c.router), amount); + + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.tokenPool)); + uint256 bridgedAmount = l1.tokenPool.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l1.c.router, + token: l1.c.token, + amount: amount, + sourceChainSelector: l1.c.chainSelector, + destinationChainSelector: l2.c.chainSelector, + sender: alice, + migrated: true + }) + ); + + /// expected flow: router => onRamp => proxyPool => tokenPool + vm.expectEmit(address(l1.tokenPool)); + emit Locked(address(l1.c.proxyPool), amount); + + vm.expectEmit(address(l1.c.proxyPool)); + emit Locked(address(l1.c.EVM2EVMOnRamp1_5), amount); + + vm.expectEmit(address(l1.c.EVM2EVMOnRamp1_5)); // @dev caller is now 1.5 onRamp + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l1.c.router.ccipSend{value: eventArg.feeTokenAmount}(l2.c.chainSelector, message); + + assertEq(l1.c.token.balanceOf(address(l1.tokenPool)), tokenPoolBalance + amount); + assertEq(l1.tokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + + // ARB executeMessage + vm.selectFork(l2.c.forkId); + + vm.expectEmit(address(l2.tokenPool)); + emit Minted(address(l2.c.EVM2EVMOffRamp1_2), alice, amount); + vm.prank(address(l2.c.EVM2EVMOffRamp1_2)); + l2.c.EVM2EVMOffRamp1_2.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length) + ); + + vm.expectEmit(address(l2.c.proxyPool)); // emitter is proxyPool for 1.5 on ramp + emit Minted(address(l2.c.EVM2EVMOffRamp1_5), alice, amount); + vm.prank(address(l2.c.EVM2EVMOffRamp1_5)); + l2.c.EVM2EVMOffRamp1_5.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](1) // tokenGasOverrides + ); + } + + // ARB (=> ETH) sendMessage + { + vm.selectFork(l2.c.forkId); + + vm.prank(alice); + l2.c.token.approve(address(l2.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l2.c.router, + token: l2.c.token, + amount: amount, + sourceChainSelector: l2.c.chainSelector, + destinationChainSelector: l1.c.chainSelector, + sender: alice, + migrated: true + }) + ); + + /// expected flow: router => onRamp => proxyPool => tokenPool + vm.expectEmit(address(l2.tokenPool)); + emit Burned(address(l2.c.proxyPool), amount); // @dev caller is now 1.5 onRamp + + vm.expectEmit(address(l2.c.proxyPool)); + emit Burned(address(l2.c.EVM2EVMOnRamp1_5), amount); // @dev caller is now 1.5 onRamp + + vm.expectEmit(address(l2.c.EVM2EVMOnRamp1_5)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l2.c.router.ccipSend{value: eventArg.feeTokenAmount}(l1.c.chainSelector, message); + + // ETH executeMessage + vm.selectFork(l1.c.forkId); + + uint256 tokenPoolBalanceBefore = l1.c.token.balanceOf(address(l1.tokenPool)); + + vm.expectEmit(address(l1.c.proxyPool)); // emitter is proxyPool for 1.5 off ramp + emit Released(address(l1.c.EVM2EVMOffRamp1_5), alice, amount); + vm.prank(address(l1.c.EVM2EVMOffRamp1_5)); + l1.c.EVM2EVMOffRamp1_5.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](1) // tokenGasOverrides + ); + + assertEq(l1.c.token.balanceOf(address(l1.tokenPool)), tokenPoolBalanceBefore - amount); + assertEq(l1.c.token.balanceOf(alice), amount); + } + } + + function test_SendRevertsWithoutUpgrade() public { + { + vm.selectFork(l1.c.forkId); + uint256 amount = 500e18; + deal(address(l1.c.token), alice, amount, true); + vm.prank(alice); + l1.c.token.approve(address(l1.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l1.c.router, + token: l1.c.token, + amount: amount, + sourceChainSelector: l1.c.chainSelector, + destinationChainSelector: l2.c.chainSelector, + sender: alice, + migrated: true + }) + ); + + // mock undo upgrade by setting proxy pool to random address + vm.prank(l1.tokenPool.owner()); + l1.tokenPool.setProxyPool(address(1337)); + + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, l1.c.proxyPool)); + vm.prank(alice); + l1.c.router.ccipSend{value: eventArg.feeTokenAmount}(l2.c.chainSelector, message); + } + + { + vm.selectFork(l2.c.forkId); + uint256 amount = 500e18; + deal(address(l2.c.token), alice, amount, true); + vm.prank(alice); + l2.c.token.approve(address(l2.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l2.c.router, + token: l2.c.token, + amount: amount, + sourceChainSelector: l2.c.chainSelector, + destinationChainSelector: l1.c.chainSelector, + sender: alice, + migrated: true + }) + ); + + // mock undo upgrade by setting proxy pool to random address + vm.prank(l2.tokenPool.owner()); + l2.tokenPool.setProxyPool(address(1337)); + + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, l2.c.proxyPool)); + vm.prank(alice); + l2.c.router.ccipSend{value: eventArg.feeTokenAmount}(l1.c.chainSelector, message); + } + } + + function test_ExecuteRevertsWithoutUpgrade() public { + { + vm.selectFork(l1.c.forkId); + uint256 amount = 500e18; + deal(address(l1.c.token), alice, amount, true); + vm.prank(alice); + l1.c.token.approve(address(l1.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l1.c.router, + token: l1.c.token, + amount: amount, + sourceChainSelector: l1.c.chainSelector, + destinationChainSelector: l2.c.chainSelector, + sender: alice, + migrated: true + }) + ); + + // mock undo upgrade by setting proxy pool to random address + vm.prank(l1.tokenPool.owner()); + l1.tokenPool.setProxyPool(address(1337)); + + vm.expectRevert(abi.encodeWithSelector(NotACompatiblePool.selector, address(0))); + vm.prank(address(l1.c.EVM2EVMOffRamp1_5)); + l1.c.EVM2EVMOffRamp1_5.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](1) // tokenGasOverrides + ); + } + + { + vm.selectFork(l2.c.forkId); + uint256 amount = 500e18; + deal(address(l2.c.token), alice, amount, true); + vm.prank(alice); + l2.c.token.approve(address(l2.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l2.c.router, + token: l2.c.token, + amount: amount, + sourceChainSelector: l2.c.chainSelector, + destinationChainSelector: l1.c.chainSelector, + sender: alice, + migrated: true + }) + ); + + // mock undo upgrade by setting proxy pool to random address + vm.prank(l2.tokenPool.owner()); + l2.tokenPool.setProxyPool(address(1337)); + + vm.expectRevert(abi.encodeWithSelector(NotACompatiblePool.selector, address(0))); + vm.prank(address(l2.c.EVM2EVMOffRamp1_5)); + l2.c.EVM2EVMOffRamp1_5.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](1) // tokenGasOverrides + ); + } + } + function _mockCCIPMigration(Common memory src, Common memory dest) internal { + vm.selectFork(src.forkId); + + // token registry not set for 1.5 migration + assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(0)); + vm.startPrank(src.tokenAdminRegistry.owner()); + src.tokenAdminRegistry.proposeAdministrator(address(src.token), src.tokenAdminRegistry.owner()); + src.tokenAdminRegistry.acceptAdminRole(address(src.token)); + src.tokenAdminRegistry.setPool(address(src.token), address(src.proxyPool)); + vm.stopPrank(); + assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(src.proxyPool)); + + assertEq(src.proxyPool.getRouter(), address(src.router)); + + IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); + chains[0] = IProxyPool.ChainUpdate({ + remoteChainSelector: dest.chainSelector, + remotePoolAddress: abi.encode(address(dest.proxyPool)), + remoteTokenAddress: abi.encode(address(dest.token)), + allowed: true, + outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + vm.prank(src.proxyPool.owner()); + src.proxyPool.applyChainUpdates(chains); + + assertTrue(src.proxyPool.isSupportedChain(dest.chainSelector)); + + IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); + onRampUpdates[0] = IRouter.OnRamp({ + destChainSelector: dest.chainSelector, + onRamp: address(src.EVM2EVMOnRamp1_5) // new onRamp + }); + IRouter.OffRamp[] memory offRampUpdates = new IRouter.OffRamp[](1); + offRampUpdates[0] = IRouter.OffRamp({ + sourceChainSelector: dest.chainSelector, + offRamp: address(src.EVM2EVMOffRamp1_5) // new offRamp + }); + + vm.prank(src.router.owner()); + src.router.applyRampUpdates(onRampUpdates, new IRouter.OffRamp[](0), offRampUpdates); + } +} diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index b5f08c17c..eea86420d 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -3,9 +3,18 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; +import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; +import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IERC20} from 'src/interfaces/IERC20.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; /** @@ -13,73 +22,333 @@ import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCI * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol -vv */ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { + struct CCIPSendParams { + IRouter router; + uint256 amount; + bool migrated; + } + AaveV3Ethereum_GHOCCIP150Upgrade_20241021 internal proposal; - UpgradeableLockReleaseTokenPool internal tokenPoolProxy; - address internal proxyPool; + UpgradeableLockReleaseTokenPool internal ghoTokenPool; + IProxyPool internal proxyPool; + + address internal alice = makeAddr('alice'); - uint64 internal constant ETH_ARB_CHAIN_SELECTOR = 4949039107694359620; + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + address internal constant ARB_GHO_TOKEN = 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33; + address internal constant ARB_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + address internal constant ON_RAMP_1_2 = 0x925228D7B82d883Dde340A55Fe8e6dA56244A22C; + address internal constant ON_RAMP_1_5 = 0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284; + address internal constant OFF_RAMP_1_2 = 0xeFC4a18af59398FF23bfe7325F2401aD44286F4d; + address internal constant OFF_RAMP_1_5 = 0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9; event Locked(address indexed sender, uint256 amount); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event CCIPSendRequested(IInternal.EVM2EVMMessage message); error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21015645); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21045560); proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); - tokenPoolProxy = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); - proxyPool = proposal.GHO_CCIP_PROXY_POOL(); + ghoTokenPool = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); + + _validateConstants(); } /** * @dev executes the generic test suite including e2e and config snapshots */ function test_defaultProposalExecution() public { + bytes memory dynamicParamsBefore = _getDynamicParams(); + bytes memory staticParamsBefore = _getStaticParams(); defaultTest( 'AaveV3Ethereum_GHOCCIP150Upgrade_20241021', AaveV3Ethereum.POOL, address(proposal) ); + assertEq(keccak256(_getDynamicParams()), keccak256(dynamicParamsBefore)); + assertEq(keccak256(_getStaticParams()), keccak256(staticParamsBefore)); } function test_getProxyPool() public { // proxyPool getter does not exist before the upgrade vm.expectRevert(); - tokenPoolProxy.getProxyPool(); + ghoTokenPool.getProxyPool(); + + executePayload(vm, address(proposal)); + + assertEq(ghoTokenPool.getProxyPool(), address(proxyPool)); + } + + function test_tokenPoolCannotBeInitializedAgain() public { + vm.expectRevert('Initializable: contract is already initialized'); + ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router'), 0); + /// proxy implementation is initialized + assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); + + executePayload(vm, address(proposal)); + + vm.expectRevert('Initializable: contract is already initialized'); + ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router'), 0); + /// proxy implementation is initialized + assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); + } + + function test_sendMessagePreCCIPMigration() public { + executePayload(vm, address(proposal)); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + IRouter router = IRouter(ghoTokenPool.getRouter()); + uint256 amount = 500_000e18; + vm.prank(alice); + gho.approve(address(router), amount); + deal(address(gho), alice, amount); + + uint256 tokenPoolBalance = gho.balanceOf(address(ghoTokenPool)); + uint256 bridgedAmount = ghoTokenPool.getCurrentBridgedAmount(); + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: false})); + + vm.expectEmit(); + emit Locked(ON_RAMP_1_2, amount); + vm.expectEmit(); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + router.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); + + assertEq(gho.balanceOf(address(ghoTokenPool)), tokenPoolBalance + amount); + assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + } + + function test_sendMessagePostCCIPMigration() public { executePayload(vm, address(proposal)); - assertEq(tokenPoolProxy.getProxyPool(), proxyPool); + _mockCCIPMigration(); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + IRouter router = IRouter(ghoTokenPool.getRouter()); + uint256 amount = 500_000e18; + vm.prank(alice); + gho.approve(address(router), amount); + deal(address(gho), alice, amount); + + uint256 tokenPoolBalance = gho.balanceOf(address(ghoTokenPool)); + uint256 bridgedAmount = ghoTokenPool.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: true})); + + vm.expectEmit(); + emit Locked(ON_RAMP_1_5, amount); + vm.expectEmit(); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + router.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); + + assertEq(gho.balanceOf(address(ghoTokenPool)), tokenPoolBalance + amount); + assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + } + + function test_executeMessagePreCCIPMigration() public { + executePayload(vm, address(proposal)); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + IRouter router = IRouter(ghoTokenPool.getRouter()); + uint256 amount = 500_000e18; + // mock previously locked gho + deal(address(gho), address(ghoTokenPool), amount); + + address offRamp = _getOffRamp({router: router, migrated: false}); + + vm.expectEmit(); + emit Released(offRamp, alice, amount); + vm.prank(offRamp); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); + + assertEq(gho.balanceOf(alice), amount); + } + + function test_executeMessagePostCCIPMigration() public { + executePayload(vm, address(proposal)); + + _mockCCIPMigration(); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + IRouter router = IRouter(ghoTokenPool.getRouter()); + uint256 amount = 500_000e18; + // mock previously locked gho + deal(address(gho), address(ghoTokenPool), amount); + + address offRamp = _getOffRamp({router: router, migrated: true}); + + vm.expectEmit(); + emit Released(offRamp, alice, amount); + vm.prank(offRamp); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); + + assertEq(gho.balanceOf(alice), amount); } function test_proxyPoolCanOnRamp() public { - address alice = makeAddr('alice'); uint256 amount = 1337e18; - uint256 bridgedAmount = tokenPoolProxy.getCurrentBridgedAmount(); + uint256 bridgedAmount = ghoTokenPool.getCurrentBridgedAmount(); vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); - vm.prank(proxyPool); - tokenPoolProxy.lockOrBurn( - alice, - abi.encode(alice), - amount, - ETH_ARB_CHAIN_SELECTOR, - new bytes(0) - ); + vm.prank(address(proxyPool)); + ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ARB_CHAIN_SELECTOR, new bytes(0)); executePayload(vm, address(proposal)); vm.expectEmit(); - emit Locked(proxyPool, amount); - vm.prank(proxyPool); - tokenPoolProxy.lockOrBurn( - alice, - abi.encode(alice), - amount, - ETH_ARB_CHAIN_SELECTOR, - new bytes(0) + emit Locked(address(proxyPool), amount); + vm.prank(address(proxyPool)); + ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ARB_CHAIN_SELECTOR, new bytes(0)); + + assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + } + + function _mockCCIPMigration() private { + IRouter router = IRouter(ghoTokenPool.getRouter()); + // token registry not set for 1.5 migration + assertEq(TOKEN_ADMIN_REGISTRY.getPool(MiscEthereum.GHO_TOKEN), address(0)); + vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.proposeAdministrator(MiscEthereum.GHO_TOKEN, TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(MiscEthereum.GHO_TOKEN); + TOKEN_ADMIN_REGISTRY.setPool(MiscEthereum.GHO_TOKEN, address(proxyPool)); + vm.stopPrank(); + assertEq(TOKEN_ADMIN_REGISTRY.getPool(MiscEthereum.GHO_TOKEN), address(proxyPool)); + + assertEq(proxyPool.getRouter(), address(router)); + + IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); + chains[0] = IProxyPool.ChainUpdate({ + remoteChainSelector: ARB_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(ARB_PROXY_POOL), + remoteTokenAddress: abi.encode(address(ARB_GHO_TOKEN)), + allowed: true, + outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + vm.prank(proxyPool.owner()); + proxyPool.applyChainUpdates(chains); + + assertTrue(proxyPool.isSupportedChain(ARB_CHAIN_SELECTOR)); + + IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); + onRampUpdates[0] = IRouter.OnRamp({ + destChainSelector: ARB_CHAIN_SELECTOR, + onRamp: ON_RAMP_1_5 // new onRamp + }); + IRouter.OffRamp[] memory offRampUpdates = new IRouter.OffRamp[](1); + offRampUpdates[0] = IRouter.OffRamp({ + sourceChainSelector: ARB_CHAIN_SELECTOR, + offRamp: OFF_RAMP_1_5 // new offRamp + }); + + vm.prank(router.owner()); + router.applyRampUpdates(onRampUpdates, new IRouter.OffRamp[](0), offRampUpdates); + } + + function _getTokenMessage( + CCIPSendParams memory params + ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { + IClient.EVM2AnyMessage memory message = CCIPUtils.generateMessage(alice, 1); + message.tokenAmounts[0] = IClient.EVMTokenAmount({ + token: MiscEthereum.GHO_TOKEN, + amount: params.amount + }); + + uint256 feeAmount = params.router.getFee(ARB_CHAIN_SELECTOR, message); + deal(alice, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: params.router, + sourceChainSelector: ETH_CHAIN_SELECTOR, + feeTokenAmount: feeAmount, + originalSender: alice, + destinationToken: ARB_GHO_TOKEN, + migrated: params.migrated + }) ); - assertEq(tokenPoolProxy.getCurrentBridgedAmount(), bridgedAmount + amount); + return (message, eventArg); + } + + function _getOffRamp(IRouter router, bool migrated) internal view returns (address) { + IRouter.OffRamp[] memory offRamps = router.getOffRamps(); + for (uint256 i; i < offRamps.length; ++i) { + IRouter.OffRamp memory config = offRamps[i]; + if (config.sourceChainSelector == ARB_CHAIN_SELECTOR) { + address offRamp = config.offRamp; + if ( + keccak256(bytes(ITypeAndVersion(offRamp).typeAndVersion())) == + keccak256(bytes(migrated ? 'EVM2EVMOffRamp 1.5.0' : 'EVM2EVMOffRamp 1.2.0')) + ) { + return offRamp; + } + } + } + assert(false); + } + + function _getImplementation(address proxy) private view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) private view returns (uint8) { + /// slot 0 + // <1 byte ^ 1 byte ^ ---------- 20 bytes ----------> + // initialized initializing owner + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function _getStaticParams() private view returns (bytes memory) { + return + abi.encode( + address(ghoTokenPool.getToken()), + ghoTokenPool.getAllowList(), + ghoTokenPool.getArmProxy(), + ghoTokenPool.canAcceptLiquidity(), + ghoTokenPool.getRouter() + ); + } + + function _getDynamicParams() private view returns (bytes memory) { + return + abi.encode( + ghoTokenPool.owner(), + ghoTokenPool.getBridgeLimitAdmin(), + ghoTokenPool.getRateLimitAdmin(), + ghoTokenPool.getRebalancer(), + ghoTokenPool.getSupportedChains(), + ghoTokenPool.getLockReleaseInterfaceId(), + ghoTokenPool.getBridgeLimit(), + ghoTokenPool.getCurrentBridgedAmount(), + ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR) + ); + } + + function _validateConstants() private pure { + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(ITypeAndVersion(ON_RAMP_1_2).typeAndVersion(), 'EVM2EVMOnRamp 1.2.0'); + assertEq(ITypeAndVersion(ON_RAMP_1_5).typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); + assertEq(ITypeAndVersion(OFF_RAMP_1_5).typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol b/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol new file mode 100644 index 000000000..1071069d2 --- /dev/null +++ b/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol @@ -0,0 +1,152 @@ +pragma solidity ^0.8.0; + +import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; +import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; + +library CCIPUtils { + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + + bytes32 internal constant LEAF_DOMAIN_SEPARATOR = + 0x0000000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR = + 0x0000000000000000000000000000000000000000000000000000000000000001; + bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256('EVM2EVMMessageHashV2'); + bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + + struct SourceTokenData { + bytes sourcePoolAddress; + bytes destTokenAddress; + bytes extraData; + uint32 destGasAmount; + } + + struct MessageToEventParams { + IClient.EVM2AnyMessage message; + IRouter router; + uint64 sourceChainSelector; + uint256 feeTokenAmount; + address originalSender; + address destinationToken; + bool migrated; + } + + function generateMessage( + address receiver, + uint256 tokenAmountsLength + ) internal pure returns (IClient.EVM2AnyMessage memory) { + return + IClient.EVM2AnyMessage({ + receiver: abi.encode(receiver), + data: '', + tokenAmounts: new IClient.EVMTokenAmount[](tokenAmountsLength), + feeToken: address(0), + extraArgs: argsToBytes(IClient.EVMExtraArgsV1({gasLimit: 0})) + }); + } + + function messageToEvent( + MessageToEventParams memory params + ) public view returns (IInternal.EVM2EVMMessage memory) { + uint64 destChainSelector = params.sourceChainSelector == ETH_CHAIN_SELECTOR + ? ARB_CHAIN_SELECTOR + : ETH_CHAIN_SELECTOR; + IEVM2EVMOnRamp onRamp = IEVM2EVMOnRamp(params.router.getOnRamp(destChainSelector)); + + bytes memory args = new bytes(params.message.extraArgs.length - 4); + for (uint256 i = 4; i < params.message.extraArgs.length; ++i) { + args[i - 4] = params.message.extraArgs[i]; + } + + IInternal.EVM2EVMMessage memory messageEvent = IInternal.EVM2EVMMessage({ + sequenceNumber: onRamp.getExpectedNextSequenceNumber(), + feeTokenAmount: params.feeTokenAmount, + sender: params.originalSender, + nonce: onRamp.getSenderNonce(params.originalSender) + 1, + gasLimit: abi.decode(args, (IClient.EVMExtraArgsV1)).gasLimit, + strict: false, + sourceChainSelector: params.sourceChainSelector, + receiver: abi.decode(params.message.receiver, (address)), + data: params.message.data, + tokenAmounts: params.message.tokenAmounts, + sourceTokenData: new bytes[](params.message.tokenAmounts.length), + feeToken: params.router.getWrappedNative(), + messageId: '' + }); + + // change introduced in CCIP 1.5, hence we only apply if CCIP has migrated to 1.5 + if (params.migrated) { + for (uint256 i; i < params.message.tokenAmounts.length; ++i) { + messageEvent.sourceTokenData[i] = abi.encode( + SourceTokenData({ + sourcePoolAddress: abi.encode( + onRamp.getPoolBySourceToken(destChainSelector, params.message.tokenAmounts[i].token) + ), + destTokenAddress: abi.encode(params.destinationToken), + extraData: '', + destGasAmount: 90000 + }) + ); + } + } + + messageEvent.messageId = hash( + messageEvent, + generateMetadataHash(params.sourceChainSelector, destChainSelector, address(onRamp)) + ); + return messageEvent; + } + + function generateMetadataHash( + uint64 sourceChainSelector, + uint64 destChainSelector, + address onRamp + ) internal pure returns (bytes32) { + return + keccak256(abi.encode(EVM_2_EVM_MESSAGE_HASH, sourceChainSelector, destChainSelector, onRamp)); + } + + function argsToBytes( + IClient.EVMExtraArgsV1 memory extraArgs + ) internal pure returns (bytes memory bts) { + return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); + } + + /// @dev Used to hash messages for single-lane ramps. + /// OnRamp hash(EVM2EVMMessage) = OffRamp hash(EVM2EVMMessage) + /// The EVM2EVMMessage's messageId is expected to be the output of this hash function + /// @param original Message to hash + /// @param metadataHash Immutable metadata hash representing a lane with a fixed OnRamp + /// @return hashedMessage hashed message as a keccak256 + function hash( + IInternal.EVM2EVMMessage memory original, + bytes32 metadataHash + ) internal pure returns (bytes32) { + // Fixed-size message fields are included in nested hash to reduce stack pressure. + // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. + return + keccak256( + abi.encode( + LEAF_DOMAIN_SEPARATOR, + metadataHash, + keccak256( + abi.encode( + original.sender, + original.receiver, + original.sequenceNumber, + original.gasLimit, + original.strict, + original.nonce, + original.feeToken, + original.feeTokenAmount + ) + ), + keccak256(original.data), + keccak256(abi.encode(original.tokenAmounts)), + keccak256(abi.encode(original.sourceTokenData)) + ) + ); + } +} diff --git a/src/interfaces/IERC20.sol b/src/interfaces/IERC20.sol new file mode 100644 index 000000000..536ba0b96 --- /dev/null +++ b/src/interfaces/IERC20.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} diff --git a/src/interfaces/ccip/IEVM2EVMOffRamp.sol b/src/interfaces/ccip/IEVM2EVMOffRamp.sol index b900be64b..bda913d5d 100644 --- a/src/interfaces/ccip/IEVM2EVMOffRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOffRamp.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; -interface IEVM2EVMOffRamp { +interface IEVM2EVMOffRamp_1_2 { /// @notice Execute a single message. /// @param message The message that will be executed. /// @param offchainTokenData Token transfer data to be passed to TokenPool. @@ -17,3 +17,17 @@ interface IEVM2EVMOffRamp { bytes[] memory offchainTokenData ) external; } +interface IEVM2EVMOffRamp_1_5 { + /// @notice Execute a single message. + /// @param message The message that will be executed. + /// @param offchainTokenData Token transfer data to be passed to TokenPool. + /// @dev We make this external and callable by the contract itself, in order to try/catch + /// its execution and enforce atomicity among successful message processing and token transfer. + /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts + /// (for example smart contract wallets) without an associated message. + function executeSingleMessage( + IInternal.EVM2EVMMessage calldata message, + bytes[] calldata offchainTokenData, + uint32[] memory tokenGasOverrides + ) external; +} diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol new file mode 100644 index 000000000..251e0c585 --- /dev/null +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {IInternal} from './IInternal.sol'; +interface IEVM2EVMOnRamp { + /// @notice Gets the next sequence number to be used in the onRamp + /// @return the next sequence number to be used + function getExpectedNextSequenceNumber() external view returns (uint64); + + /// @notice Get the next nonce for a given sender + /// @param sender The sender to get the nonce for + /// @return nonce The next nonce for the sender + function getSenderNonce(address sender) external view returns (uint64 nonce); + + /// @notice Adds and removed token pools. + /// @param removes The tokens and pools to be removed + /// @param adds The tokens and pools to be added. + function applyPoolUpdates( + IInternal.PoolUpdate[] memory removes, + IInternal.PoolUpdate[] memory adds + ) external; + + /// @notice Get the pool for a specific token + /// @param destChainSelector The destination chain selector + /// @param sourceToken The source chain token to get the pool for + /// @return pool Token pool + function getPoolBySourceToken( + uint64 destChainSelector, + address sourceToken + ) external view returns (address); +} diff --git a/src/interfaces/ccip/IInternal.sol b/src/interfaces/ccip/IInternal.sol index fa8c78f6d..062ee93da 100644 --- a/src/interfaces/ccip/IInternal.sol +++ b/src/interfaces/ccip/IInternal.sol @@ -5,6 +5,11 @@ pragma solidity ^0.8.0; import {IClient} from 'src/interfaces/ccip/IClient.sol'; interface IInternal { + struct PoolUpdate { + address token; // The IERC20 token address + address pool; // The token pool address + } + /// @notice The cross chain message that gets committed to EVM chains. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct EVM2EVMMessage { diff --git a/src/interfaces/ccip/IProxyPool.sol b/src/interfaces/ccip/IProxyPool.sol new file mode 100644 index 000000000..bb84dcd71 --- /dev/null +++ b/src/interfaces/ccip/IProxyPool.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ITypeAndVersion} from './ITypeAndVersion.sol'; +import {IRateLimiter} from './IRateLimiter.sol'; +interface IProxyPool is ITypeAndVersion { + struct ChainUpdate { + uint64 remoteChainSelector; + bool allowed; + bytes remotePoolAddress; + bytes remoteTokenAddress; + IRateLimiter.Config inboundRateLimiterConfig; + IRateLimiter.Config outboundRateLimiterConfig; + } + + function owner() external view returns (address); + function getRouter() external view returns (address); + function setRouter(address router) external; + function getRemotePool(uint64 chainSelector) external view returns (bytes memory); + function applyChainUpdates(ChainUpdate[] memory updates) external; + function isSupportedChain(uint64 chainSelector) external view returns (bool); +} diff --git a/src/interfaces/ccip/IRateLimiter.sol b/src/interfaces/ccip/IRateLimiter.sol new file mode 100644 index 000000000..983e9b1af --- /dev/null +++ b/src/interfaces/ccip/IRateLimiter.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +interface IRateLimiter { + struct Config { + bool isEnabled; // Indication whether the rate limiting should be enabled + uint128 capacity; // ────╮ Specifies the capacity of the rate limiter + uint128 rate; // ───────╯ Specifies the rate of the rate limiter + } +} diff --git a/src/interfaces/ccip/IRouter.sol b/src/interfaces/ccip/IRouter.sol index 4e524b42f..43c0c1db7 100644 --- a/src/interfaces/ccip/IRouter.sol +++ b/src/interfaces/ccip/IRouter.sol @@ -5,23 +5,39 @@ pragma solidity ^0.8.0; import {IClient} from 'src/interfaces/ccip/IClient.sol'; interface IRouter { - /// @notice Request a message to be sent to the destination chain - /// @param destinationChainSelector The destination chain ID - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return messageId The message ID - /// @dev Note if msg.value is larger than the required fee (from getFee) we accept - /// the overpayment with no refund. - /// @dev Reverts with appropriate reason upon invalid message. + error UnsupportedDestinationChain(uint64 destChainSelector); + error InsufficientFeeTokenAmount(); + error InvalidMsgValue(); + + struct OnRamp { + uint64 destChainSelector; + address onRamp; + } + + struct OffRamp { + uint64 sourceChainSelector; + address offRamp; + } + + function owner() external view returns (address); + function getWrappedNative() external view returns (address); + function getOffRamps() external view returns (OffRamp[] memory); + function getOnRamp(uint64 destChainSelector) external view returns (address onRampAddress); + function isOffRamp( + uint64 sourceChainSelector, + address offRamp + ) external view returns (bool isOffRamp); + function applyRampUpdates( + OnRamp[] calldata onRampUpdates, + OffRamp[] calldata offRampRemoves, + OffRamp[] calldata offRampAdds + ) external; + function isChainSupported(uint64 chainSelector) external view returns (bool supported); + function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory tokens); function ccipSend( uint64 destinationChainSelector, IClient.EVM2AnyMessage memory message ) external payable returns (bytes32); - - /// @param destinationChainSelector The destination chainSelector - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return fee returns execution fee for the message - /// delivery to destination chain, denominated in the feeToken specified in the message. - /// @dev Reverts with appropriate reason upon invalid message. function getFee( uint64 destinationChainSelector, IClient.EVM2AnyMessage memory message diff --git a/src/interfaces/ccip/ITokenAdminRegistry.sol b/src/interfaces/ccip/ITokenAdminRegistry.sol new file mode 100644 index 000000000..1a123b5d0 --- /dev/null +++ b/src/interfaces/ccip/ITokenAdminRegistry.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ITypeAndVersion} from './ITypeAndVersion.sol'; +interface ITokenAdminRegistry is ITypeAndVersion { + function owner() external view returns (address); + function acceptAdminRole(address from) external; + + function proposeAdministrator(address localToken, address administrator) external; + + function getPool(address token) external view returns (address); + function setPool(address source, address pool) external; +} diff --git a/src/interfaces/ccip/ITypeAndVersion.sol b/src/interfaces/ccip/ITypeAndVersion.sol new file mode 100644 index 000000000..135f6d0ae --- /dev/null +++ b/src/interfaces/ccip/ITypeAndVersion.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ITypeAndVersion { + function typeAndVersion() external pure returns (string memory); +} From 38a1159ec4b3a36634e049fd8ae62e4110fa12cc Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:14:24 +0530 Subject: [PATCH 18/57] chore: fix license, explicit senders for expectEmit --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 20 +++++++++---------- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 16 ++++++++------- .../utils/CCIPUtils.sol | 1 + src/interfaces/ccip/IEVM2EVMOffRamp.sol | 1 + src/interfaces/ccip/IEVM2EVMOnRamp.sol | 1 + src/interfaces/ccip/IProxyPool.sol | 3 ++- src/interfaces/ccip/IRouter.sol | 1 - src/interfaces/ccip/ITokenAdminRegistry.sol | 4 +--- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index dfcd23816..4a05e272d 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -118,9 +118,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IInternal.EVM2EVMMessage memory eventArg ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: false})); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Burned(ON_RAMP_1_2, amount); - vm.expectEmit(); + vm.expectEmit(ON_RAMP_1_2); emit CCIPSendRequested(eventArg); vm.prank(alice); router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); @@ -145,9 +145,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IInternal.EVM2EVMMessage memory eventArg ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: true})); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); + emit Burned(address(proxyPool), amount); + vm.expectEmit(address(proxyPool)); emit Burned(ON_RAMP_1_5, amount); - vm.expectEmit(); + vm.expectEmit(ON_RAMP_1_5); emit CCIPSendRequested(eventArg); vm.prank(alice); router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); @@ -160,10 +162,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); uint256 amount = 500_000e18; - // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) - deal(address(gho), address(ghoTokenPool), amount); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Minted(OFF_RAMP_1_2, alice, amount); vm.prank(OFF_RAMP_1_2); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); @@ -178,10 +178,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); uint256 amount = 500_000e18; - // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) - deal(address(gho), address(ghoTokenPool), amount); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Minted(OFF_RAMP_1_5, alice, amount); vm.prank(OFF_RAMP_1_5); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); @@ -200,7 +198,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) deal(ARB_GHO_TOKEN, address(ghoTokenPool), amount); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Burned(address(proxyPool), amount); vm.prank(address(proxyPool)); ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ETH_CHAIN_SELECTOR, new bytes(0)); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index eea86420d..b9d6b3ae3 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -117,9 +117,9 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IInternal.EVM2EVMMessage memory eventArg ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: false})); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Locked(ON_RAMP_1_2, amount); - vm.expectEmit(); + vm.expectEmit(ON_RAMP_1_2); emit CCIPSendRequested(eventArg); vm.prank(alice); router.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); @@ -148,9 +148,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IInternal.EVM2EVMMessage memory eventArg ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: true})); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); + emit Locked(address(proxyPool), amount); + vm.expectEmit(address(proxyPool)); emit Locked(ON_RAMP_1_5, amount); - vm.expectEmit(); + vm.expectEmit(ON_RAMP_1_5); emit CCIPSendRequested(eventArg); vm.prank(alice); router.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); @@ -170,7 +172,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { address offRamp = _getOffRamp({router: router, migrated: false}); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Released(offRamp, alice, amount); vm.prank(offRamp); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); @@ -191,7 +193,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { address offRamp = _getOffRamp({router: router, migrated: true}); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Released(offRamp, alice, amount); vm.prank(offRamp); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); @@ -210,7 +212,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); - vm.expectEmit(); + vm.expectEmit(address(ghoTokenPool)); emit Locked(address(proxyPool), amount); vm.prank(address(proxyPool)); ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ARB_CHAIN_SELECTOR, new bytes(0)); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol b/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol index 1071069d2..f7d20897b 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IClient} from 'src/interfaces/ccip/IClient.sol'; diff --git a/src/interfaces/ccip/IEVM2EVMOffRamp.sol b/src/interfaces/ccip/IEVM2EVMOffRamp.sol index bda913d5d..7f8b84385 100644 --- a/src/interfaces/ccip/IEVM2EVMOffRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOffRamp.sol @@ -17,6 +17,7 @@ interface IEVM2EVMOffRamp_1_2 { bytes[] memory offchainTokenData ) external; } + interface IEVM2EVMOffRamp_1_5 { /// @notice Execute a single message. /// @param message The message that will be executed. diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol index 251e0c585..e73bc188c 100644 --- a/src/interfaces/ccip/IEVM2EVMOnRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import {IInternal} from './IInternal.sol'; + interface IEVM2EVMOnRamp { /// @notice Gets the next sequence number to be used in the onRamp /// @return the next sequence number to be used diff --git a/src/interfaces/ccip/IProxyPool.sol b/src/interfaces/ccip/IProxyPool.sol index bb84dcd71..3f7c7658b 100644 --- a/src/interfaces/ccip/IProxyPool.sol +++ b/src/interfaces/ccip/IProxyPool.sol @@ -1,8 +1,9 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ITypeAndVersion} from './ITypeAndVersion.sol'; import {IRateLimiter} from './IRateLimiter.sol'; + interface IProxyPool is ITypeAndVersion { struct ChainUpdate { uint64 remoteChainSelector; diff --git a/src/interfaces/ccip/IRouter.sol b/src/interfaces/ccip/IRouter.sol index 43c0c1db7..89c9275b2 100644 --- a/src/interfaces/ccip/IRouter.sol +++ b/src/interfaces/ccip/IRouter.sol @@ -13,7 +13,6 @@ interface IRouter { uint64 destChainSelector; address onRamp; } - struct OffRamp { uint64 sourceChainSelector; address offRamp; diff --git a/src/interfaces/ccip/ITokenAdminRegistry.sol b/src/interfaces/ccip/ITokenAdminRegistry.sol index 1a123b5d0..760982254 100644 --- a/src/interfaces/ccip/ITokenAdminRegistry.sol +++ b/src/interfaces/ccip/ITokenAdminRegistry.sol @@ -1,13 +1,11 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ITypeAndVersion} from './ITypeAndVersion.sol'; interface ITokenAdminRegistry is ITypeAndVersion { function owner() external view returns (address); function acceptAdminRole(address from) external; - function proposeAdministrator(address localToken, address administrator) external; - function getPool(address token) external view returns (address); function setPool(address source, address pool) external; } From f199681863f20a4d4fa3f3bfac6961f4dcf57df8 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 29 Oct 2024 03:20:39 +0530 Subject: [PATCH 19/57] ci: override rpc url in secrets --- .github/workflows/test.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f186f228..977839ab4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,19 @@ jobs: test-sol: uses: bgd-labs/github-workflows/.github/workflows/foundry-test.yml@main - secrets: inherit + secrets: + RPC_MAINNET: "https://eth-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_ARBITRUM: "https://arb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_POLYGON: "https://polygon-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_AVALANCHE: "https://avax-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_OPTIMISM: "https://opt-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_METIS: "https://metis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_BASE: "https://base-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_GNOSIS: "https://gnosis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_BNB: "https://bnb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_ZKEVM: "https://polygonzkevm-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_SCROLL: "https://scroll-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_ZKSYNC: "https://zksync-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" with: mode: "CHANGED" From 7b2376b1a09cabb6d084f7c9f9072168c9805968 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 29 Oct 2024 03:53:02 +0530 Subject: [PATCH 20/57] test: proxy pool can off ramp --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 18 ++++++++++++++++- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 20 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 4a05e272d..888b67f28 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -204,6 +204,21 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ETH_CHAIN_SELECTOR, new bytes(0)); } + function test_proxyPoolCanOffRamp() public { + uint256 amount = 1337e18; + + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); + vm.prank(address(proxyPool)); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, new bytes(0)); + + executePayload(vm, address(proposal)); + + vm.expectEmit(address(ghoTokenPool)); + emit Minted(address(proxyPool), alice, amount); + vm.prank(address(proxyPool)); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, new bytes(0)); + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration @@ -303,8 +318,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ); } - function _validateConstants() private pure { + function _validateConstants() private view { assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(proxyPool.typeAndVersion(), 'BurnMintTokenPoolAndProxy 1.5.0'); assertEq(ITypeAndVersion(ON_RAMP_1_2).typeAndVersion(), 'EVM2EVMOnRamp 1.2.0'); assertEq(ITypeAndVersion(ON_RAMP_1_5).typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index b9d6b3ae3..b60ced563 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -220,6 +220,23 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); } + function test_proxyPoolCanOffRamp() public { + uint256 amount = 1337e18; + + vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); + vm.prank(address(proxyPool)); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, new bytes(0)); + + executePayload(vm, address(proposal)); + // mock previously locked gho + deal(MiscEthereum.GHO_TOKEN, address(ghoTokenPool), amount); + + vm.expectEmit(address(ghoTokenPool)); + emit Released(address(proxyPool), alice, amount); + vm.prank(address(proxyPool)); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, new bytes(0)); + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration @@ -346,8 +363,9 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ); } - function _validateConstants() private pure { + function _validateConstants() private view { assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(proxyPool.typeAndVersion(), 'LockReleaseTokenPoolAndProxy 1.5.0'); assertEq(ITypeAndVersion(ON_RAMP_1_2).typeAndVersion(), 'EVM2EVMOnRamp 1.2.0'); assertEq(ITypeAndVersion(ON_RAMP_1_5).typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); From d4d438e7aeaf2194b0322d69789d03d96c310b71 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 29 Oct 2024 03:55:18 +0530 Subject: [PATCH 21/57] chore: reorder deps --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 273048d87..18571fa45 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; /** diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 3722ccc9b..386de8a23 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; /** From fc6a51c50cf110c1715e8a14636e0d60790242e7 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:54:26 +0530 Subject: [PATCH 22/57] nit: utilize existing ierc20 import, style guide, use arb assets for gho addy --- ...eV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 1 - ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 6 +- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 9 ++- ...eV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 3 +- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 2 +- src/interfaces/IERC20.sol | 78 ------------------- 6 files changed, 10 insertions(+), 89 deletions(-) delete mode 100644 src/interfaces/IERC20.sol diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 18571fa45..4dd2a3ce9 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -10,7 +10,6 @@ import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/Upgrad /** * @title GHO CCIP 1.50 Upgrade * @author Aave Labs - * - Snapshot: TODO * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 888b67f28..125482616 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {AaveV3Arbitrum, AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -13,7 +14,6 @@ import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; -import {IERC20} from 'src/interfaces/IERC20.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; @@ -38,7 +38,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; - address internal constant ARB_GHO_TOKEN = 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33; + address internal constant ARB_GHO_TOKEN = AaveV3ArbitrumAssets.GHO_UNDERLYING; address internal constant ETH_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 07dbb0b08..f4d9443ac 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -15,7 +16,6 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IEVM2EVMOffRamp_1_2, IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; -import {IERC20} from 'src/interfaces/IERC20.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; @@ -26,9 +26,6 @@ import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCI * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol -vv */ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { - error CallerIsNotARampOnRouter(address caller); - error NotACompatiblePool(address pool); - struct CCIPSendParams { IRouter router; IERC20 token; @@ -74,6 +71,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { event Released(address indexed sender, address indexed recipient, uint256 amount); event Minted(address indexed sender, address indexed recipient, uint256 amount); + error CallerIsNotARampOnRouter(address caller); + error NotACompatiblePool(address pool); + function setUp() public virtual { l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21045560); l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 267660907); @@ -607,6 +607,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is ); } } + function _mockCCIPMigration(Common memory src, Common memory dest) internal { vm.selectFork(src.forkId); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 386de8a23..8648de7ed 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -3,14 +3,13 @@ pragma solidity ^0.8.0; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; -import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; /** * @title GHO CCIP 1.50 Upgrade * @author Aave Labs - * - Snapshot: TODO * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index b60ced563..7de2f9800 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -12,7 +13,6 @@ import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; -import {IERC20} from 'src/interfaces/IERC20.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; diff --git a/src/interfaces/IERC20.sol b/src/interfaces/IERC20.sol deleted file mode 100644 index 536ba0b96..000000000 --- a/src/interfaces/IERC20.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address from, address to, uint256 amount) external returns (bool); -} From f64be600cd6f0c96bc940a14ff7ece5ddea05d64 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:43:44 +0530 Subject: [PATCH 23/57] feat: add rate limit, use gho fascilitator for tests --- ...eV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 26 ++ ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 130 ++++++++-- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 226 +++++++++++++++--- ...eV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 26 ++ ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 108 ++++++--- src/interfaces/ccip/IRateLimiter.sol | 8 + 6 files changed, 438 insertions(+), 86 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 4dd2a3ce9..0bc20c882 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -6,6 +6,7 @@ import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin. import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; /** * @title GHO CCIP 1.50 Upgrade @@ -14,6 +15,7 @@ import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/Upgrad */ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; + uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; function execute() external { UpgradeableBurnMintTokenPool tokenPoolProxy = UpgradeableBurnMintTokenPool( @@ -36,5 +38,29 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // Update proxyPool address tokenPoolProxy.setProxyPool(GHO_CCIP_PROXY_POOL); + + // Set rate limit + tokenPoolProxy.setChainRateLimiterConfig( + ETH_CHAIN_SELECTOR, + getOutBoundRateLimiterConfig(), + getInBoundRateLimiterConfig() + ); + } + + /// @notice Returns the rate limiter configuration for the outbound rate limiter + /// The onRamp rate limit for ARB => ETH will be as follows: + /// Capacity: 350_000 GHO + /// Rate: 100 GHO per second (=> 360_000 GHO per hour) + /// @return The rate limiter configuration + function getOutBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + } + + /// @notice Returns the rate limiter configuration for the inbound rate limiter + /// The offramp capacity for ETH => ARB will be disabled, as the outbound rate limit + /// will be set on ETH token pool + /// @return The rate limiter configuration + function getInBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 125482616..65c72808a 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -8,6 +8,7 @@ import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; @@ -15,6 +16,7 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; @@ -67,6 +69,19 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { * @dev executes the generic test suite including e2e and config snapshots */ function test_defaultProposalExecution() public { + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + bytes memory dynamicParamsBefore = _getDynamicParams(); bytes memory staticParamsBefore = _getStaticParams(); @@ -75,8 +90,22 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { AaveV3Arbitrum.POOL, address(proposal) ); + assertEq(keccak256(_getDynamicParams()), keccak256(dynamicParamsBefore)); assertEq(keccak256(_getStaticParams()), keccak256(staticParamsBefore)); + + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR)) + ), + abi.encode(proposal.getInBoundRateLimiterConfig()) + ); + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR)) + ), + abi.encode(proposal.getOutBoundRateLimiterConfig()) + ); } function test_getProxyPool() public { @@ -89,6 +118,17 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ghoTokenPool.getProxyPool(), address(proxyPool)); } + function test_getRateLimitAdmin() public { + // rateLimitAdmin getter does not exist before the upgrade on BurnMintTokenPool + vm.expectRevert(); + ghoTokenPool.getRateLimitAdmin(); + + executePayload(vm, address(proposal)); + + // we currently do not set the rate limit admin + assertEq(ghoTokenPool.getRateLimitAdmin(), address(0)); + } + function test_tokenPoolCannotBeInitializedAgain() public { vm.expectRevert('Initializable: contract is already initialized'); ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); @@ -106,12 +146,16 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function test_sendMessagePreCCIPMigration() public { executePayload(vm, address(proposal)); - IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 500_000e18; + uint256 amount = 150_000e18; + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); + vm.prank(alice); - gho.approve(address(router), amount); - deal(address(gho), alice, amount); + IERC20(ARB_GHO_TOKEN).approve(address(router), amount); + deal(ARB_GHO_TOKEN, alice, amount); ( IClient.EVM2AnyMessage memory message, @@ -125,7 +169,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { vm.prank(alice); router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); - assertEq(gho.balanceOf(alice), 0); + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), 0); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore - amount); } function test_sendMessagePostCCIPMigration() public { @@ -133,12 +178,16 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); - IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 500_000e18; + uint256 amount = 350_000e18; + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); + vm.prank(alice); - gho.approve(address(router), amount); - deal(address(gho), alice, amount); + IERC20(ARB_GHO_TOKEN).approve(address(router), amount); + deal(ARB_GHO_TOKEN, alice, amount); ( IClient.EVM2AnyMessage memory message, @@ -154,21 +203,26 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { vm.prank(alice); router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); - assertEq(gho.balanceOf(alice), 0); + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), 0); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore - amount); } function test_executeMessagePreCCIPMigration() public { executePayload(vm, address(proposal)); - IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - uint256 amount = 500_000e18; + uint256 amount = 350_000e18; + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); vm.expectEmit(address(ghoTokenPool)); emit Minted(OFF_RAMP_1_2, alice, amount); vm.prank(OFF_RAMP_1_2); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); - assertEq(gho.balanceOf(alice), amount); + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), amount); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } function test_executeMessagePostCCIPMigration() public { @@ -176,15 +230,19 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); - IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - uint256 amount = 500_000e18; + uint256 amount = 350_000e18; + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); vm.expectEmit(address(ghoTokenPool)); emit Minted(OFF_RAMP_1_5, alice, amount); vm.prank(OFF_RAMP_1_5); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); - assertEq(gho.balanceOf(alice), amount); + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), amount); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } function test_proxyPoolCanOnRamp() public { @@ -197,11 +255,18 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); // router is responsible for transferring liquidity, so we mock router.token.transferFrom(user, tokenPool) deal(ARB_GHO_TOKEN, address(ghoTokenPool), amount); + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); vm.expectEmit(address(ghoTokenPool)); emit Burned(address(proxyPool), amount); vm.prank(address(proxyPool)); ghoTokenPool.lockOrBurn(alice, abi.encode(alice), amount, ETH_CHAIN_SELECTOR, new bytes(0)); + + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), 0); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore - amount); } function test_proxyPoolCanOffRamp() public { @@ -212,11 +277,15 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, new bytes(0)); executePayload(vm, address(proposal)); + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); vm.expectEmit(address(ghoTokenPool)); emit Minted(address(proxyPool), alice, amount); vm.prank(address(proxyPool)); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, new bytes(0)); + + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), amount); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } function _mockCCIPMigration() private { @@ -298,6 +367,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + function _getFacilitatorLevel(address f) internal view returns (uint256) { + (, uint256 level) = IGhoToken(ARB_GHO_TOKEN).getFacilitatorBucket(f); + return level; + } + function _getStaticParams() private view returns (bytes memory) { return abi.encode( @@ -313,8 +387,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { abi.encode( ghoTokenPool.owner(), ghoTokenPool.getSupportedChains(), - ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), - ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR) + ghoTokenPool.getAllowListEnabled() ); } @@ -326,4 +399,25 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_5).typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); } + + function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { + uint128 rate = proposal.getOutBoundRateLimiterConfig().rate; + assertNotEq(rate, 0); + return amount / uint256(rate) + 1; // account for rounding + } + + function _tokenBucketToConfig( + RateLimiter.TokenBucket memory bucket + ) private pure returns (RateLimiter.Config memory) { + return + RateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() private pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index f4d9443ac..5d09119e1 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -219,6 +219,50 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { assertEq(l2.c.router.getOnRamp(l1.c.chainSelector), address(l2.c.EVM2EVMOnRamp1_2)); } } + + function _mockCCIPMigration(Common memory src, Common memory dest) internal { + vm.selectFork(src.forkId); + + // token registry not set for 1.5 migration + assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(0)); + vm.startPrank(src.tokenAdminRegistry.owner()); + src.tokenAdminRegistry.proposeAdministrator(address(src.token), src.tokenAdminRegistry.owner()); + src.tokenAdminRegistry.acceptAdminRole(address(src.token)); + src.tokenAdminRegistry.setPool(address(src.token), address(src.proxyPool)); + vm.stopPrank(); + assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(src.proxyPool)); + + assertEq(src.proxyPool.getRouter(), address(src.router)); + + IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); + chains[0] = IProxyPool.ChainUpdate({ + remoteChainSelector: dest.chainSelector, + remotePoolAddress: abi.encode(address(dest.proxyPool)), + remoteTokenAddress: abi.encode(address(dest.token)), + allowed: true, + outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + vm.prank(src.proxyPool.owner()); + src.proxyPool.applyChainUpdates(chains); + + assertTrue(src.proxyPool.isSupportedChain(dest.chainSelector)); + + IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); + onRampUpdates[0] = IRouter.OnRamp({ + destChainSelector: dest.chainSelector, + onRamp: address(src.EVM2EVMOnRamp1_5) // new onRamp + }); + IRouter.OffRamp[] memory offRampUpdates = new IRouter.OffRamp[](1); + offRampUpdates[0] = IRouter.OffRamp({ + sourceChainSelector: dest.chainSelector, + offRamp: address(src.EVM2EVMOffRamp1_5) // new offRamp + }); + + vm.prank(src.router.owner()); + src.router.applyRampUpdates(onRampUpdates, new IRouter.OffRamp[](0), offRampUpdates); + } } contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is @@ -244,6 +288,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); + uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.tokenPool)); uint256 bridgedAmount = l1.tokenPool.getCurrentBridgedAmount(); @@ -294,6 +342,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); + uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -365,6 +416,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); + uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.tokenPool)); uint256 bridgedAmount = l1.tokenPool.getCurrentBridgedAmount(); @@ -425,6 +480,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); + uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -479,6 +537,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is deal(address(l1.c.token), alice, amount, true); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); + uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -510,6 +571,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); + uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -607,48 +671,140 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is ); } } +} - function _mockCCIPMigration(Common memory src, Common memory dest) internal { - vm.selectFork(src.forkId); +contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is + AaveV3E2E_GHOCCIP150Upgrade_20241021_Base +{ + function setUp() public override { + super.setUp(); - // token registry not set for 1.5 migration - assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(0)); - vm.startPrank(src.tokenAdminRegistry.owner()); - src.tokenAdminRegistry.proposeAdministrator(address(src.token), src.tokenAdminRegistry.owner()); - src.tokenAdminRegistry.acceptAdminRole(address(src.token)); - src.tokenAdminRegistry.setPool(address(src.token), address(src.proxyPool)); - vm.stopPrank(); - assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(src.proxyPool)); + // execute proposal + vm.selectFork(l1.c.forkId); + executePayload(vm, address(l1.proposal)); + vm.selectFork(l2.c.forkId); + executePayload(vm, address(l2.proposal)); - assertEq(src.proxyPool.getRouter(), address(src.router)); + _validateConfig({migrated: false}); + } - IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); - chains[0] = IProxyPool.ChainUpdate({ - remoteChainSelector: dest.chainSelector, - remotePoolAddress: abi.encode(address(dest.proxyPool)), - remoteTokenAddress: abi.encode(address(dest.token)), - allowed: true, - outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); + function test_sendFlowInBetweenCCIPMigrationFromEth() public { + // ETH => ARB, ccipSend 1.4; CCIP migration, Destination executeMessage + { + vm.selectFork(l1.c.forkId); + uint256 amount = 500e18; + deal(address(l1.c.token), alice, amount, true); + vm.prank(alice); + l1.c.token.approve(address(l1.c.router), amount); + uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero - vm.prank(src.proxyPool.owner()); - src.proxyPool.applyChainUpdates(chains); + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l1.c.router, + token: l1.c.token, + amount: amount, + sourceChainSelector: l1.c.chainSelector, + destinationChainSelector: l2.c.chainSelector, + sender: alice, + migrated: false + }) + ); - assertTrue(src.proxyPool.isSupportedChain(dest.chainSelector)); + vm.expectEmit(address(l1.tokenPool)); + emit Locked(address(l1.c.EVM2EVMOnRamp1_2), amount); + vm.expectEmit(address(l1.c.EVM2EVMOnRamp1_2)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l1.c.router.ccipSend{value: eventArg.feeTokenAmount}(l2.c.chainSelector, message); - IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); - onRampUpdates[0] = IRouter.OnRamp({ - destChainSelector: dest.chainSelector, - onRamp: address(src.EVM2EVMOnRamp1_5) // new onRamp - }); - IRouter.OffRamp[] memory offRampUpdates = new IRouter.OffRamp[](1); - offRampUpdates[0] = IRouter.OffRamp({ - sourceChainSelector: dest.chainSelector, - offRamp: address(src.EVM2EVMOffRamp1_5) // new offRamp - }); + assertEq(l1.c.token.balanceOf(alice), 0); - vm.prank(src.router.owner()); - src.router.applyRampUpdates(onRampUpdates, new IRouter.OffRamp[](0), offRampUpdates); + vm.selectFork(l2.c.forkId); + // CCIP Migration on L2 + _mockCCIPMigration(l2.c, l1.c); + + // reverts with 1.5 off ramp + vm.expectRevert(); + vm.prank(address(l2.c.EVM2EVMOffRamp1_5)); + l2.c.EVM2EVMOffRamp1_5.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](0) // tokenGasOverrides + ); + + // system can use legacy 1.2 off ramp after migration + vm.expectEmit(address(l2.tokenPool)); + emit Minted(address(l2.c.EVM2EVMOffRamp1_2), alice, amount); + vm.prank(address(l2.c.EVM2EVMOffRamp1_2)); + l2.c.EVM2EVMOffRamp1_2.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length) + ); + } + } + + function test_sendFlowInBetweenCCIPMigrationFromArb() public { + // ARB => ETH, ccipSend 1.4; CCIP migration, Destination executeMessage + { + vm.selectFork(l2.c.forkId); + uint256 amount = 500e18; + deal(address(l2.c.token), alice, amount, true); + vm.prank(alice); + l2.c.token.approve(address(l2.c.router), amount); + uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(rate) + 1); // rate is non zero + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({ + router: l2.c.router, + token: l2.c.token, + amount: amount, + sourceChainSelector: l2.c.chainSelector, + destinationChainSelector: l1.c.chainSelector, + sender: alice, + migrated: false + }) + ); + + vm.expectEmit(address(l2.tokenPool)); + emit Burned(address(l2.c.EVM2EVMOnRamp1_2), amount); + vm.expectEmit(address(l2.c.EVM2EVMOnRamp1_2)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l2.c.router.ccipSend{value: eventArg.feeTokenAmount}(l1.c.chainSelector, message); + + assertEq(l2.c.token.balanceOf(alice), 0); + + vm.selectFork(l1.c.forkId); + // CCIP Migration on L2 + _mockCCIPMigration(l1.c, l1.c); + + // reverts with 1.5 off ramp + vm.expectRevert(); + vm.prank(address(l1.c.EVM2EVMOffRamp1_5)); + l1.c.EVM2EVMOffRamp1_5.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](0) // tokenGasOverrides + ); + + // system can use legacy 1.2 off ramp after migration + vm.expectEmit(address(l1.tokenPool)); + emit Released(address(l1.c.EVM2EVMOffRamp1_2), alice, amount); + vm.prank(address(l1.c.EVM2EVMOffRamp1_2)); + l1.c.EVM2EVMOffRamp1_2.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length) + ); + } } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 8648de7ed..c261248fc 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -6,6 +6,7 @@ import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin. import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; /** * @title GHO CCIP 1.50 Upgrade @@ -14,6 +15,7 @@ import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/Upg */ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; + uint64 public constant ARB_CHAIN_SELECTOR = 4949039107694359620; function execute() external { UpgradeableLockReleaseTokenPool tokenPoolProxy = UpgradeableLockReleaseTokenPool( @@ -37,5 +39,29 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // Update proxyPool address tokenPoolProxy.setProxyPool(GHO_CCIP_PROXY_POOL); + + // Set rate limit + tokenPoolProxy.setChainRateLimiterConfig( + ARB_CHAIN_SELECTOR, + getOutBoundRateLimiterConfig(), + getInBoundRateLimiterConfig() + ); + } + + /// @notice Returns the rate limiter configuration for the outbound rate limiter + /// The onRamp rate limit for ETH => ARB will be as follows: + /// Capacity: 350_000 GHO + /// Rate: 100 GHO per second (=> 360_000 GHO per hour) + /// @return The rate limiter configuration + function getOutBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + } + + /// @notice Returns the rate limiter configuration for the inbound rate limiter + /// The offramp capacity for ARB => ETH will be disabled, as the outbound rate limit + /// will be set on ARB token pool + /// @return The rate limiter configuration + function getInBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 7de2f9800..7a4518041 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -7,6 +7,7 @@ import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; @@ -64,15 +65,43 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { * @dev executes the generic test suite including e2e and config snapshots */ function test_defaultProposalExecution() public { + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + bytes memory dynamicParamsBefore = _getDynamicParams(); bytes memory staticParamsBefore = _getStaticParams(); + defaultTest( 'AaveV3Ethereum_GHOCCIP150Upgrade_20241021', AaveV3Ethereum.POOL, address(proposal) ); + assertEq(keccak256(_getDynamicParams()), keccak256(dynamicParamsBefore)); assertEq(keccak256(_getStaticParams()), keccak256(staticParamsBefore)); + + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR)) + ), + abi.encode(proposal.getInBoundRateLimiterConfig()) + ); + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR)) + ), + abi.encode(proposal.getOutBoundRateLimiterConfig()) + ); } function test_getProxyPool() public { @@ -104,7 +133,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 500_000e18; + uint256 amount = 150_000e18; + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); + vm.prank(alice); gho.approve(address(router), amount); deal(address(gho), alice, amount); @@ -135,7 +168,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 500_000e18; + uint256 amount = 350_000e18; + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); + vm.prank(alice); gho.approve(address(router), amount); deal(address(gho), alice, amount); @@ -165,16 +202,16 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 500_000e18; + uint256 amount = 350_000e18; + + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); // mock previously locked gho deal(address(gho), address(ghoTokenPool), amount); - address offRamp = _getOffRamp({router: router, migrated: false}); - vm.expectEmit(address(ghoTokenPool)); - emit Released(offRamp, alice, amount); - vm.prank(offRamp); + emit Released(OFF_RAMP_1_2, alice, amount); + vm.prank(OFF_RAMP_1_2); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); assertEq(gho.balanceOf(alice), amount); @@ -186,16 +223,15 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 500_000e18; + uint256 amount = 350_000e18; + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); // mock previously locked gho deal(address(gho), address(ghoTokenPool), amount); - address offRamp = _getOffRamp({router: router, migrated: true}); - vm.expectEmit(address(ghoTokenPool)); - emit Released(offRamp, alice, amount); - vm.prank(offRamp); + emit Released(OFF_RAMP_1_5, alice, amount); + vm.prank(OFF_RAMP_1_5); ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); assertEq(gho.balanceOf(alice), amount); @@ -212,6 +248,9 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); + // wait for the rate limiter to refill + skip(_getOutboundRefillTime(amount)); + vm.expectEmit(address(ghoTokenPool)); emit Locked(address(proxyPool), amount); vm.prank(address(proxyPool)); @@ -307,23 +346,6 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return (message, eventArg); } - function _getOffRamp(IRouter router, bool migrated) internal view returns (address) { - IRouter.OffRamp[] memory offRamps = router.getOffRamps(); - for (uint256 i; i < offRamps.length; ++i) { - IRouter.OffRamp memory config = offRamps[i]; - if (config.sourceChainSelector == ARB_CHAIN_SELECTOR) { - address offRamp = config.offRamp; - if ( - keccak256(bytes(ITypeAndVersion(offRamp).typeAndVersion())) == - keccak256(bytes(migrated ? 'EVM2EVMOffRamp 1.5.0' : 'EVM2EVMOffRamp 1.2.0')) - ) { - return offRamp; - } - } - } - assert(false); - } - function _getImplementation(address proxy) private view returns (address) { bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); return address(uint160(uint256(vm.load(proxy, slot)))); @@ -358,8 +380,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ghoTokenPool.getLockReleaseInterfaceId(), ghoTokenPool.getBridgeLimit(), ghoTokenPool.getCurrentBridgedAmount(), - ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), - ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR) + ghoTokenPool.getRateLimitAdmin() ); } @@ -371,4 +392,25 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_5).typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); } + + function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { + uint128 rate = proposal.getOutBoundRateLimiterConfig().rate; + assertNotEq(rate, 0); + return amount / uint256(rate) + 1; // account for rounding + } + + function _tokenBucketToConfig( + RateLimiter.TokenBucket memory bucket + ) private pure returns (RateLimiter.Config memory) { + return + RateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() private pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } } diff --git a/src/interfaces/ccip/IRateLimiter.sol b/src/interfaces/ccip/IRateLimiter.sol index 983e9b1af..d4cb9ffa4 100644 --- a/src/interfaces/ccip/IRateLimiter.sol +++ b/src/interfaces/ccip/IRateLimiter.sol @@ -3,6 +3,14 @@ pragma solidity ^0.8.0; interface IRateLimiter { + struct TokenBucket { + uint128 tokens; // ──────╮ Current number of tokens that are in the bucket. + uint32 lastUpdated; // │ Timestamp in seconds of the last token refill, good for 100+ years. + bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not + uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket. + uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled. + } + struct Config { bool isEnabled; // Indication whether the rate limiting should be enabled uint128 capacity; // ────╮ Specifies the capacity of the rate limiter From af02c9eaaf3f05213654fde716e90213d9589c15 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:58:15 +0530 Subject: [PATCH 24/57] feat: set in bound rate limit as well --- ...eV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 7 +- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 77 ++++++++++++++++++- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 55 ++++++++++--- ...eV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 7 +- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 12 ++- 5 files changed, 138 insertions(+), 20 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 0bc20c882..493504d02 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -57,10 +57,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { } /// @notice Returns the rate limiter configuration for the inbound rate limiter - /// The offramp capacity for ETH => ARB will be disabled, as the outbound rate limit - /// will be set on ETH token pool + /// The offRamp rate limit for ETH => ARB will be as follows: + /// Capacity: 350_000 GHO + /// Rate: 100 GHO per second (=> 360_000 GHO per hour) /// @return The rate limiter configuration function getInBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 65c72808a..94c570f1d 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -143,6 +143,66 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); } + // function test_fuzzOutBoundRateLimit(uint256 amount) public { + // // executePayload(vm, address(proposal)); + + // (uint256 bucketCapacity, ) = IGhoToken(ARB_GHO_TOKEN).getFacilitatorBucket( + // address(ghoTokenPool) + // ); + // amount = bound(amount, 0, bucketCapacity); + // deal(ARB_GHO_TOKEN, alice, amount); + + // IRouter router = IRouter(ghoTokenPool.getRouter()); + // vm.prank(alice); + // IERC20(ARB_GHO_TOKEN).approve(address(router), amount); + // uint256 capacity = proposal.getOutBoundRateLimiterConfig().capacity; + + // ( + // IClient.EVM2AnyMessage memory message, + // IInternal.EVM2EVMMessage memory eventArg + // ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: false})); + + // if (amount > capacity) { + // vm.expectRevert( + // abi.encodeWithSelector( + // RateLimiter.AggregateValueMaxCapacityExceeded.selector, + // capacity, + // amount + // ) + // ); + // } else { + // vm.expectRevert( + // abi.encodeWithSelector( + // RateLimiter.TokenRateLimitReached.selector, + // 1 /* minWaitInSeconds */, + // 0 /* available */, + // ARB_GHO_TOKEN + // ) // since the upgrade has just happened this block + // ); + // } + // vm.prank(alice); + // router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + + // skip(_getOutboundRefillTime(amount)); + + // if (amount > capacity) { + // vm.expectRevert( + // abi.encodeWithSelector( + // RateLimiter.AggregateValueMaxCapacityExceeded.selector, + // capacity, + // amount + // ) + // ); + // } else { + // vm.expectEmit(address(ghoTokenPool)); + // emit Burned(ON_RAMP_1_2, amount); + // vm.expectEmit(ON_RAMP_1_2); + // emit CCIPSendRequested(eventArg); + // } + // vm.prank(alice); + // router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + // } + function test_sendMessagePreCCIPMigration() public { executePayload(vm, address(proposal)); @@ -214,7 +274,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill - skip(_getOutboundRefillTime(amount)); + skip(_getInboundRefillTime(amount)); vm.expectEmit(address(ghoTokenPool)); emit Minted(OFF_RAMP_1_2, alice, amount); @@ -234,7 +294,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill - skip(_getOutboundRefillTime(amount)); + skip(_getInboundRefillTime(amount)); vm.expectEmit(address(ghoTokenPool)); emit Minted(OFF_RAMP_1_5, alice, amount); @@ -279,6 +339,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + // wait for the rate limiter to refill + skip(_getInboundRefillTime(amount)); + vm.expectEmit(address(ghoTokenPool)); emit Minted(address(proxyPool), alice, amount); vm.prank(address(proxyPool)); @@ -288,6 +351,10 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } + function test_sendRevertOnInvalidMessageFormat() public { + // invalid message format: 1.2 after migration, 1.5 before migration + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration @@ -406,6 +473,12 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return amount / uint256(rate) + 1; // account for rounding } + function _getInboundRefillTime(uint256 amount) private view returns (uint256) { + uint128 rate = proposal.getInBoundRateLimiterConfig().rate; + assertNotEq(rate, 0); + return amount / uint256(rate) + 1; // account for rounding + } + function _tokenBucketToConfig( RateLimiter.TokenBucket memory bucket ) private pure returns (RateLimiter.Config memory) { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 5d09119e1..4bdf712d8 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -288,9 +288,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l1.proposal.getOutBoundRateLimiterConfig().rate; // wait for the rate limiter to refill - skip(amount / uint256(rate) + 1); // rate is non zero + skip(amount / uint256(outBoundRate) + 1); // rate is non zero uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.tokenPool)); uint256 bridgedAmount = l1.tokenPool.getCurrentBridgedAmount(); @@ -325,6 +325,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is uint256 aliceBalanceBefore = l2.c.token.balanceOf(alice); + uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + vm.expectEmit(address(l2.tokenPool)); emit Minted(address(l2.c.EVM2EVMOffRamp1_2), alice, amount); vm.prank(address(l2.c.EVM2EVMOffRamp1_2)); @@ -342,9 +346,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l2.proposal.getOutBoundRateLimiterConfig().rate; // wait for the rate limiter to refill - skip(amount / uint256(rate) + 1); // rate is non zero + skip(amount / uint256(outBoundRate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -375,6 +379,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is uint256 tokenPoolBalanceBefore = l1.c.token.balanceOf(address(l1.tokenPool)); + uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + vm.expectEmit(address(l1.tokenPool)); emit Released(address(l1.c.EVM2EVMOffRamp1_2), alice, amount); vm.prank(address(l1.c.EVM2EVMOffRamp1_2)); @@ -416,9 +424,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l1.proposal.getOutBoundRateLimiterConfig().rate; // wait for the rate limiter to refill - skip(amount / uint256(rate) + 1); // rate is non zero + skip(amount / uint256(outBoundRate) + 1); // rate is non zero uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.tokenPool)); uint256 bridgedAmount = l1.tokenPool.getCurrentBridgedAmount(); @@ -456,6 +464,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is // ARB executeMessage vm.selectFork(l2.c.forkId); + uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + vm.expectEmit(address(l2.tokenPool)); emit Minted(address(l2.c.EVM2EVMOffRamp1_2), alice, amount); vm.prank(address(l2.c.EVM2EVMOffRamp1_2)); @@ -464,6 +476,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is new bytes[](message.tokenAmounts.length) ); + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + vm.expectEmit(address(l2.c.proxyPool)); // emitter is proxyPool for 1.5 on ramp emit Minted(address(l2.c.EVM2EVMOffRamp1_5), alice, amount); vm.prank(address(l2.c.EVM2EVMOffRamp1_5)); @@ -480,9 +495,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l2.proposal.getOutBoundRateLimiterConfig().rate; // wait for the rate limiter to refill - skip(amount / uint256(rate) + 1); // rate is non zero + skip(amount / uint256(outBoundRate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -516,6 +531,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is uint256 tokenPoolBalanceBefore = l1.c.token.balanceOf(address(l1.tokenPool)); + uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + vm.expectEmit(address(l1.c.proxyPool)); // emitter is proxyPool for 1.5 off ramp emit Released(address(l1.c.EVM2EVMOffRamp1_5), alice, amount); vm.prank(address(l1.c.EVM2EVMOffRamp1_5)); @@ -608,6 +627,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); + uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + ( IClient.EVM2AnyMessage memory message, IInternal.EVM2EVMMessage memory eventArg @@ -643,6 +666,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); + uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + ( IClient.EVM2AnyMessage memory message, IInternal.EVM2EVMMessage memory eventArg @@ -728,6 +755,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is // CCIP Migration on L2 _mockCCIPMigration(l2.c, l1.c); + uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + // reverts with 1.5 off ramp vm.expectRevert(); vm.prank(address(l2.c.EVM2EVMOffRamp1_5)); @@ -756,9 +787,9 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l2.proposal.getOutBoundRateLimiterConfig().rate; // wait for the rate limiter to refill - skip(amount / uint256(rate) + 1); // rate is non zero + skip(amount / uint256(outBoundRate) + 1); // rate is non zero ( IClient.EVM2AnyMessage memory message, @@ -788,6 +819,10 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is // CCIP Migration on L2 _mockCCIPMigration(l1.c, l1.c); + uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + // wait for the rate limiter to refill + skip(amount / uint256(inBoundRate) + 1); // rate is non zero + // reverts with 1.5 off ramp vm.expectRevert(); vm.prank(address(l1.c.EVM2EVMOffRamp1_5)); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index c261248fc..00ae3566f 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -58,10 +58,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { } /// @notice Returns the rate limiter configuration for the inbound rate limiter - /// The offramp capacity for ARB => ETH will be disabled, as the outbound rate limit - /// will be set on ARB token pool + /// The offRamp rate limit for ARB=>ETH will be as follows: + /// Capacity: 350_000 GHO + /// Rate: 100 GHO per second (=> 360_000 GHO per hour) /// @return The rate limiter configuration function getInBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 7a4518041..b6a8df092 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -205,7 +205,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { uint256 amount = 350_000e18; // wait for the rate limiter to refill - skip(_getOutboundRefillTime(amount)); + skip(_getInboundRefillTime(amount)); // mock previously locked gho deal(address(gho), address(ghoTokenPool), amount); @@ -225,7 +225,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); uint256 amount = 350_000e18; // wait for the rate limiter to refill - skip(_getOutboundRefillTime(amount)); + skip(_getInboundRefillTime(amount)); // mock previously locked gho deal(address(gho), address(ghoTokenPool), amount); @@ -269,6 +269,8 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); // mock previously locked gho deal(MiscEthereum.GHO_TOKEN, address(ghoTokenPool), amount); + // wait for the rate limiter to refill + skip(_getInboundRefillTime(amount)); vm.expectEmit(address(ghoTokenPool)); emit Released(address(proxyPool), alice, amount); @@ -399,6 +401,12 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return amount / uint256(rate) + 1; // account for rounding } + function _getInboundRefillTime(uint256 amount) private view returns (uint256) { + uint128 rate = proposal.getInBoundRateLimiterConfig().rate; + assertNotEq(rate, 0); + return amount / uint256(rate) + 1; // account for rounding + } + function _tokenBucketToConfig( RateLimiter.TokenBucket memory bucket ) private pure returns (RateLimiter.Config memory) { From 95070805950b3ba08cac244187b682cb8a9a7928 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:36:50 +0530 Subject: [PATCH 25/57] chore: cleanup --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 68 ++----------------- 1 file changed, 4 insertions(+), 64 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 94c570f1d..6280efab5 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -17,6 +17,7 @@ import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IEVM2EVMOffRamp_1_2, IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; @@ -38,6 +39,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { address internal alice = makeAddr('alice'); + bytes32 internal constant CCIP_SEND_EVENT_SIG = + 0xd0c3c799bf9e2639de44391e7f524d229b2b55f5b1ea94b2bf7da42f7243dddd; uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; address internal constant ARB_GHO_TOKEN = AaveV3ArbitrumAssets.GHO_UNDERLYING; @@ -55,6 +58,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); error CallerIsNotARampOnRouter(address caller); + error NotACompatiblePool(address pool); function setUp() public { vm.createSelectFork(vm.rpcUrl('arbitrum'), 267660907); @@ -143,66 +147,6 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); } - // function test_fuzzOutBoundRateLimit(uint256 amount) public { - // // executePayload(vm, address(proposal)); - - // (uint256 bucketCapacity, ) = IGhoToken(ARB_GHO_TOKEN).getFacilitatorBucket( - // address(ghoTokenPool) - // ); - // amount = bound(amount, 0, bucketCapacity); - // deal(ARB_GHO_TOKEN, alice, amount); - - // IRouter router = IRouter(ghoTokenPool.getRouter()); - // vm.prank(alice); - // IERC20(ARB_GHO_TOKEN).approve(address(router), amount); - // uint256 capacity = proposal.getOutBoundRateLimiterConfig().capacity; - - // ( - // IClient.EVM2AnyMessage memory message, - // IInternal.EVM2EVMMessage memory eventArg - // ) = _getTokenMessage(CCIPSendParams({router: router, amount: amount, migrated: false})); - - // if (amount > capacity) { - // vm.expectRevert( - // abi.encodeWithSelector( - // RateLimiter.AggregateValueMaxCapacityExceeded.selector, - // capacity, - // amount - // ) - // ); - // } else { - // vm.expectRevert( - // abi.encodeWithSelector( - // RateLimiter.TokenRateLimitReached.selector, - // 1 /* minWaitInSeconds */, - // 0 /* available */, - // ARB_GHO_TOKEN - // ) // since the upgrade has just happened this block - // ); - // } - // vm.prank(alice); - // router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); - - // skip(_getOutboundRefillTime(amount)); - - // if (amount > capacity) { - // vm.expectRevert( - // abi.encodeWithSelector( - // RateLimiter.AggregateValueMaxCapacityExceeded.selector, - // capacity, - // amount - // ) - // ); - // } else { - // vm.expectEmit(address(ghoTokenPool)); - // emit Burned(ON_RAMP_1_2, amount); - // vm.expectEmit(ON_RAMP_1_2); - // emit CCIPSendRequested(eventArg); - // } - // vm.prank(alice); - // router.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); - // } - function test_sendMessagePreCCIPMigration() public { executePayload(vm, address(proposal)); @@ -351,10 +295,6 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } - function test_sendRevertOnInvalidMessageFormat() public { - // invalid message format: 1.2 after migration, 1.5 before migration - } - function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration From 1f15974ca1e19234928dd47c40b7926be0bb6584 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:42:09 +0530 Subject: [PATCH 26/57] test: check proxy initialized version --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 5 ++--- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 6280efab5..b96fea273 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -17,7 +17,6 @@ import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IEVM2EVMOffRamp_1_2, IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; @@ -39,8 +38,6 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { address internal alice = makeAddr('alice'); - bytes32 internal constant CCIP_SEND_EVENT_SIG = - 0xd0c3c799bf9e2639de44391e7f524d229b2b55f5b1ea94b2bf7da42f7243dddd; uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; address internal constant ARB_GHO_TOKEN = AaveV3ArbitrumAssets.GHO_UNDERLYING; @@ -137,12 +134,14 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { vm.expectRevert('Initializable: contract is already initialized'); ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); /// proxy implementation is initialized + assertEq(_readInitialized(address(ghoTokenPool)), 1); assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); executePayload(vm, address(proposal)); vm.expectRevert('Initializable: contract is already initialized'); ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); + assertEq(_readInitialized(address(ghoTokenPool)), 1); /// proxy implementation is initialized assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index b6a8df092..a2fa1f833 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -117,6 +117,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function test_tokenPoolCannotBeInitializedAgain() public { vm.expectRevert('Initializable: contract is already initialized'); ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router'), 0); + assertEq(_readInitialized(address(ghoTokenPool)), 1); /// proxy implementation is initialized assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); @@ -124,6 +125,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { vm.expectRevert('Initializable: contract is already initialized'); ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router'), 0); + assertEq(_readInitialized(address(ghoTokenPool)), 1); /// proxy implementation is initialized assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); } From 3954cb7b749b81978061893a3fb55d15604eaf35 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:29:52 +0530 Subject: [PATCH 27/57] chore: inBetween => inFlight" --- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 4bdf712d8..85d15fddc 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -700,7 +700,8 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is } } -contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is +// sendMsg => CCIP Migration => executeMsg +contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is AaveV3E2E_GHOCCIP150Upgrade_20241021_Base { function setUp() public override { @@ -715,7 +716,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is _validateConfig({migrated: false}); } - function test_sendFlowInBetweenCCIPMigrationFromEth() public { + function test_sendFlowInFlightCCIPMigrationFromEth() public { // ETH => ARB, ccipSend 1.4; CCIP migration, Destination executeMessage { vm.selectFork(l1.c.forkId); @@ -751,10 +752,12 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is assertEq(l1.c.token.balanceOf(alice), 0); - vm.selectFork(l2.c.forkId); - // CCIP Migration on L2 + // CCIP Migration + _mockCCIPMigration(l1.c, l2.c); _mockCCIPMigration(l2.c, l1.c); + vm.selectFork(l2.c.forkId); + uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -779,7 +782,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is } } - function test_sendFlowInBetweenCCIPMigrationFromArb() public { + function test_sendFlowInFlightCCIPMigrationFromArb() public { // ARB => ETH, ccipSend 1.4; CCIP migration, Destination executeMessage { vm.selectFork(l2.c.forkId); @@ -815,9 +818,11 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InBetweenCCIPMigration is assertEq(l2.c.token.balanceOf(alice), 0); - vm.selectFork(l1.c.forkId); - // CCIP Migration on L2 + // CCIP Migration _mockCCIPMigration(l1.c, l1.c); + _mockCCIPMigration(l2.c, l1.c); + + vm.selectFork(l1.c.forkId); uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; // wait for the rate limiter to refill From 9abb6d3bb54a4d1cdb6fd466b6a9c53dc7823cb6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 30 Oct 2024 23:54:26 +0530 Subject: [PATCH 28/57] chore: test name consistency --- .../AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 85d15fddc..8f905e84f 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -716,7 +716,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is _validateConfig({migrated: false}); } - function test_sendFlowInFlightCCIPMigrationFromEth() public { + function test_SendFlowInFlightCCIPMigrationFromEth() public { // ETH => ARB, ccipSend 1.4; CCIP migration, Destination executeMessage { vm.selectFork(l1.c.forkId); @@ -782,7 +782,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is } } - function test_sendFlowInFlightCCIPMigrationFromArb() public { + function test_SendFlowInFlightCCIPMigrationFromArb() public { // ARB => ETH, ccipSend 1.4; CCIP migration, Destination executeMessage { vm.selectFork(l2.c.forkId); @@ -819,7 +819,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is assertEq(l2.c.token.balanceOf(alice), 0); // CCIP Migration - _mockCCIPMigration(l1.c, l1.c); + _mockCCIPMigration(l1.c, l2.c); _mockCCIPMigration(l2.c, l1.c); vm.selectFork(l1.c.forkId); From ced148d9d261b77e65b72743382dff377ab6495a Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 31 Oct 2024 03:16:43 +0530 Subject: [PATCH 29/57] test: dynamically fetch dest gas amt --- .../utils/CCIPUtils.sol | 10 ++++- src/interfaces/ccip/IEVM2EVMOnRamp.sol | 38 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol b/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol index f7d20897b..c73b30175 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/utils/CCIPUtils.sol @@ -87,7 +87,7 @@ library CCIPUtils { ), destTokenAddress: abi.encode(params.destinationToken), extraData: '', - destGasAmount: 90000 + destGasAmount: getDestGasAmount(onRamp, params.message.tokenAmounts[i].token) }) ); } @@ -150,4 +150,12 @@ library CCIPUtils { ) ); } + + function getDestGasAmount(IEVM2EVMOnRamp onRamp, address token) internal view returns (uint32) { + IEVM2EVMOnRamp.TokenTransferFeeConfig memory config = onRamp.getTokenTransferFeeConfig(token); + return + config.isEnabled + ? config.destGasOverhead + : onRamp.getDynamicConfig().defaultTokenDestGasOverhead; + } } diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol index e73bc188c..20efb0cfd 100644 --- a/src/interfaces/ccip/IEVM2EVMOnRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -5,6 +5,35 @@ pragma solidity ^0.8.0; import {IInternal} from './IInternal.sol'; interface IEVM2EVMOnRamp { + struct TokenTransferFeeConfig { + uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD + uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD + uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 + uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain + // │ Extra data availability bytes that are returned from the source pool and sent + uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + bool aggregateRateLimitEnabled; // │ Whether this transfer token is to be included in Aggregate Rate Limiting + bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees + } + + struct DynamicConfig { + address router; // ──────────────────────────╮ Router address + uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message + uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs + uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver + uint32 destDataAvailabilityOverheadGas; // ──╯ Extra data availability gas charged on top of the message, e.g. for OCR + uint16 destGasPerDataAvailabilityByte; // ───╮ Amount of gas to charge per byte of message data that needs availability + uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 + address priceRegistry; // │ Price registry address + uint32 maxDataBytes; // │ Maximum payload data size in bytes + uint32 maxPerMsgGasLimit; // ────────────────╯ Maximum gas limit for messages targeting EVMs + // │ + // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token + uint16 defaultTokenFeeUSDCents; // ──────────╮ Default token fee charged per token transfer + uint32 defaultTokenDestGasOverhead; // │ Default gas charged to execute the token transfer on the destination chain + bool enforceOutOfOrder; // ──────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. + } + /// @notice Gets the next sequence number to be used in the onRamp /// @return the next sequence number to be used function getExpectedNextSequenceNumber() external view returns (uint64); @@ -30,4 +59,13 @@ interface IEVM2EVMOnRamp { uint64 destChainSelector, address sourceToken ) external view returns (address); + + /// @notice Gets the transfer fee config for a given token. + function getTokenTransferFeeConfig( + address token + ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig); + + /// @notice Returns the dynamic onRamp config. + /// @return dynamicConfig the configuration. + function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig); } From b1da849eda95e50974e518002966c80a50c8bd71 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 31 Oct 2024 03:31:57 +0530 Subject: [PATCH 30/57] test: execMsg post migration using legacy off ramp --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 20 ++++++++++++++++++ ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 21 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index b96fea273..9d94bc187 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -248,6 +248,26 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } + function test_executeMessagePostCCIPMigrationViaLegacyOffRamp() public { + executePayload(vm, address(proposal)); + + _mockCCIPMigration(); + + uint256 amount = 350_000e18; + uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); + + // wait for the rate limiter to refill + skip(_getInboundRefillTime(amount)); + + vm.expectEmit(address(ghoTokenPool)); + emit Minted(OFF_RAMP_1_2, alice, amount); + vm.prank(OFF_RAMP_1_2); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ETH_CHAIN_SELECTOR, ''); + + assertEq(IERC20(ARB_GHO_TOKEN).balanceOf(alice), amount); + assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); + } + function test_proxyPoolCanOnRamp() public { uint256 amount = 1337e18; diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index a2fa1f833..9f59ac82e 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -239,6 +239,27 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(gho.balanceOf(alice), amount); } + function test_executeMessagePostCCIPMigrationViaLegacyOffRamp() public { + executePayload(vm, address(proposal)); + + _mockCCIPMigration(); + + IERC20 gho = IERC20(address(ghoTokenPool.getToken())); + uint256 amount = 350_000e18; + + // wait for the rate limiter to refill + skip(_getInboundRefillTime(amount)); + // mock previously locked gho + deal(address(gho), address(ghoTokenPool), amount); + + vm.expectEmit(address(ghoTokenPool)); + emit Released(OFF_RAMP_1_2, alice, amount); + vm.prank(OFF_RAMP_1_2); + ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, ''); + + assertEq(gho.balanceOf(alice), amount); + } + function test_proxyPoolCanOnRamp() public { uint256 amount = 1337e18; From bf4f3e5a7a38dd5facb2cb655542d8bf94843a6d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 31 Oct 2024 04:57:03 +0530 Subject: [PATCH 31/57] test: ccip steward can disable rate limit --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 39 ++++++++++++++ ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 40 +++++++++++++++ src/interfaces/IGhoCcipSteward.sol | 51 +++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/interfaces/IGhoCcipSteward.sol diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 9d94bc187..33f526aae 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -17,6 +17,7 @@ import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; @@ -50,6 +51,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { address internal constant OFF_RAMP_1_2 = 0x542ba1902044069330e8c5b36A84EC503863722f; address internal constant OFF_RAMP_1_5 = 0x91e46cc5590A4B9182e47f40006140A7077Dec31; + IGhoCcipSteward internal constant GHO_CCIP_STEWARD = + IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); + event Burned(address indexed sender, uint256 amount); event Minted(address indexed sender, address indexed recipient, uint256 amount); event CCIPSendRequested(IInternal.EVM2EVMMessage message); @@ -314,6 +318,29 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } + function test_stewardCanDisableRateLimit() public { + executePayload(vm, address(proposal)); + + vm.prank(ghoTokenPool.owner()); + ghoTokenPool.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); + + vm.prank(_readRiskAdmin()); + GHO_CCIP_STEWARD.updateRateLimit(ETH_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); + + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration @@ -393,6 +420,15 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + function _readRiskAdmin() private view returns (address riskAdmin) { + // private immutable at offset 144 + address steward = address(GHO_CCIP_STEWARD); + assembly { + extcodecopy(steward, 0, 144, 20) // use scratch space + riskAdmin := shr(96, mload(0)) // correct padding + } + } + function _getFacilitatorLevel(address f) internal view returns (uint256) { (, uint256 level) = IGhoToken(ARB_GHO_TOKEN).getFacilitatorBucket(f); return level; @@ -424,6 +460,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ITypeAndVersion(ON_RAMP_1_5).typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_5).typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + + assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), ARB_GHO_TOKEN); + assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 9f59ac82e..45305e31c 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -15,6 +15,7 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; @@ -41,11 +42,15 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { address internal constant ARB_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + address internal constant ON_RAMP_1_2 = 0x925228D7B82d883Dde340A55Fe8e6dA56244A22C; address internal constant ON_RAMP_1_5 = 0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284; address internal constant OFF_RAMP_1_2 = 0xeFC4a18af59398FF23bfe7325F2401aD44286F4d; address internal constant OFF_RAMP_1_5 = 0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9; + IGhoCcipSteward internal constant GHO_CCIP_STEWARD = + IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); + event Locked(address indexed sender, uint256 amount); event Released(address indexed sender, address indexed recipient, uint256 amount); event CCIPSendRequested(IInternal.EVM2EVMMessage message); @@ -301,6 +306,29 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, new bytes(0)); } + function test_stewardDisableRateLimit() public { + executePayload(vm, address(proposal)); + + vm.prank(ghoTokenPool.owner()); + ghoTokenPool.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); + + vm.prank(_readRiskAdmin()); + GHO_CCIP_STEWARD.updateRateLimit(ARB_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); + + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + assertEq( + abi.encode( + _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR)) + ), + abi.encode(_getDisabledConfig()) + ); + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration @@ -383,6 +411,15 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + function _readRiskAdmin() private view returns (address riskAdmin) { + // private immutable at offset 144 + address steward = address(GHO_CCIP_STEWARD); + assembly { + extcodecopy(steward, 0, 144, 20) // use scratch space + riskAdmin := shr(96, mload(0)) // correct padding + } + } + function _getStaticParams() private view returns (bytes memory) { return abi.encode( @@ -416,6 +453,9 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ITypeAndVersion(ON_RAMP_1_5).typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_2).typeAndVersion(), 'EVM2EVMOffRamp 1.2.0'); assertEq(ITypeAndVersion(OFF_RAMP_1_5).typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + + assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); + assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { diff --git a/src/interfaces/IGhoCcipSteward.sol b/src/interfaces/IGhoCcipSteward.sol new file mode 100644 index 000000000..f3dfec74f --- /dev/null +++ b/src/interfaces/IGhoCcipSteward.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.10; + +interface IGhoCcipSteward { + /** + * @notice Updates the CCIP bridge limit + * @dev Only callable by Risk Council + * @param newBridgeLimit The new desired bridge limit + */ + function updateBridgeLimit(uint256 newBridgeLimit) external; + + /** + * @notice Updates the CCIP rate limit config + * @dev Only callable by Risk Council + * @dev Rate limit update must be consistent with other pools' rate limit + * @param remoteChainSelector The remote chain selector for which the rate limits apply. + * @param outboundEnabled True if the outbound rate limiter is enabled. + * @param outboundCapacity The outbound rate limiter capacity. + * @param outboundRate The outbound rate limiter rate. + * @param inboundEnabled True if the inbound rate limiter is enabled. + * @param inboundCapacity The inbound rate limiter capacity. + * @param inboundRate The inbound rate limiter rate. + */ + function updateRateLimit( + uint64 remoteChainSelector, + bool outboundEnabled, + uint128 outboundCapacity, + uint128 outboundRate, + bool inboundEnabled, + uint128 inboundCapacity, + uint128 inboundRate + ) external; + + /** + * @notice Returns the minimum delay that must be respected between parameters update. + * @return The minimum delay between parameter updates (in seconds) + */ + function MINIMUM_DELAY() external view returns (uint256); + + /** + * @notice Returns the address of the Gho Token + * @return The address of the GhoToken + */ + function GHO_TOKEN() external view returns (address); + + /** + * @notice Returns the address of the Gho CCIP Token Pool + * @return The address of the Gho CCIP Token Pool + */ + function GHO_TOKEN_POOL() external view returns (address); +} From a525136d44e2db441855715da3092a57bc05a89c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 31 Oct 2024 05:07:34 +0530 Subject: [PATCH 32/57] chore: cleanup --- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 45305e31c..36def8a96 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; @@ -38,7 +39,6 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; - address internal constant ARB_GHO_TOKEN = 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33; address internal constant ARB_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); @@ -346,7 +346,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { chains[0] = IProxyPool.ChainUpdate({ remoteChainSelector: ARB_CHAIN_SELECTOR, remotePoolAddress: abi.encode(ARB_PROXY_POOL), - remoteTokenAddress: abi.encode(address(ARB_GHO_TOKEN)), + remoteTokenAddress: abi.encode(address(AaveV3ArbitrumAssets.GHO_UNDERLYING)), allowed: true, outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) @@ -391,7 +391,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { sourceChainSelector: ETH_CHAIN_SELECTOR, feeTokenAmount: feeAmount, originalSender: alice, - destinationToken: ARB_GHO_TOKEN, + destinationToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, migrated: params.migrated }) ); From be370f60c1c7d1bd3a5246f3a67799bfa339253c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:41:31 +0530 Subject: [PATCH 33/57] doc: add comment for fetching all offramps, use RISK_COUNCIL for clarity --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 3 ++- .../AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 4 +++- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 3 ++- src/interfaces/IGhoCcipSteward.sol | 6 ++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 33f526aae..1fe9faffa 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -324,7 +324,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { vm.prank(ghoTokenPool.owner()); ghoTokenPool.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); - vm.prank(_readRiskAdmin()); + vm.prank(GHO_CCIP_STEWARD.RISK_COUNCIL()); GHO_CCIP_STEWARD.updateRateLimit(ETH_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); assertEq( @@ -463,6 +463,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), ARB_GHO_TOKEN); assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); + assertEq(GHO_CCIP_STEWARD.RISK_COUNCIL(), _readRiskAdmin()); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 8f905e84f..e62080247 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -161,6 +161,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { assertTrue(l1.c.router.isOffRamp(l2.c.chainSelector, address(l1.c.EVM2EVMOffRamp1_2))); assertTrue(l1.c.router.isOffRamp(l2.c.chainSelector, address(l1.c.EVM2EVMOffRamp1_5))); + // ensure only 1.2 & 1.5 offRamps are configured IRouter.OffRamp[] memory offRamps = l1.c.router.getOffRamps(); for (uint256 i; i < offRamps.length; ++i) { if (offRamps[i].sourceChainSelector == l2.c.chainSelector) { @@ -203,6 +204,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { assertTrue(l2.c.router.isOffRamp(l1.c.chainSelector, address(l2.c.EVM2EVMOffRamp1_2))); assertTrue(l2.c.router.isOffRamp(l1.c.chainSelector, address(l2.c.EVM2EVMOffRamp1_5))); + // ensure only 1.2 & 1.5 offRamps are configured offRamps = l2.c.router.getOffRamps(); for (uint256 i; i < offRamps.length; ++i) { if (offRamps[i].sourceChainSelector == l1.c.chainSelector) { @@ -762,7 +764,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero - // reverts with 1.5 off ramp + // reverts with 1.5 off ramp because eventArg is in CCIP 1.4 message format vm.expectRevert(); vm.prank(address(l2.c.EVM2EVMOffRamp1_5)); l2.c.EVM2EVMOffRamp1_5.executeSingleMessage( diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 36def8a96..9e3f47ebd 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -312,7 +312,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { vm.prank(ghoTokenPool.owner()); ghoTokenPool.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); - vm.prank(_readRiskAdmin()); + vm.prank(GHO_CCIP_STEWARD.RISK_COUNCIL()); GHO_CCIP_STEWARD.updateRateLimit(ARB_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); assertEq( @@ -456,6 +456,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); + assertEq(GHO_CCIP_STEWARD.RISK_COUNCIL(), _readRiskAdmin()); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { diff --git a/src/interfaces/IGhoCcipSteward.sol b/src/interfaces/IGhoCcipSteward.sol index f3dfec74f..b3166cd73 100644 --- a/src/interfaces/IGhoCcipSteward.sol +++ b/src/interfaces/IGhoCcipSteward.sol @@ -48,4 +48,10 @@ interface IGhoCcipSteward { * @return The address of the Gho CCIP Token Pool */ function GHO_TOKEN_POOL() external view returns (address); + + /** + * @notice Returns the address of the Risk Council + * @return The address of the Risk Council + */ + function RISK_COUNCIL() external view returns (address); } From 8f151e25696fcc5d1e3d2b7f4173885434d855e5 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:12:54 +0530 Subject: [PATCH 34/57] test: ownership transfer after migration --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 22 ++++++++++++++++ ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 26 ++++++++++++++++++- src/interfaces/ccip/IProxyPool.sol | 2 ++ src/interfaces/ccip/ITokenAdminRegistry.sol | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 1fe9faffa..9c04686dc 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -341,6 +341,28 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ); } + function test_ownershipTransferOfGhoProxyPool() public { + executePayload(vm, address(proposal)); + _mockCCIPMigration(); + + assertEq(ghoTokenPool.owner(), AaveV3Arbitrum.ACL_ADMIN); + + // CLL team transfers ownership of proxyPool and GHO token in TokenAdminRegistry + vm.prank(proxyPool.owner()); + proxyPool.transferOwnership(AaveV3Arbitrum.ACL_ADMIN); + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.transferAdminRole(ARB_GHO_TOKEN, AaveV3Arbitrum.ACL_ADMIN); + + // new AIP to accept ownership + vm.startPrank(AaveV3Arbitrum.ACL_ADMIN); + proxyPool.acceptOwnership(); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(ARB_GHO_TOKEN); + vm.stopPrank(); + + assertEq(proxyPool.owner(), AaveV3Arbitrum.ACL_ADMIN); + assertTrue(TOKEN_ADMIN_REGISTRY.isAdministrator(ARB_GHO_TOKEN, AaveV3Arbitrum.ACL_ADMIN)); + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 9e3f47ebd..543a49392 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -306,7 +306,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ghoTokenPool.releaseOrMint(abi.encode(alice), alice, amount, ARB_CHAIN_SELECTOR, new bytes(0)); } - function test_stewardDisableRateLimit() public { + function test_stewardCanDisableRateLimit() public { executePayload(vm, address(proposal)); vm.prank(ghoTokenPool.owner()); @@ -329,6 +329,30 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ); } + function test_ownershipTransferOfGhoProxyPool() public { + executePayload(vm, address(proposal)); + _mockCCIPMigration(); + + assertEq(ghoTokenPool.owner(), AaveV3Ethereum.ACL_ADMIN); + + // CLL team transfers ownership of proxyPool and GHO token in TokenAdminRegistry + vm.prank(proxyPool.owner()); + proxyPool.transferOwnership(AaveV3Ethereum.ACL_ADMIN); + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.transferAdminRole(MiscEthereum.GHO_TOKEN, AaveV3Ethereum.ACL_ADMIN); + + // new AIP to accept ownership + vm.startPrank(AaveV3Ethereum.ACL_ADMIN); + proxyPool.acceptOwnership(); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(MiscEthereum.GHO_TOKEN); + vm.stopPrank(); + + assertEq(proxyPool.owner(), AaveV3Ethereum.ACL_ADMIN); + assertTrue( + TOKEN_ADMIN_REGISTRY.isAdministrator(MiscEthereum.GHO_TOKEN, AaveV3Ethereum.ACL_ADMIN) + ); + } + function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); // token registry not set for 1.5 migration diff --git a/src/interfaces/ccip/IProxyPool.sol b/src/interfaces/ccip/IProxyPool.sol index 3f7c7658b..a5696ffd3 100644 --- a/src/interfaces/ccip/IProxyPool.sol +++ b/src/interfaces/ccip/IProxyPool.sol @@ -15,6 +15,8 @@ interface IProxyPool is ITypeAndVersion { } function owner() external view returns (address); + function transferOwnership(address newOwner) external; + function acceptOwnership() external; function getRouter() external view returns (address); function setRouter(address router) external; function getRemotePool(uint64 chainSelector) external view returns (bytes memory); diff --git a/src/interfaces/ccip/ITokenAdminRegistry.sol b/src/interfaces/ccip/ITokenAdminRegistry.sol index 760982254..05667ccba 100644 --- a/src/interfaces/ccip/ITokenAdminRegistry.sol +++ b/src/interfaces/ccip/ITokenAdminRegistry.sol @@ -6,6 +6,8 @@ interface ITokenAdminRegistry is ITypeAndVersion { function owner() external view returns (address); function acceptAdminRole(address from) external; function proposeAdministrator(address localToken, address administrator) external; + function transferAdminRole(address localToken, address newAdministrator) external; + function isAdministrator(address localToken, address administrator) external view returns (bool); function getPool(address token) external view returns (address); function setPool(address source, address pool) external; } From 00d830620b474eede6666d2916330f83f1bfc0f5 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:41:07 +0530 Subject: [PATCH 35/57] chore: rm _readRiskAdmin, fix config --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 10 ---------- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 10 ---------- src/20241021_Multi_GHOCCIP150Upgrade/config.ts | 6 +++--- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 9c04686dc..795a34dea 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -442,15 +442,6 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } - function _readRiskAdmin() private view returns (address riskAdmin) { - // private immutable at offset 144 - address steward = address(GHO_CCIP_STEWARD); - assembly { - extcodecopy(steward, 0, 144, 20) // use scratch space - riskAdmin := shr(96, mload(0)) // correct padding - } - } - function _getFacilitatorLevel(address f) internal view returns (uint256) { (, uint256 level) = IGhoToken(ARB_GHO_TOKEN).getFacilitatorBucket(f); return level; @@ -485,7 +476,6 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), ARB_GHO_TOKEN); assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); - assertEq(GHO_CCIP_STEWARD.RISK_COUNCIL(), _readRiskAdmin()); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 543a49392..79dd28897 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -435,15 +435,6 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } - function _readRiskAdmin() private view returns (address riskAdmin) { - // private immutable at offset 144 - address steward = address(GHO_CCIP_STEWARD); - assembly { - extcodecopy(steward, 0, 144, 20) // use scratch space - riskAdmin := shr(96, mload(0)) // correct padding - } - } - function _getStaticParams() private view returns (bytes memory) { return abi.encode( @@ -480,7 +471,6 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); - assertEq(GHO_CCIP_STEWARD.RISK_COUNCIL(), _readRiskAdmin()); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts index bbdd55c2f..6c7e1fdad 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts +++ b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts @@ -2,7 +2,7 @@ import {ConfigFile} from '../../generator/types'; export const config: ConfigFile = { rootOptions: { pools: ['AaveV3Ethereum', 'AaveV3Arbitrum'], - title: 'GHO CCIP 1.50 Upgrade', + title: 'GHO CCIP 1.5.0 Upgrade', shortName: 'GHOCCIP150Upgrade', date: '20241021', author: 'Aave Labs', @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21015645}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 266210927}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21045560}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 267660907}}, }, }; From b813da2d85677a7f22d905984c4b18d2a9ca76ad Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 4 Nov 2024 15:52:23 +0530 Subject: [PATCH 36/57] fix: ci test setup to stay compatible with bdg upstream --- .github/workflows/test.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 977839ab4..0f186f228 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,19 +30,7 @@ jobs: test-sol: uses: bgd-labs/github-workflows/.github/workflows/foundry-test.yml@main - secrets: - RPC_MAINNET: "https://eth-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_ARBITRUM: "https://arb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_POLYGON: "https://polygon-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_AVALANCHE: "https://avax-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_OPTIMISM: "https://opt-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_METIS: "https://metis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_BASE: "https://base-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_GNOSIS: "https://gnosis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_BNB: "https://bnb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_ZKEVM: "https://polygonzkevm-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_SCROLL: "https://scroll-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_ZKSYNC: "https://zksync-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + secrets: inherit with: mode: "CHANGED" From bf04350859f0ac9a13b47a236bdd5a332c660af1 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 5 Nov 2024 01:51:05 +0700 Subject: [PATCH 37/57] feat: rm aave-ccip dep --- .gitmodules | 3 --- lib/aave-ccip | 1 - remappings.txt | 1 - 3 files changed, 5 deletions(-) delete mode 160000 lib/aave-ccip diff --git a/.gitmodules b/.gitmodules index d34bc9729..f7316a1d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "lib/aave-helpers"] path = lib/aave-helpers url = https://github.com/bgd-labs/aave-helpers -[submodule "lib/aave-ccip"] - path = lib/aave-ccip - url = https://github.com/aave/ccip diff --git a/lib/aave-ccip b/lib/aave-ccip deleted file mode 160000 index 47a535bb3..000000000 --- a/lib/aave-ccip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 47a535bb3b5829c6d015fcdf8ccdc1357520a2c1 diff --git a/remappings.txt b/remappings.txt index 5900f0f71..9fefc7eea 100644 --- a/remappings.txt +++ b/remappings.txt @@ -3,4 +3,3 @@ aave-helpers/=lib/aave-helpers/ aave-v3-origin/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src/ forge-std/=lib/aave-helpers/lib/forge-std/src/ solidity-utils/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/src -aave-ccip/=lib/aave-ccip/contracts/src/ From d4a30cb9dab84ad1657edb47168a14a71a45acd0 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 5 Nov 2024 01:52:38 +0700 Subject: [PATCH 38/57] rft: use deployed token pools --- ...eV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 31 ++-- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 80 +++++------ ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 71 ++++++---- ...eV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 32 ++--- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 83 +++++------ .../config.ts | 4 +- src/interfaces/ccip/IProxyPool.sol | 10 +- .../ccip/IUpgradeableBurnMintTokenPool.sol | 93 ++++++++++++ .../ccip/IUpgradeableLockReleaseTokenPool.sol | 133 ++++++++++++++---- 9 files changed, 346 insertions(+), 191 deletions(-) create mode 100644 src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 493504d02..07ba0f820 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -5,8 +5,8 @@ import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent- import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; +import {IUpgradeableBurnMintTokenPool} from 'src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; /** * @title GHO CCIP 1.50 Upgrade @@ -14,26 +14,21 @@ import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { - address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; + // https://arbiscan.io/address/0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1 + address public constant TOKEN_POOL_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 + address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; + function execute() external { - UpgradeableBurnMintTokenPool tokenPoolProxy = UpgradeableBurnMintTokenPool( + IUpgradeableBurnMintTokenPool tokenPoolProxy = IUpgradeableBurnMintTokenPool( MiscArbitrum.GHO_CCIP_TOKEN_POOL ); - // Deploy new tokenPool implementation, retain existing immutable configuration - address tokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - address(tokenPoolProxy.getToken()), - tokenPoolProxy.getArmProxy(), - tokenPoolProxy.getAllowListEnabled() - ) - ); - ProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( TransparentUpgradeableProxy(payable(address(tokenPoolProxy))), - tokenPoolImpl + TOKEN_POOL_IMPL ); // Update proxyPool address @@ -52,8 +47,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// Capacity: 350_000 GHO /// Rate: 100 GHO per second (=> 360_000 GHO per hour) /// @return The rate limiter configuration - function getOutBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); } /// @notice Returns the rate limiter configuration for the inbound rate limiter @@ -61,7 +56,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// Capacity: 350_000 GHO /// Rate: 100 GHO per second (=> 360_000 GHO per hour) /// @return The rate limiter configuration - function getInBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 795a34dea..2b67908e2 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -7,8 +7,6 @@ import {AaveV3Arbitrum, AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbi import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; @@ -18,6 +16,7 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IUpgradeableBurnMintTokenPool} from 'src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; @@ -34,7 +33,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { } AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 internal proposal; - UpgradeableBurnMintTokenPool internal ghoTokenPool; + IUpgradeableBurnMintTokenPool internal ghoTokenPool; IProxyPool internal proxyPool; address internal alice = makeAddr('alice'); @@ -62,9 +61,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { error NotACompatiblePool(address pool); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 267660907); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 271012501); proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); - ghoTokenPool = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + ghoTokenPool = IUpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); _validateConstants(); @@ -75,16 +74,12 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { */ function test_defaultProposalExecution() public { assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR)) - ), - abi.encode(_getDisabledConfig()) + ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() ); assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR)) - ), - abi.encode(_getDisabledConfig()) + ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() ); bytes memory dynamicParamsBefore = _getDynamicParams(); @@ -100,16 +95,12 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(keccak256(_getStaticParams()), keccak256(staticParamsBefore)); assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR)) - ), - abi.encode(proposal.getInBoundRateLimiterConfig()) + ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + proposal.getInBoundRateLimiterConfig() ); assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR)) - ), - abi.encode(proposal.getOutBoundRateLimiterConfig()) + ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + proposal.getOutBoundRateLimiterConfig() ); } @@ -365,31 +356,19 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); - // token registry not set for 1.5 migration - assertEq(TOKEN_ADMIN_REGISTRY.getPool(ARB_GHO_TOKEN), address(0)); - vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.proposeAdministrator(ARB_GHO_TOKEN, TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.acceptAdminRole(ARB_GHO_TOKEN); - TOKEN_ADMIN_REGISTRY.setPool(ARB_GHO_TOKEN, address(proxyPool)); - vm.stopPrank(); + assertEq(TOKEN_ADMIN_REGISTRY.getPool(ARB_GHO_TOKEN), address(proxyPool)); assertEq(proxyPool.getRouter(), address(router)); - IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); - chains[0] = IProxyPool.ChainUpdate({ - remoteChainSelector: ETH_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(ETH_PROXY_POOL), - remoteTokenAddress: abi.encode(address(MiscEthereum.GHO_TOKEN)), - allowed: true, - outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.prank(proxyPool.owner()); - proxyPool.applyChainUpdates(chains); - assertTrue(proxyPool.isSupportedChain(ETH_CHAIN_SELECTOR)); + assertEq(proxyPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), _getDisabledConfig()); + assertEq( + proxyPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq(proxyPool.getRemotePool(ETH_CHAIN_SELECTOR), abi.encode(ETH_PROXY_POOL)); + assertEq(proxyPool.getRemoteToken(ETH_CHAIN_SELECTOR), abi.encode(MiscEthereum.GHO_TOKEN)); IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); onRampUpdates[0] = IRouter.OnRamp({ @@ -476,6 +455,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), ARB_GHO_TOKEN); assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); + + assertEq(proxyPool.getPreviousPool(), address(ghoTokenPool)); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { @@ -491,17 +472,24 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { } function _tokenBucketToConfig( - RateLimiter.TokenBucket memory bucket - ) private pure returns (RateLimiter.Config memory) { + IRateLimiter.TokenBucket memory bucket + ) private pure returns (IRateLimiter.Config memory) { return - RateLimiter.Config({ + IRateLimiter.Config({ isEnabled: bucket.isEnabled, capacity: bucket.capacity, rate: bucket.rate }); } - function _getDisabledConfig() private pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + function _getDisabledConfig() private pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index e62080247..4436953b5 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -6,8 +6,6 @@ import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {UpgradeableBurnMintTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; @@ -17,6 +15,8 @@ import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IEVM2EVMOffRamp_1_2, IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IUpgradeableBurnMintTokenPool} from 'src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol'; +import {IUpgradeableLockReleaseTokenPool} from 'src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; @@ -51,13 +51,13 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { struct L1 { AaveV3Ethereum_GHOCCIP150Upgrade_20241021 proposal; - UpgradeableLockReleaseTokenPool tokenPool; + IUpgradeableLockReleaseTokenPool tokenPool; Common c; } struct L2 { AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 proposal; - UpgradeableBurnMintTokenPool tokenPool; + IUpgradeableBurnMintTokenPool tokenPool; Common c; } @@ -75,13 +75,13 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { error NotACompatiblePool(address pool); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21045560); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 267660907); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21115706); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 271012501); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); l1.c.proxyPool = IProxyPool(l1.proposal.GHO_CCIP_PROXY_POOL()); - l1.tokenPool = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + l1.tokenPool = IUpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); l1.c.router = IRouter(l1.tokenPool.getRouter()); l2.c.chainSelector = l1.tokenPool.getSupportedChains()[0]; l1.c.token = IERC20(address(l1.tokenPool.getToken())); @@ -94,7 +94,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { vm.selectFork(l2.c.forkId); l2.proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); l2.c.proxyPool = IProxyPool(l2.proposal.GHO_CCIP_PROXY_POOL()); - l2.tokenPool = UpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + l2.tokenPool = IUpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); l2.c.router = IRouter(l2.tokenPool.getRouter()); l1.c.chainSelector = l2.tokenPool.getSupportedChains()[0]; l2.c.token = IERC20(address(l2.tokenPool.getToken())); @@ -224,32 +224,19 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { function _mockCCIPMigration(Common memory src, Common memory dest) internal { vm.selectFork(src.forkId); - - // token registry not set for 1.5 migration - assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(0)); - vm.startPrank(src.tokenAdminRegistry.owner()); - src.tokenAdminRegistry.proposeAdministrator(address(src.token), src.tokenAdminRegistry.owner()); - src.tokenAdminRegistry.acceptAdminRole(address(src.token)); - src.tokenAdminRegistry.setPool(address(src.token), address(src.proxyPool)); - vm.stopPrank(); assertEq(src.tokenAdminRegistry.getPool(address(src.token)), address(src.proxyPool)); - assertEq(src.proxyPool.getRouter(), address(src.router)); - - IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); - chains[0] = IProxyPool.ChainUpdate({ - remoteChainSelector: dest.chainSelector, - remotePoolAddress: abi.encode(address(dest.proxyPool)), - remoteTokenAddress: abi.encode(address(dest.token)), - allowed: true, - outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.prank(src.proxyPool.owner()); - src.proxyPool.applyChainUpdates(chains); - assertTrue(src.proxyPool.isSupportedChain(dest.chainSelector)); + assertEq( + src.proxyPool.getCurrentInboundRateLimiterState(dest.chainSelector), + _getDisabledConfig() + ); + assertEq( + src.proxyPool.getCurrentOutboundRateLimiterState(dest.chainSelector), + _getDisabledConfig() + ); + assertEq(src.proxyPool.getRemotePool(dest.chainSelector), abi.encode(dest.proxyPool)); + assertEq(src.proxyPool.getRemoteToken(dest.chainSelector), abi.encode(dest.token)); IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); onRampUpdates[0] = IRouter.OnRamp({ @@ -265,6 +252,28 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { vm.prank(src.router.owner()); src.router.applyRampUpdates(onRampUpdates, new IRouter.OffRamp[](0), offRampUpdates); } + + function _getDisabledConfig() private pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) private pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + } } contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 00ae3566f..803f4416b 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -5,8 +5,8 @@ import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent- import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; +import {IUpgradeableLockReleaseTokenPool} from 'src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; /** * @title GHO CCIP 1.50 Upgrade @@ -14,27 +14,21 @@ import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; * - Discussion: https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51 */ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { - address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; uint64 public constant ARB_CHAIN_SELECTOR = 4949039107694359620; + // https://etherscan.io/address/0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1 + address public constant TOKEN_POOL_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 + address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; + function execute() external { - UpgradeableLockReleaseTokenPool tokenPoolProxy = UpgradeableLockReleaseTokenPool( + IUpgradeableLockReleaseTokenPool tokenPoolProxy = IUpgradeableLockReleaseTokenPool( MiscEthereum.GHO_CCIP_TOKEN_POOL ); - // Deploy new tokenPool implementation, retain existing immutable configuration - address tokenPoolImpl = address( - new UpgradeableLockReleaseTokenPool( - address(tokenPoolProxy.getToken()), - tokenPoolProxy.getArmProxy(), - tokenPoolProxy.getAllowListEnabled(), - tokenPoolProxy.canAcceptLiquidity() - ) - ); - ProxyAdmin(MiscEthereum.PROXY_ADMIN).upgrade( TransparentUpgradeableProxy(payable(address(tokenPoolProxy))), - tokenPoolImpl + TOKEN_POOL_IMPL ); // Update proxyPool address @@ -53,8 +47,8 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// Capacity: 350_000 GHO /// Rate: 100 GHO per second (=> 360_000 GHO per hour) /// @return The rate limiter configuration - function getOutBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); } /// @notice Returns the rate limiter configuration for the inbound rate limiter @@ -62,7 +56,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// Capacity: 350_000 GHO /// Rate: 100 GHO per second (=> 360_000 GHO per hour) /// @return The rate limiter configuration - function getInBoundRateLimiterConfig() public pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 79dd28897..68fcf47ed 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -7,8 +7,6 @@ import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {RateLimiter} from 'aave-ccip/v0.8/ccip/libraries/RateLimiter.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; @@ -17,6 +15,7 @@ import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IUpgradeableLockReleaseTokenPool} from 'src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; @@ -32,7 +31,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { } AaveV3Ethereum_GHOCCIP150Upgrade_20241021 internal proposal; - UpgradeableLockReleaseTokenPool internal ghoTokenPool; + IUpgradeableLockReleaseTokenPool internal ghoTokenPool; IProxyPool internal proxyPool; address internal alice = makeAddr('alice'); @@ -58,9 +57,9 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21045560); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21115706); proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); - ghoTokenPool = UpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + ghoTokenPool = IUpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); _validateConstants(); @@ -71,16 +70,12 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { */ function test_defaultProposalExecution() public { assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR)) - ), - abi.encode(_getDisabledConfig()) + ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() ); assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR)) - ), - abi.encode(_getDisabledConfig()) + ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() ); bytes memory dynamicParamsBefore = _getDynamicParams(); @@ -96,16 +91,12 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(keccak256(_getStaticParams()), keccak256(staticParamsBefore)); assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR)) - ), - abi.encode(proposal.getInBoundRateLimiterConfig()) + ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + proposal.getInBoundRateLimiterConfig() ); assertEq( - abi.encode( - _tokenBucketToConfig(ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR)) - ), - abi.encode(proposal.getOutBoundRateLimiterConfig()) + ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + proposal.getOutBoundRateLimiterConfig() ); } @@ -355,31 +346,22 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function _mockCCIPMigration() private { IRouter router = IRouter(ghoTokenPool.getRouter()); - // token registry not set for 1.5 migration - assertEq(TOKEN_ADMIN_REGISTRY.getPool(MiscEthereum.GHO_TOKEN), address(0)); - vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.proposeAdministrator(MiscEthereum.GHO_TOKEN, TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.acceptAdminRole(MiscEthereum.GHO_TOKEN); - TOKEN_ADMIN_REGISTRY.setPool(MiscEthereum.GHO_TOKEN, address(proxyPool)); - vm.stopPrank(); + assertEq(TOKEN_ADMIN_REGISTRY.getPool(MiscEthereum.GHO_TOKEN), address(proxyPool)); assertEq(proxyPool.getRouter(), address(router)); - IProxyPool.ChainUpdate[] memory chains = new IProxyPool.ChainUpdate[](1); - chains[0] = IProxyPool.ChainUpdate({ - remoteChainSelector: ARB_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(ARB_PROXY_POOL), - remoteTokenAddress: abi.encode(address(AaveV3ArbitrumAssets.GHO_UNDERLYING)), - allowed: true, - outboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.prank(proxyPool.owner()); - proxyPool.applyChainUpdates(chains); - assertTrue(proxyPool.isSupportedChain(ARB_CHAIN_SELECTOR)); + assertEq(proxyPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), _getDisabledConfig()); + assertEq( + proxyPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq(proxyPool.getRemotePool(ARB_CHAIN_SELECTOR), abi.encode(ARB_PROXY_POOL)); + assertEq( + proxyPool.getRemoteToken(ARB_CHAIN_SELECTOR), + abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING) + ); IRouter.OnRamp[] memory onRampUpdates = new IRouter.OnRamp[](1); onRampUpdates[0] = IRouter.OnRamp({ @@ -471,6 +453,8 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); assertEq(GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(ghoTokenPool)); + + assertEq(proxyPool.getPreviousPool(), address(ghoTokenPool)); } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { @@ -486,17 +470,24 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { } function _tokenBucketToConfig( - RateLimiter.TokenBucket memory bucket - ) private pure returns (RateLimiter.Config memory) { + IRateLimiter.TokenBucket memory bucket + ) private pure returns (IRateLimiter.Config memory) { return - RateLimiter.Config({ + IRateLimiter.Config({ isEnabled: bucket.isEnabled, capacity: bucket.capacity, rate: bucket.rate }); } - function _getDisabledConfig() private pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + function _getDisabledConfig() private pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts index 6c7e1fdad..9b2cd00f6 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts +++ b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21045560}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 267660907}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21115706}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 271012501}}, }, }; diff --git a/src/interfaces/ccip/IProxyPool.sol b/src/interfaces/ccip/IProxyPool.sol index a5696ffd3..4810b9e9d 100644 --- a/src/interfaces/ccip/IProxyPool.sol +++ b/src/interfaces/ccip/IProxyPool.sol @@ -19,7 +19,15 @@ interface IProxyPool is ITypeAndVersion { function acceptOwnership() external; function getRouter() external view returns (address); function setRouter(address router) external; - function getRemotePool(uint64 chainSelector) external view returns (bytes memory); function applyChainUpdates(ChainUpdate[] memory updates) external; function isSupportedChain(uint64 chainSelector) external view returns (bool); + function getPreviousPool() external view returns (address); + function getCurrentInboundRateLimiterState( + uint64 chainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getCurrentOutboundRateLimiterState( + uint64 chainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getRemotePool(uint64 remoteChainSelector) external view returns (bytes memory); + function getRemoteToken(uint64 remoteChainSelector) external view returns (bytes memory); } diff --git a/src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol b/src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol new file mode 100644 index 000000000..09c322ccc --- /dev/null +++ b/src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IRateLimiter} from './IRateLimiter.sol'; + +interface IUpgradeableBurnMintTokenPool { + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error AllowListNotEnabled(); + error BadARMSignal(); + error BucketOverfilled(); + error CallerIsNotARampOnRouter(address caller); + error ChainAlreadyExists(uint64 chainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error DisabledNonZeroRateLimit(IRateLimiter.Config config); + error InvalidRatelimitRate(IRateLimiter.Config rateLimiterConfig); + error NonExistentChain(uint64 remoteChainSelector); + error RateLimitMustBeDisabled(); + error SenderNotAllowed(address sender); + error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); + error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); + error Unauthorized(address caller); + error ZeroAddressNotAllowed(); + + event AllowListAdd(address sender); + event AllowListRemove(address sender); + event Burned(address indexed sender, uint256 amount); + event ChainAdded( + uint64 remoteChainSelector, + IRateLimiter.Config outboundRateLimiterConfig, + IRateLimiter.Config inboundRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + IRateLimiter.Config outboundRateLimiterConfig, + IRateLimiter.Config inboundRateLimiterConfig + ); + event ChainRemoved(uint64 remoteChainSelector); + event ConfigChanged(IRateLimiter.Config config); + event Initialized(uint8 version); + event Locked(address indexed sender, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event RouterUpdated(address oldRouter, address newRouter); + event TokensConsumed(uint256 tokens); + + function acceptOwnership() external; + function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; + function getAllowList() external view returns (address[] memory); + function getAllowListEnabled() external view returns (bool); + function getArmProxy() external view returns (address armProxy); + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getProxyPool() external view returns (address proxyPool); + function getRateLimitAdmin() external view returns (address); + function getRouter() external view returns (address router); + function getSupportedChains() external view returns (uint64[] memory); + function getToken() external view returns (address token); + function initialize(address owner, address[] memory allowlist, address router) external; + function isSupportedChain(uint64 remoteChainSelector) external view returns (bool); + function lockOrBurn( + address originalSender, + bytes memory, + uint256 amount, + uint64 remoteChainSelector, + bytes memory + ) external returns (bytes memory); + function owner() external view returns (address); + function releaseOrMint( + bytes memory, + address receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes memory + ) external; + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + IRateLimiter.Config memory outboundConfig, + IRateLimiter.Config memory inboundConfig + ) external; + function setProxyPool(address proxyPool) external; + function setRateLimitAdmin(address rateLimitAdmin) external; + function setRouter(address newRouter) external; + function supportsInterface(bytes4 interfaceId) external pure returns (bool); + function transferOwnership(address to) external; + function typeAndVersion() external view returns (string memory); +} diff --git a/src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol b/src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol index 02252f92c..bdc364e79 100644 --- a/src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol +++ b/src/interfaces/ccip/IUpgradeableLockReleaseTokenPool.sol @@ -1,40 +1,117 @@ // SPDX-License-Identifier: MIT - pragma solidity ^0.8.0; -import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IRateLimiter} from './IRateLimiter.sol'; interface IUpgradeableLockReleaseTokenPool { + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error AllowListNotEnabled(); + error BadARMSignal(); error BridgeLimitExceeded(uint256 bridgeLimit); + error BucketOverfilled(); + error CallerIsNotARampOnRouter(address caller); + error ChainAlreadyExists(uint64 chainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error DisabledNonZeroRateLimit(IRateLimiter.Config config); + error InsufficientLiquidity(); + error InvalidRatelimitRate(IRateLimiter.Config rateLimiterConfig); + error LiquidityNotAccepted(); + error NonExistentChain(uint64 remoteChainSelector); + error NotEnoughBridgedAmount(); + error RateLimitMustBeDisabled(); + error SenderNotAllowed(address sender); + error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); + error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); + error Unauthorized(address caller); + error ZeroAddressNotAllowed(); - /// @dev Initializer - /// @dev The address passed as `owner` must accept ownership after initialization. - /// @dev The `allowlist` is only effective if pool is set to access-controlled mode - /// @param owner The address of the owner - /// @param allowlist A set of addresses allowed to trigger lockOrBurn as original senders - /// @param router The address of the router - function initialize(address owner, address[] memory allowlist, address router) external; + event AllowListAdd(address sender); + event AllowListRemove(address sender); + event BridgeLimitAdminUpdated(address indexed oldAdmin, address indexed newAdmin); + event BridgeLimitUpdated(uint256 oldBridgeLimit, uint256 newBridgeLimit); + event Burned(address indexed sender, uint256 amount); + event ChainAdded( + uint64 remoteChainSelector, + IRateLimiter.Config outboundRateLimiterConfig, + IRateLimiter.Config inboundRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + IRateLimiter.Config outboundRateLimiterConfig, + IRateLimiter.Config inboundRateLimiterConfig + ); + event ChainRemoved(uint64 remoteChainSelector); + event ConfigChanged(IRateLimiter.Config config); + event Initialized(uint8 version); + event LiquidityAdded(address indexed provider, uint256 indexed amount); + event LiquidityRemoved(address indexed provider, uint256 indexed amount); + event Locked(address indexed sender, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event RouterUpdated(address oldRouter, address newRouter); + event TokensConsumed(uint256 tokens); - /// @dev Ownable + function acceptOwnership() external; + function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; + function canAcceptLiquidity() external view returns (bool); + function getAllowList() external view returns (address[] memory); + function getAllowListEnabled() external view returns (bool); + function getArmProxy() external view returns (address armProxy); + function getBridgeLimit() external view returns (uint256); + function getBridgeLimitAdmin() external view returns (address); + function getCurrentBridgedAmount() external view returns (uint256); + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getLockReleaseInterfaceId() external pure returns (bytes4); + function getProxyPool() external view returns (address proxyPool); + function getRateLimitAdmin() external view returns (address); + function getRebalancer() external view returns (address); + function getRouter() external view returns (address router); + function getSupportedChains() external view returns (uint64[] memory); + function getToken() external view returns (address token); + function initialize( + address owner, + address[] memory allowlist, + address router, + uint256 bridgeLimit + ) external; + function isSupportedChain(uint64 remoteChainSelector) external view returns (bool); + function lockOrBurn( + address originalSender, + bytes memory, + uint256 amount, + uint64 remoteChainSelector, + bytes memory + ) external returns (bytes memory); function owner() external view returns (address); - - /// @notice Sets the bridge limit - /// @param limit The new limit - function setBridgeLimit(uint256 limit) external; - - /// @notice Sets the bridge limit admin address. - /// @dev Only callable by the owner. - /// @param bridgeLimitAdmin The new bridge limit admin address. + function provideLiquidity(uint256 amount) external; + function releaseOrMint( + bytes memory, + address receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes memory + ) external; + function setBridgeLimit(uint256 newBridgeLimit) external; function setBridgeLimitAdmin(address bridgeLimitAdmin) external; - - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner. - /// @param rateLimitAdmin The new rate limiter admin address. + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + IRateLimiter.Config memory outboundConfig, + IRateLimiter.Config memory inboundConfig + ) external; + function setProxyPool(address proxyPool) external; function setRateLimitAdmin(address rateLimitAdmin) external; - - /// @notice Gets the bridge limiter admin address. - function getBridgeLimitAdmin() external view returns (address); - - /// @notice Gets the rate limiter admin address. - function getRateLimitAdmin() external view returns (address); + function setRebalancer(address rebalancer) external; + function setRouter(address newRouter) external; + function supportsInterface(bytes4 interfaceId) external pure returns (bool); + function transferOwnership(address to) external; + function typeAndVersion() external view returns (string memory); + function withdrawLiquidity(uint256 amount) external; } From fcf898f4140c5f87ccd1f62d7babee9c05f32f36 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:00:35 +0700 Subject: [PATCH 39/57] tmp: fix ci for aave org, to rm for bdg --- .github/workflows/test.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f186f228..977839ab4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,19 @@ jobs: test-sol: uses: bgd-labs/github-workflows/.github/workflows/foundry-test.yml@main - secrets: inherit + secrets: + RPC_MAINNET: "https://eth-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_ARBITRUM: "https://arb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_POLYGON: "https://polygon-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_AVALANCHE: "https://avax-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_OPTIMISM: "https://opt-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_METIS: "https://metis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_BASE: "https://base-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_GNOSIS: "https://gnosis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_BNB: "https://bnb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_ZKEVM: "https://polygonzkevm-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_SCROLL: "https://scroll-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + RPC_ZKSYNC: "https://zksync-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" with: mode: "CHANGED" From fe6ca4b08abd4b4fabcadaf98ae48098b29db6a6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:18:10 +0700 Subject: [PATCH 40/57] fix: ci to bdg setup --- .github/workflows/test.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 977839ab4..0f186f228 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,19 +30,7 @@ jobs: test-sol: uses: bgd-labs/github-workflows/.github/workflows/foundry-test.yml@main - secrets: - RPC_MAINNET: "https://eth-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_ARBITRUM: "https://arb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_POLYGON: "https://polygon-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_AVALANCHE: "https://avax-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_OPTIMISM: "https://opt-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_METIS: "https://metis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_BASE: "https://base-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_GNOSIS: "https://gnosis-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_BNB: "https://bnb-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_ZKEVM: "https://polygonzkevm-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_SCROLL: "https://scroll-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" - RPC_ZKSYNC: "https://zksync-mainnet.g.alchemy.com/v2/${{ secrets.ALCHEMY_KEY }}" + secrets: inherit with: mode: "CHANGED" From 635ce493a3eb85d2beeda6258bc832cc61160964 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:38:33 +0700 Subject: [PATCH 41/57] fix: update rate limit --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 10 +++++----- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 07ba0f820..5e1043ad0 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -44,19 +44,19 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// @notice Returns the rate limiter configuration for the outbound rate limiter /// The onRamp rate limit for ARB => ETH will be as follows: - /// Capacity: 350_000 GHO - /// Rate: 100 GHO per second (=> 360_000 GHO per hour) + /// Capacity: 300_000 GHO + /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); } /// @notice Returns the rate limiter configuration for the inbound rate limiter /// The offRamp rate limit for ETH => ARB will be as follows: /// Capacity: 350_000 GHO - /// Rate: 100 GHO per second (=> 360_000 GHO per hour) + /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 803f4416b..c0c9a2fea 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -44,19 +44,19 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// @notice Returns the rate limiter configuration for the outbound rate limiter /// The onRamp rate limit for ETH => ARB will be as follows: - /// Capacity: 350_000 GHO - /// Rate: 100 GHO per second (=> 360_000 GHO per hour) + /// Capacity: 300_000 GHO + /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); } /// @notice Returns the rate limiter configuration for the inbound rate limiter /// The offRamp rate limit for ARB=>ETH will be as follows: /// Capacity: 350_000 GHO - /// Rate: 100 GHO per second (=> 360_000 GHO per hour) + /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 350_000e18, rate: 100e18}); + return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); } } From 520a6bfdd0808f67151840f3d3de2f19d1c20846 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:38:46 +0700 Subject: [PATCH 42/57] test: fuzz amounts --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 20 +++++++++---------- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 20 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 2b67908e2..777d9813c 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -141,11 +141,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); } - function test_sendMessagePreCCIPMigration() public { + function test_sendMessagePreCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 150_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -171,13 +171,13 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore - amount); } - function test_sendMessagePostCCIPMigration() public { + function test_sendMessagePostCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); _mockCCIPMigration(); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -205,10 +205,10 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore - amount); } - function test_executeMessagePreCCIPMigration() public { + function test_executeMessagePreCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -223,12 +223,12 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } - function test_executeMessagePostCCIPMigration() public { + function test_executeMessagePostCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); _mockCCIPMigration(); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -243,12 +243,12 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } - function test_executeMessagePostCCIPMigrationViaLegacyOffRamp() public { + function test_executeMessagePostCCIPMigrationViaLegacyOffRamp(uint256 amount) public { executePayload(vm, address(proposal)); _mockCCIPMigration(); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 68fcf47ed..4f14bebf1 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -126,12 +126,12 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_readInitialized(_getImplementation(address(ghoTokenPool))), 255); } - function test_sendMessagePreCCIPMigration() public { + function test_sendMessagePreCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 150_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getOutboundRefillTime(amount)); @@ -159,14 +159,14 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); } - function test_sendMessagePostCCIPMigration() public { + function test_sendMessagePostCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); _mockCCIPMigration(); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getOutboundRefillTime(amount)); @@ -196,11 +196,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); } - function test_executeMessagePreCCIPMigration() public { + function test_executeMessagePreCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getInboundRefillTime(amount)); @@ -215,13 +215,13 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(gho.balanceOf(alice), amount); } - function test_executeMessagePostCCIPMigration() public { + function test_executeMessagePostCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); _mockCCIPMigration(); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getInboundRefillTime(amount)); // mock previously locked gho @@ -235,13 +235,13 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(gho.balanceOf(alice), amount); } - function test_executeMessagePostCCIPMigrationViaLegacyOffRamp() public { + function test_executeMessagePostCCIPMigrationViaLegacyOffRamp(uint256 amount) public { executePayload(vm, address(proposal)); _mockCCIPMigration(); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - uint256 amount = 350_000e18; + amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getInboundRefillTime(amount)); From efc2c1e4efba1a626e2158cbe9f068b0cc6678a1 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:39:05 +0700 Subject: [PATCH 43/57] chore: snapshot docs --- src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md | 2 +- src/20241021_Multi_GHOCCIP150Upgrade/config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md index de8f4b8b5..1b3e59844 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -14,7 +14,7 @@ discussions: "https://governance.aave.com/t/bgd-technical-maintenance-proposals/ - Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol) - Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol) -- [Snapshot](TODO) +- Snapshot - Direct-to-AIP - [Discussion](https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51) ## Copyright diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts index 9b2cd00f6..eb88f8031 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts +++ b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts @@ -7,7 +7,7 @@ export const config: ConfigFile = { date: '20241021', author: 'Aave Labs', discussion: 'https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51', - snapshot: '', + snapshot: 'Direct-to-AIP', votingNetwork: 'POLYGON', }, poolOptions: { From 18da0108c89e4fd932bb52581d78706014c35b30 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:05:46 +0700 Subject: [PATCH 44/57] chore: const cap rate --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 9 ++++++--- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 5e1043ad0..d895e41d7 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -21,6 +21,9 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; + uint256 internal constant CAPACITY = 300e18; + uint256 internal constant RATE = 60e18; + function execute() external { IUpgradeableBurnMintTokenPool tokenPoolProxy = IUpgradeableBurnMintTokenPool( MiscArbitrum.GHO_CCIP_TOKEN_POOL @@ -48,15 +51,15 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); + return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); } /// @notice Returns the rate limiter configuration for the inbound rate limiter /// The offRamp rate limit for ETH => ARB will be as follows: - /// Capacity: 350_000 GHO + /// Capacity: 300_000 GHO /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); + return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index c0c9a2fea..5adb3ed10 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -21,6 +21,9 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; + uint256 internal constant CAPACITY = 300e18; + uint256 internal constant RATE = 60e18; + function execute() external { IUpgradeableLockReleaseTokenPool tokenPoolProxy = IUpgradeableLockReleaseTokenPool( MiscEthereum.GHO_CCIP_TOKEN_POOL @@ -48,15 +51,15 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); + return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); } /// @notice Returns the rate limiter configuration for the inbound rate limiter /// The offRamp rate limit for ARB=>ETH will be as follows: - /// Capacity: 350_000 GHO + /// Capacity: 300_000 GHO /// Rate: 60 GHO per second (=> 216_000 GHO per hour) /// @return The rate limiter configuration function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: 300_000e18, rate: 60e18}); + return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); } } From de7fb1b71e89bc674fb9f94dfcb7a204def1bf94 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:08:00 +0700 Subject: [PATCH 45/57] chore: fix type --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index d895e41d7..d0b978402 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -21,8 +21,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; - uint256 internal constant CAPACITY = 300e18; - uint256 internal constant RATE = 60e18; + uint128 internal constant CAPACITY = 300e18; + uint128 internal constant RATE = 60e18; function execute() external { IUpgradeableBurnMintTokenPool tokenPoolProxy = IUpgradeableBurnMintTokenPool( diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 5adb3ed10..5b9db2f4c 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -21,8 +21,8 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; - uint256 internal constant CAPACITY = 300e18; - uint256 internal constant RATE = 60e18; + uint128 internal constant CAPACITY = 300e18; + uint128 internal constant RATE = 60e18; function execute() external { IUpgradeableLockReleaseTokenPool tokenPoolProxy = IUpgradeableLockReleaseTokenPool( From ce16b8985989160b9a1ff69996be70e0ce37754a Mon Sep 17 00:00:00 2001 From: miguelmtzinf Date: Wed, 6 Nov 2024 13:49:56 +0100 Subject: [PATCH 46/57] fix: Fix rate limit config constants --- ...eV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 36 +++++---------- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 27 ++++++++---- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 44 ++++++++++++------- ...eV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 36 +++++---------- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 27 ++++++++---- 5 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index d0b978402..c161bb90d 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -21,8 +21,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; - uint128 internal constant CAPACITY = 300e18; - uint128 internal constant RATE = 60e18; + /// @dev Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300e18; + + /// @dev Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; function execute() external { IUpgradeableBurnMintTokenPool tokenPoolProxy = IUpgradeableBurnMintTokenPool( @@ -38,28 +41,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { tokenPoolProxy.setProxyPool(GHO_CCIP_PROXY_POOL); // Set rate limit - tokenPoolProxy.setChainRateLimiterConfig( - ETH_CHAIN_SELECTOR, - getOutBoundRateLimiterConfig(), - getInBoundRateLimiterConfig() - ); - } - - /// @notice Returns the rate limiter configuration for the outbound rate limiter - /// The onRamp rate limit for ARB => ETH will be as follows: - /// Capacity: 300_000 GHO - /// Rate: 60 GHO per second (=> 216_000 GHO per hour) - /// @return The rate limiter configuration - function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); - } - - /// @notice Returns the rate limiter configuration for the inbound rate limiter - /// The offRamp rate limit for ETH => ARB will be as follows: - /// Capacity: 300_000 GHO - /// Rate: 60 GHO per second (=> 216_000 GHO per hour) - /// @return The rate limiter configuration - function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); + IRateLimiter.Config memory rateLimitConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE + }); + tokenPoolProxy.setChainRateLimiterConfig(ETH_CHAIN_SELECTOR, rateLimitConfig, rateLimitConfig); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 777d9813c..23a6e39e2 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -96,11 +96,11 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq( ghoTokenPool.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), - proposal.getInBoundRateLimiterConfig() + _getRateLimiterConfig() ); assertEq( ghoTokenPool.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), - proposal.getOutBoundRateLimiterConfig() + _getRateLimiterConfig() ); } @@ -145,7 +145,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); IRouter router = IRouter(ghoTokenPool.getRouter()); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -177,7 +177,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); IRouter router = IRouter(ghoTokenPool.getRouter()); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -208,7 +208,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function test_executeMessagePreCCIPMigration(uint256 amount) public { executePayload(vm, address(proposal)); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -228,7 +228,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -248,7 +248,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); uint256 facilitatorLevelBefore = _getFacilitatorLevel(address(ghoTokenPool)); // wait for the rate limiter to refill @@ -460,13 +460,13 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { - uint128 rate = proposal.getOutBoundRateLimiterConfig().rate; + uint128 rate = _getRateLimiterConfig().rate; assertNotEq(rate, 0); return amount / uint256(rate) + 1; // account for rounding } function _getInboundRefillTime(uint256 amount) private view returns (uint256) { - uint128 rate = proposal.getInBoundRateLimiterConfig().rate; + uint128 rate = _getRateLimiterConfig().rate; assertNotEq(rate, 0); return amount / uint256(rate) + 1; // account for rounding } @@ -492,4 +492,13 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ) internal pure { assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } + + function _getRateLimiterConfig() internal view returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: true, + capacity: proposal.CCIP_RATE_LIMIT_CAPACITY(), + rate: proposal.CCIP_RATE_LIMIT_REFILL_RATE() + }); + } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 4436953b5..8d754812f 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -52,12 +52,14 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { struct L1 { AaveV3Ethereum_GHOCCIP150Upgrade_20241021 proposal; IUpgradeableLockReleaseTokenPool tokenPool; + IRateLimiter.Config rateLimitConfig; Common c; } struct L2 { AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 proposal; IUpgradeableBurnMintTokenPool tokenPool; + IRateLimiter.Config rateLimitConfig; Common c; } @@ -82,6 +84,11 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { l1.proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); l1.c.proxyPool = IProxyPool(l1.proposal.GHO_CCIP_PROXY_POOL()); l1.tokenPool = IUpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); + l1.rateLimitConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: l1.proposal.CCIP_RATE_LIMIT_CAPACITY(), + rate: l1.proposal.CCIP_RATE_LIMIT_REFILL_RATE() + }); l1.c.router = IRouter(l1.tokenPool.getRouter()); l2.c.chainSelector = l1.tokenPool.getSupportedChains()[0]; l1.c.token = IERC20(address(l1.tokenPool.getToken())); @@ -95,6 +102,11 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { l2.proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); l2.c.proxyPool = IProxyPool(l2.proposal.GHO_CCIP_PROXY_POOL()); l2.tokenPool = IUpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + l2.rateLimitConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: l2.proposal.CCIP_RATE_LIMIT_CAPACITY(), + rate: l2.proposal.CCIP_RATE_LIMIT_REFILL_RATE() + }); l2.c.router = IRouter(l2.tokenPool.getRouter()); l1.c.chainSelector = l2.tokenPool.getSupportedChains()[0]; l2.c.token = IERC20(address(l2.tokenPool.getToken())); @@ -299,7 +311,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 outBoundRate = l1.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(outBoundRate) + 1); // rate is non zero @@ -336,7 +348,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is uint256 aliceBalanceBefore = l2.c.token.balanceOf(alice); - uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -357,7 +369,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 outBoundRate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(outBoundRate) + 1); // rate is non zero @@ -390,7 +402,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is uint256 tokenPoolBalanceBefore = l1.c.token.balanceOf(address(l1.tokenPool)); - uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -435,7 +447,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 outBoundRate = l1.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(outBoundRate) + 1); // rate is non zero @@ -475,7 +487,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is // ARB executeMessage vm.selectFork(l2.c.forkId); - uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -506,7 +518,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 outBoundRate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(outBoundRate) + 1); // rate is non zero @@ -542,7 +554,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is uint256 tokenPoolBalanceBefore = l1.c.token.balanceOf(address(l1.tokenPool)); - uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -567,7 +579,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is deal(address(l1.c.token), alice, amount, true); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + uint128 rate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(rate) + 1); // rate is non zero @@ -601,7 +613,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 rate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 rate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(rate) + 1); // rate is non zero @@ -638,7 +650,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -677,7 +689,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -735,7 +747,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is deal(address(l1.c.token), alice, amount, true); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); - uint128 rate = l1.proposal.getOutBoundRateLimiterConfig().rate; + uint128 rate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(rate) + 1); // rate is non zero @@ -769,7 +781,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is vm.selectFork(l2.c.forkId); - uint128 inBoundRate = l2.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero @@ -801,7 +813,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); - uint128 outBoundRate = l2.proposal.getOutBoundRateLimiterConfig().rate; + uint128 outBoundRate = l2.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(outBoundRate) + 1); // rate is non zero @@ -835,7 +847,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is vm.selectFork(l1.c.forkId); - uint128 inBoundRate = l1.proposal.getInBoundRateLimiterConfig().rate; + uint128 inBoundRate = l1.rateLimitConfig.rate; // wait for the rate limiter to refill skip(amount / uint256(inBoundRate) + 1); // rate is non zero diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 5b9db2f4c..4f1811bcb 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -21,8 +21,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; - uint128 internal constant CAPACITY = 300e18; - uint128 internal constant RATE = 60e18; + /// @dev Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300e18; + + /// @dev Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; function execute() external { IUpgradeableLockReleaseTokenPool tokenPoolProxy = IUpgradeableLockReleaseTokenPool( @@ -38,28 +41,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { tokenPoolProxy.setProxyPool(GHO_CCIP_PROXY_POOL); // Set rate limit - tokenPoolProxy.setChainRateLimiterConfig( - ARB_CHAIN_SELECTOR, - getOutBoundRateLimiterConfig(), - getInBoundRateLimiterConfig() - ); - } - - /// @notice Returns the rate limiter configuration for the outbound rate limiter - /// The onRamp rate limit for ETH => ARB will be as follows: - /// Capacity: 300_000 GHO - /// Rate: 60 GHO per second (=> 216_000 GHO per hour) - /// @return The rate limiter configuration - function getOutBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); - } - - /// @notice Returns the rate limiter configuration for the inbound rate limiter - /// The offRamp rate limit for ARB=>ETH will be as follows: - /// Capacity: 300_000 GHO - /// Rate: 60 GHO per second (=> 216_000 GHO per hour) - /// @return The rate limiter configuration - function getInBoundRateLimiterConfig() public pure returns (IRateLimiter.Config memory) { - return IRateLimiter.Config({isEnabled: true, capacity: CAPACITY, rate: RATE}); + IRateLimiter.Config memory rateLimitConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE + }); + tokenPoolProxy.setChainRateLimiterConfig(ARB_CHAIN_SELECTOR, rateLimitConfig, rateLimitConfig); } } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 4f14bebf1..6e1d75a17 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -92,11 +92,11 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq( ghoTokenPool.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), - proposal.getInBoundRateLimiterConfig() + _getRateLimiterConfig() ); assertEq( ghoTokenPool.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), - proposal.getOutBoundRateLimiterConfig() + _getRateLimiterConfig() ); } @@ -131,7 +131,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getOutboundRefillTime(amount)); @@ -166,7 +166,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { IERC20 gho = IERC20(address(ghoTokenPool.getToken())); IRouter router = IRouter(ghoTokenPool.getRouter()); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getOutboundRefillTime(amount)); @@ -200,7 +200,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { executePayload(vm, address(proposal)); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getInboundRefillTime(amount)); @@ -221,7 +221,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getInboundRefillTime(amount)); // mock previously locked gho @@ -241,7 +241,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { _mockCCIPMigration(); IERC20 gho = IERC20(address(ghoTokenPool.getToken())); - amount = bound(amount, 1, proposal.getOutBoundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getRateLimiterConfig().capacity); // wait for the rate limiter to refill skip(_getInboundRefillTime(amount)); @@ -458,13 +458,13 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { } function _getOutboundRefillTime(uint256 amount) private view returns (uint256) { - uint128 rate = proposal.getOutBoundRateLimiterConfig().rate; + uint128 rate = _getRateLimiterConfig().rate; assertNotEq(rate, 0); return amount / uint256(rate) + 1; // account for rounding } function _getInboundRefillTime(uint256 amount) private view returns (uint256) { - uint128 rate = proposal.getInBoundRateLimiterConfig().rate; + uint128 rate = _getRateLimiterConfig().rate; assertNotEq(rate, 0); return amount / uint256(rate) + 1; // account for rounding } @@ -490,4 +490,13 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { ) internal pure { assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } + + function _getRateLimiterConfig() internal view returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: true, + capacity: proposal.CCIP_RATE_LIMIT_CAPACITY(), + rate: proposal.CCIP_RATE_LIMIT_REFILL_RATE() + }); + } } From 896a03257ee7abbbe6cb81a957b09055d74e366f Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:07:21 +0700 Subject: [PATCH 47/57] fix: tests, impl correct solc --- ...eV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 4 ++-- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 10 +++++----- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 20 +++++++++---------- ...eV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 4 ++-- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 2 +- .../config.ts | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index c161bb90d..88e904e51 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -16,8 +16,8 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; - // https://arbiscan.io/address/0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1 - address public constant TOKEN_POOL_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + // https://arbiscan.io/address/0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73 + address public constant TOKEN_POOL_IMPL = 0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73; // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 23a6e39e2..4830f9c48 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -61,7 +61,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { error NotACompatiblePool(address pool); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 271012501); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 271638492); proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); ghoTokenPool = IUpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); @@ -263,8 +263,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore + amount); } - function test_proxyPoolCanOnRamp() public { - uint256 amount = 1337e18; + function test_proxyPoolCanOnRamp(uint256 amount) public { + amount = bound(amount, 1, _getRateLimiterConfig().capacity); vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); vm.prank(address(proxyPool)); @@ -287,8 +287,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(_getFacilitatorLevel(address(ghoTokenPool)), facilitatorLevelBefore - amount); } - function test_proxyPoolCanOffRamp() public { - uint256 amount = 1337e18; + function test_proxyPoolCanOffRamp(uint256 amount) public { + amount = bound(amount, 1, _getRateLimiterConfig().capacity); vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); vm.prank(address(proxyPool)); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 8d754812f..94b692892 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -77,8 +77,8 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { error NotACompatiblePool(address pool); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21115706); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 271012501); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21128760); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 271638492); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); @@ -303,7 +303,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PreCCIPMigration is } function test_E2E() public { - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; // ETH (=> ARB) sendMessage { vm.selectFork(l1.c.forkId); @@ -439,7 +439,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is } function test_E2E() public { - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; // ETH (=> ARB) sendMessage { vm.selectFork(l1.c.forkId); @@ -575,7 +575,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is function test_SendRevertsWithoutUpgrade() public { { vm.selectFork(l1.c.forkId); - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; deal(address(l1.c.token), alice, amount, true); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); @@ -609,7 +609,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is { vm.selectFork(l2.c.forkId); - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); @@ -645,7 +645,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is function test_ExecuteRevertsWithoutUpgrade() public { { vm.selectFork(l1.c.forkId); - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; deal(address(l1.c.token), alice, amount, true); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); @@ -684,7 +684,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_PostCCIPMigration is { vm.selectFork(l2.c.forkId); - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); @@ -743,7 +743,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is // ETH => ARB, ccipSend 1.4; CCIP migration, Destination executeMessage { vm.selectFork(l1.c.forkId); - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; deal(address(l1.c.token), alice, amount, true); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); @@ -809,7 +809,7 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_InFlightCCIPMigration is // ARB => ETH, ccipSend 1.4; CCIP migration, Destination executeMessage { vm.selectFork(l2.c.forkId); - uint256 amount = 500e18; + uint256 amount = l1.rateLimitConfig.capacity; deal(address(l2.c.token), alice, amount, true); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 4f1811bcb..219811e98 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -16,8 +16,8 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { uint64 public constant ARB_CHAIN_SELECTOR = 4949039107694359620; - // https://etherscan.io/address/0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1 - address public constant TOKEN_POOL_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + // https://etherscan.io/address/0xb77E872A68C62CfC0dFb02C067Ecc3DA23B4bbf3 + address public constant TOKEN_POOL_IMPL = 0xb77E872A68C62CfC0dFb02C067Ecc3DA23B4bbf3; // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 6e1d75a17..1542fbe06 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -57,7 +57,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21115706); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21128760); proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); ghoTokenPool = IUpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts index eb88f8031..ae3e224b0 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts +++ b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21115706}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 271012501}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21128760}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 271638492}}, }, }; From 7aa813e4fbec9a035ca16c05162de31039a13872 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:11:59 +0700 Subject: [PATCH 48/57] fix: tests --- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 1542fbe06..2f142a726 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -256,8 +256,8 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(gho.balanceOf(alice), amount); } - function test_proxyPoolCanOnRamp() public { - uint256 amount = 1337e18; + function test_proxyPoolCanOnRamp(uint256 amount) public { + amount = bound(amount, 1, _getRateLimiterConfig().capacity); uint256 bridgedAmount = ghoTokenPool.getCurrentBridgedAmount(); @@ -278,8 +278,8 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ghoTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); } - function test_proxyPoolCanOffRamp() public { - uint256 amount = 1337e18; + function test_proxyPoolCanOffRamp(uint256 amount) public { + amount = bound(amount, 1, _getRateLimiterConfig().capacity); vm.expectRevert(abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, proxyPool)); vm.prank(address(proxyPool)); From 403ed4015731e071e4b8fa2614adca8a6d99b3ab Mon Sep 17 00:00:00 2001 From: Dhairya Sethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:03:32 +0700 Subject: [PATCH 49/57] Update src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol Co-authored-by: Harsh Pandey --- .../AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol index 219811e98..7d6a405fe 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol @@ -22,7 +22,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { address public constant GHO_CCIP_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; /// @dev Token Rate Limit Capacity: 300_000 GHO - uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300e18; + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; /// @dev Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; From 300427197794ecea94c32599582a5117a1848b83 Mon Sep 17 00:00:00 2001 From: Dhairya Sethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:05:04 +0700 Subject: [PATCH 50/57] Update src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol Co-authored-by: Harsh Pandey --- .../AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol index 88e904e51..7daeb4d52 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol @@ -22,7 +22,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021 is IProposalGenericExecutor { address public constant GHO_CCIP_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; /// @dev Token Rate Limit Capacity: 300_000 GHO - uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300e18; + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; /// @dev Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; From 445d0f7db3b54d71d922bd3e7897fb8193fd4fda Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:08:27 +0700 Subject: [PATCH 51/57] doc: reference token pool contracts --- src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md index 1b3e59844..734d576b6 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -16,6 +16,7 @@ discussions: "https://governance.aave.com/t/bgd-technical-maintenance-proposals/ - Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol) - Snapshot - Direct-to-AIP - [Discussion](https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51) +- Token Pool Contracts - [UpgradeableLockReleaseTokenPool](https://github.com/aave/ccip/blob/bc0561e6a9615f410086d4766839eaf3ca9b9f49/contracts/src/v0.8/ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol), [UpgradeableBurnMintTokenPool](https://github.com/aave/ccip/blob/bc0561e6a9615f410086d4766839eaf3ca9b9f49/contracts/src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol) ## Copyright From 4abc58433ff0a05fb648670301e336b1221b5a0b Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:15:50 +0700 Subject: [PATCH 52/57] doc: upgrade spec --- .../GHOCCIP150Upgrade.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md index 734d576b6..cdbb79d64 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -6,10 +6,21 @@ discussions: "https://governance.aave.com/t/bgd-technical-maintenance-proposals/ ## Simple Summary +Proposal to update GHO CCIP Token Pools to ensure GHO’s CCIP integration remains functional during and after the upcoming migration to CCIP version 1.5. + ## Motivation +The Chainlink Cross-Chain Interoperability Protocol (CCIP) is upgrading to version 1.5 in Q4 2024, introducing several new features and enhancements. We are expecting that a detailed description of this new version will be announced by Chainlink soon. +Currently, GHO CCIP Token Pools are based on version 1.4, and they are not compatible in their current form with CCIP 1.5. The Chainlink CCIP team cannot migrate the GHO CCIP Token Pools as part of the system-wide upgrade, as these are fully controlled by the Aave DAO. +Aave Labs will provide technical support to ensure that GHO CCIP Token Pools remain functional, secure, and aligned with the latest updates, enabling GHO to expand to other networks if needed. + ## Specification +Below actions are taken in order to make GHO token pools work with the new CCIP 1.5 protocol by allowing the "Intermediary Contract" (proxyPool) to translate the interface between 1.4 & 1.5 OnRamps and OffRamps: +Configure an Intermediary Contract: This contract translates execution calls between the new OnRamp and the existing GHO Token Pools. It was developed and deployed by the Chainlink CCIP team on behalf of the Aave DAO. +Upgrade the Existing GHO Token Pools: The existing Token Pools are adjusted to allow calls from both the old and new versions of the OnRamp and OffRamp, through the intermediary contract. +Setup a Token Rate Limit: A token rate limit of 300.000 GHO as limit capacity and 60 GHO per second as refill rate is set for both directions of Ethereum <> Arbitrum lane. This is a temporary security measure that can be lifted later via AIP or by GHO Stewards. + ## References - Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol) From b794f79a324300ad134bb7f10caf5893956ec102 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:17:51 +0700 Subject: [PATCH 53/57] doc: formatting --- src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md index cdbb79d64..85fa1427b 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -17,9 +17,10 @@ Aave Labs will provide technical support to ensure that GHO CCIP Token Pools rem ## Specification Below actions are taken in order to make GHO token pools work with the new CCIP 1.5 protocol by allowing the "Intermediary Contract" (proxyPool) to translate the interface between 1.4 & 1.5 OnRamps and OffRamps: -Configure an Intermediary Contract: This contract translates execution calls between the new OnRamp and the existing GHO Token Pools. It was developed and deployed by the Chainlink CCIP team on behalf of the Aave DAO. -Upgrade the Existing GHO Token Pools: The existing Token Pools are adjusted to allow calls from both the old and new versions of the OnRamp and OffRamp, through the intermediary contract. -Setup a Token Rate Limit: A token rate limit of 300.000 GHO as limit capacity and 60 GHO per second as refill rate is set for both directions of Ethereum <> Arbitrum lane. This is a temporary security measure that can be lifted later via AIP or by GHO Stewards. + +- Configure an Intermediary Contract: This contract translates execution calls between the new OnRamp and the existing GHO Token Pools. It was developed and deployed by the Chainlink CCIP team on behalf of the Aave DAO. +- Upgrade the Existing GHO Token Pools: The existing Token Pools are adjusted to allow calls from both the old and new versions of the OnRamp and OffRamp, through the intermediary contract. +- Setup a Token Rate Limit: A token rate limit of 300.000 GHO as limit capacity and 60 GHO per second as refill rate is set for both directions of Ethereum <> Arbitrum lane. This is a temporary security measure that can be lifted later via AIP or by GHO Stewards. ## References From 9b08d27de72307f9c698852964fff86dc9db0a2f Mon Sep 17 00:00:00 2001 From: Dhairya Sethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 7 Nov 2024 00:06:21 +0700 Subject: [PATCH 54/57] Update src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md Co-authored-by: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> --- src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md index 85fa1427b..a95083d23 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -20,7 +20,7 @@ Below actions are taken in order to make GHO token pools work with the new CCIP - Configure an Intermediary Contract: This contract translates execution calls between the new OnRamp and the existing GHO Token Pools. It was developed and deployed by the Chainlink CCIP team on behalf of the Aave DAO. - Upgrade the Existing GHO Token Pools: The existing Token Pools are adjusted to allow calls from both the old and new versions of the OnRamp and OffRamp, through the intermediary contract. -- Setup a Token Rate Limit: A token rate limit of 300.000 GHO as limit capacity and 60 GHO per second as refill rate is set for both directions of Ethereum <> Arbitrum lane. This is a temporary security measure that can be lifted later via AIP or by GHO Stewards. +- Setup a Token Rate Limit: A token rate limit of 300,000 GHO as limit capacity and 60 GHO per second as refill rate is set for both directions of Ethereum <> Arbitrum lane. This is a temporary security measure that can be lifted later via AIP or by GHO Stewards. ## References From 15fcc5fb94bc5ae0fb1723721d12c00584547e32 Mon Sep 17 00:00:00 2001 From: Dhairya Sethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 7 Nov 2024 00:06:35 +0700 Subject: [PATCH 55/57] Update src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md Co-authored-by: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> --- src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md index a95083d23..ea56acb50 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade.md @@ -1,5 +1,5 @@ --- -title: "GHO CCIP 1.50 Upgrade" +title: "GHO CCIP Integration Maintenance (CCIP v1.5 upgrade)" author: "Aave Labs" discussions: "https://governance.aave.com/t/bgd-technical-maintenance-proposals/15274/51" --- From fd82f22f37b6b9cd15099df1ad33e11d9e6eba31 Mon Sep 17 00:00:00 2001 From: miguelmtzinf Date: Thu, 7 Nov 2024 10:48:37 +0100 Subject: [PATCH 56/57] test: Refresh block number with ghostewards aip executed --- ...3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol | 19 +++-------- ...AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol | 4 +-- ...3Ethereum_GHOCCIP150Upgrade_20241021.t.sol | 13 ++++---- .../GHOCCIP150Upgrade_20241021.s.sol | 33 +++++++++++++++++++ .../config.ts | 4 +-- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol index 4830f9c48..79e12a8d7 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.t.sol @@ -61,7 +61,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { error NotACompatiblePool(address pool); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 271638492); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 271788784); proposal = new AaveV3Arbitrum_GHOCCIP150Upgrade_20241021(); ghoTokenPool = IUpgradeableBurnMintTokenPool(MiscArbitrum.GHO_CCIP_TOKEN_POOL); proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); @@ -114,17 +114,6 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { assertEq(ghoTokenPool.getProxyPool(), address(proxyPool)); } - function test_getRateLimitAdmin() public { - // rateLimitAdmin getter does not exist before the upgrade on BurnMintTokenPool - vm.expectRevert(); - ghoTokenPool.getRateLimitAdmin(); - - executePayload(vm, address(proposal)); - - // we currently do not set the rate limit admin - assertEq(ghoTokenPool.getRateLimitAdmin(), address(0)); - } - function test_tokenPoolCannotBeInitializedAgain() public { vm.expectRevert('Initializable: contract is already initialized'); ghoTokenPool.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); @@ -312,8 +301,7 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function test_stewardCanDisableRateLimit() public { executePayload(vm, address(proposal)); - vm.prank(ghoTokenPool.owner()); - ghoTokenPool.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); + assertEq(ghoTokenPool.getRateLimitAdmin(), address(GHO_CCIP_STEWARD)); vm.prank(GHO_CCIP_STEWARD.RISK_COUNCIL()); GHO_CCIP_STEWARD.updateRateLimit(ETH_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); @@ -441,7 +429,8 @@ contract AaveV3Arbitrum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { abi.encode( ghoTokenPool.owner(), ghoTokenPool.getSupportedChains(), - ghoTokenPool.getAllowListEnabled() + ghoTokenPool.getAllowListEnabled(), + ghoTokenPool.getRateLimitAdmin() ); } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol index 94b692892..e64678526 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3E2E_GHOCCIP150Upgrade_20241021.t.sol @@ -77,8 +77,8 @@ contract AaveV3E2E_GHOCCIP150Upgrade_20241021_Base is ProtocolV3TestBase { error NotACompatiblePool(address pool); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21128760); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 271638492); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21131872); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 271788784); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol index 2f142a726..c9b0b63d8 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/AaveV3Ethereum_GHOCCIP150Upgrade_20241021.t.sol @@ -57,7 +57,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { error CallerIsNotARampOnRouter(address caller); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21128760); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21131872); proposal = new AaveV3Ethereum_GHOCCIP150Upgrade_20241021(); ghoTokenPool = IUpgradeableLockReleaseTokenPool(MiscEthereum.GHO_CCIP_TOKEN_POOL); proxyPool = IProxyPool(proposal.GHO_CCIP_PROXY_POOL()); @@ -300,8 +300,7 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { function test_stewardCanDisableRateLimit() public { executePayload(vm, address(proposal)); - vm.prank(ghoTokenPool.owner()); - ghoTokenPool.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); + assertEq(ghoTokenPool.getRateLimitAdmin(), address(GHO_CCIP_STEWARD)); vm.prank(GHO_CCIP_STEWARD.RISK_COUNCIL()); GHO_CCIP_STEWARD.updateRateLimit(ARB_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); @@ -432,14 +431,14 @@ contract AaveV3Ethereum_GHOCCIP150Upgrade_20241021_Test is ProtocolV3TestBase { return abi.encode( ghoTokenPool.owner(), - ghoTokenPool.getBridgeLimitAdmin(), + ghoTokenPool.getSupportedChains(), + ghoTokenPool.getAllowListEnabled(), ghoTokenPool.getRateLimitAdmin(), + ghoTokenPool.getBridgeLimitAdmin(), ghoTokenPool.getRebalancer(), - ghoTokenPool.getSupportedChains(), ghoTokenPool.getLockReleaseInterfaceId(), ghoTokenPool.getBridgeLimit(), - ghoTokenPool.getCurrentBridgedAmount(), - ghoTokenPool.getRateLimitAdmin() + ghoTokenPool.getCurrentBridgedAmount() ); } diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol index 728f912ec..3cd6cef6b 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol @@ -6,6 +6,10 @@ import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {EthereumScript, ArbitrumScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; +import {Script} from 'forge-std/Script.sol'; + +import {IUpgradeableBurnMintTokenPool} from 'src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; /** * @dev Deploy Ethereum @@ -85,3 +89,32 @@ contract CreateProposal is EthereumScript { ); } } + +contract EthConfigurator is Script { + function run() external { + vm.startBroadcast(); + // Set rate limit + IRateLimiter.Config memory rateLimitConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 10_000e18, + rate: 60e18 + }); + IUpgradeableBurnMintTokenPool(0x7768248E1Ff75612c18324bad06bb393c1206980) + .setChainRateLimiterConfig(3478487238524512106, rateLimitConfig, rateLimitConfig); + vm.stopBroadcast(); + } +} +contract ArbConfigurator is Script { + function run() external { + vm.startBroadcast(); + // Set rate limit + IRateLimiter.Config memory rateLimitConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 10_000e18, + rate: 60e18 + }); + IUpgradeableBurnMintTokenPool(0x3eC2b6F818B72442fc36561e9F930DD2b60957D2) + .setChainRateLimiterConfig(16015286601757825753, rateLimitConfig, rateLimitConfig); + vm.stopBroadcast(); + } +} diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts index ae3e224b0..f1a49b82f 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/config.ts +++ b/src/20241021_Multi_GHOCCIP150Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21128760}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 271638492}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21131872}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 271788784}}, }, }; From 6dd88380a90dbb53c609805a42ce2bdaa8ffe12a Mon Sep 17 00:00:00 2001 From: miguelmtzinf Date: Thu, 7 Nov 2024 10:50:12 +0100 Subject: [PATCH 57/57] fix: Remove unneeded script --- .../GHOCCIP150Upgrade_20241021.s.sol | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol index 3cd6cef6b..728f912ec 100644 --- a/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol +++ b/src/20241021_Multi_GHOCCIP150Upgrade/GHOCCIP150Upgrade_20241021.s.sol @@ -6,10 +6,6 @@ import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {EthereumScript, ArbitrumScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol'; import {AaveV3Ethereum_GHOCCIP150Upgrade_20241021} from './AaveV3Ethereum_GHOCCIP150Upgrade_20241021.sol'; import {AaveV3Arbitrum_GHOCCIP150Upgrade_20241021} from './AaveV3Arbitrum_GHOCCIP150Upgrade_20241021.sol'; -import {Script} from 'forge-std/Script.sol'; - -import {IUpgradeableBurnMintTokenPool} from 'src/interfaces/ccip/IUpgradeableBurnMintTokenPool.sol'; -import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; /** * @dev Deploy Ethereum @@ -89,32 +85,3 @@ contract CreateProposal is EthereumScript { ); } } - -contract EthConfigurator is Script { - function run() external { - vm.startBroadcast(); - // Set rate limit - IRateLimiter.Config memory rateLimitConfig = IRateLimiter.Config({ - isEnabled: true, - capacity: 10_000e18, - rate: 60e18 - }); - IUpgradeableBurnMintTokenPool(0x7768248E1Ff75612c18324bad06bb393c1206980) - .setChainRateLimiterConfig(3478487238524512106, rateLimitConfig, rateLimitConfig); - vm.stopBroadcast(); - } -} -contract ArbConfigurator is Script { - function run() external { - vm.startBroadcast(); - // Set rate limit - IRateLimiter.Config memory rateLimitConfig = IRateLimiter.Config({ - isEnabled: true, - capacity: 10_000e18, - rate: 60e18 - }); - IUpgradeableBurnMintTokenPool(0x3eC2b6F818B72442fc36561e9F930DD2b60957D2) - .setChainRateLimiterConfig(16015286601757825753, rateLimitConfig, rateLimitConfig); - vm.stopBroadcast(); - } -}