From 24a3f7d23e03aca479c43c3f5d8a26c06d2686e8 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 6 Dec 2023 03:34:57 +0530 Subject: [PATCH 001/123] 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 002/123] 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 003/123] 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 004/123] 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 005/123] 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 006/123] 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 007/123] 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 008/123] 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 009/123] 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 c64c0c16e5c7b2395c2c04929385855c85a9831d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 9 Dec 2024 22:29:36 +0530 Subject: [PATCH 010/123] chore: init aip --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 15 ++ ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 32 ++++ ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 17 ++ ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 32 ++++ .../GHOCCIP151Upgrade.md | 22 +++ .../GHOCCIP151Upgrade_20241209.s.sol | 87 ++++++++++ .../config.ts | 17 ++ .../utils/CCIPUtils.sol | 157 ++++++++++++++++++ 8 files changed, 379 insertions(+) create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade.md create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.s.sol create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/config.ts create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol new file mode 100644 index 000000000..ec61d0ecc --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +/** + * @title GHO CCIP 1.5.1 Upgrade + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { + function execute() external { + // custom code goes here + } +} diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol new file mode 100644 index 000000000..dd23bd9e9 --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; + +/** + * @dev Test for AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 + * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol -vv + */ +contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Test is ProtocolV3TestBase { + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('arbitrum'), 283036001); + proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Arbitrum_GHOCCIP151Upgrade_20241209', + AaveV3Arbitrum.POOL, + address(proposal) + ); + } +} diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol new file mode 100644 index 000000000..4ffc72b93 --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +/** + * @title GHO CCIP 1.5.1 Upgrade + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + + function execute() external { + // custom code goes here + } +} diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol new file mode 100644 index 000000000..4e5857fe4 --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; + +/** + * @dev Test for AaveV3Ethereum_GHOCCIP151Upgrade_20241209 + * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol -vv + */ +contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Test is ProtocolV3TestBase { + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 21366260); + proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_GHOCCIP151Upgrade_20241209', + AaveV3Ethereum.POOL, + address(proposal) + ); + } +} diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade.md b/src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade.md new file mode 100644 index 000000000..fb8e2c778 --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade.md @@ -0,0 +1,22 @@ +--- +title: "GHO CCIP 1.5.1 Upgrade" +author: "Aave Labs" +discussions: "" +--- + +## Simple Summary + +## Motivation + +## Specification + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.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/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.s.sol b/src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.s.sol new file mode 100644 index 000000000..c4a58b46b --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.s.sol @@ -0,0 +1,87 @@ +// 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_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; +import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.s.sol:DeployEthereum chain=mainnet + * verify-command: FOUNDRY_PROFILE=mainnet npx catapulta-verify -b broadcast/GHOCCIP151Upgrade_20241209.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_GHOCCIP151Upgrade_20241209).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/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.s.sol:DeployArbitrum chain=arbitrum + * verify-command: FOUNDRY_PROFILE=arbitrum npx catapulta-verify -b broadcast/GHOCCIP151Upgrade_20241209.s.sol/42161/run-latest.json + */ +contract DeployArbitrum is ArbitrumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Arbitrum_GHOCCIP151Upgrade_20241209).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/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade_20241209.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_GHOCCIP151Upgrade_20241209).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + IPayloadsControllerCore.ExecutionAction[] + memory actionsArbitrum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsArbitrum[0] = GovV3Helpers.buildAction( + type(AaveV3Arbitrum_GHOCCIP151Upgrade_20241209).creationCode + ); + payloads[1] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovernanceV3Ethereum.VOTING_PORTAL_ETH_POL, + GovV3Helpers.ipfsHashFile(vm, 'src/20241209_Multi_GHOCCIP151Upgrade/GHOCCIP151Upgrade.md') + ); + } +} diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts new file mode 100644 index 000000000..0647cfa65 --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -0,0 +1,17 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum', 'AaveV3Arbitrum'], + title: 'GHO CCIP 1.5.1 Upgrade', + shortName: 'GHOCCIP151Upgrade', + date: '20241209', + author: 'Aave Labs', + discussion: '', + snapshot: '', + votingNetwork: 'POLYGON', + }, + poolOptions: { + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21366260}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 283036001}}, + }, +}; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol b/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol new file mode 100644 index 000000000..b7e6f2f1b --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +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; + } + + 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: '' + }); + + 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: getDestGasAmount(onRamp, params.message.tokenAmounts[i].token) + }) + ); + } + + 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)) + ) + ); + } + + 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; + } +} From 2ff2f26c8342d2ec2d1a90fbe449ff34cd3485c1 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 00:55:53 +0530 Subject: [PATCH 011/123] feat: ccip 1.5.1 upgrade --- .gitmodules | 4 + ...hereum_GHOCCIP151Upgrade_20241209_after.md | 19 + lib/ccip | 1 + remappings.txt | 1 + ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 104 ++- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 462 ++++++++++++- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 627 ++++++++++++++++++ ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 77 ++- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 492 +++++++++++++- .../utils/CCIPUtils.sol | 17 +- src/interfaces/IGhoToken.sol | 41 +- src/interfaces/ccip/IEVM2EVMOffRamp.sol | 20 +- src/interfaces/ccip/IEVM2EVMOnRamp.sol | 72 ++ src/interfaces/ccip/IInternal.sol | 5 + src/interfaces/ccip/IRateLimiter.sol | 19 + src/interfaces/ccip/IRouter.sol | 46 +- src/interfaces/ccip/ITokenAdminRegistry.sol | 48 ++ src/interfaces/ccip/ITypeAndVersion.sol | 6 + src/interfaces/ccip/tokenPool/IPool.sol | 32 + .../IUpgradeableBurnMintTokenPool.sol | 219 ++++++ .../IUpgradeableLockReleaseTokenPool.sol | 267 ++++++++ 21 files changed, 2544 insertions(+), 35 deletions(-) create mode 100644 diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md create mode 160000 lib/ccip create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol create mode 100644 src/interfaces/ccip/IEVM2EVMOnRamp.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 create mode 100644 src/interfaces/ccip/tokenPool/IPool.sol create mode 100644 src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol create mode 100644 src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol diff --git a/.gitmodules b/.gitmodules index f7316a1d6..df7437c38 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "lib/aave-helpers"] path = lib/aave-helpers url = https://github.com/bgd-labs/aave-helpers +[submodule "lib/ccip"] + path = lib/ccip + url = https://github.com/aave/ccip + branch = feat/1_5_1_token_pool diff --git a/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md b/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md new file mode 100644 index 000000000..95861275d --- /dev/null +++ b/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md @@ -0,0 +1,19 @@ +## Emodes changed + +### EMode: ETH correlated(id: 1) + + + +### EMode: sUSDe Stablecoins(id: 2) + + + +### EMode: rsETH LST main(id: 3) + + + +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/lib/ccip b/lib/ccip new file mode 160000 index 000000000..5f84e6eaa --- /dev/null +++ b/lib/ccip @@ -0,0 +1 @@ +Subproject commit 5f84e6eaa1393ce19c50c3dfbbc026a77d1998c7 diff --git a/remappings.txt b/remappings.txt index 9fefc7eea..8f62b1c9f 100644 --- a/remappings.txt +++ b/remappings.txt @@ -3,3 +3,4 @@ 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/ccip/contracts/src/v0.8/ccip diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index ec61d0ecc..218894346 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -2,6 +2,22 @@ pragma solidity ^0.8.0; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; + +contract Burner { + function burn(address token, uint256 amount) external { + IGhoToken(token).burn(amount); + } +} + /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs @@ -9,7 +25,93 @@ import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGen * - Discussion: TODO */ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { + uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; + + // https://arbiscan.io/address/0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E + ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + + // https://arbiscan.io/address/0xF168B83598516A532a85995b52504a2Fa058C068 + IUpgradeableBurnMintTokenPool_1_4 public constant EXISTING_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; -> not using since this will be overwritten with new token pool address + IUpgradeableBurnMintTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; + + // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 + address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH + address public immutable NEW_REMOTE_POOL_ETH; + + ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); + IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); + + constructor(address newTokenPoolArb, address newTokenPoolEth) { + NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); + NEW_REMOTE_POOL_ETH = newTokenPoolEth; + } + function execute() external { - // custom code goes here + _acceptOwnership(); + _migrateLiquidity(); + _setupAndRegisterNewPool(); + } + + // pre-req - chainlink transfers gho token pool ownership on token admin registry + function _acceptOwnership() internal { + NEW_TOKEN_POOL.acceptOwnership(); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(AaveV3ArbitrumAssets.GHO_UNDERLYING); + } + + function _migrateLiquidity() internal { + // bucketLevel === bridgedAmount + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(EXISTING_TOKEN_POOL) + ); + + GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); + NEW_TOKEN_POOL.transferLiquidity(address(EXISTING_TOKEN_POOL), bucketLevel); + + address existingTokenPoolImpl = PROXY_ADMIN.getProxyImplementation( + TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))) + ); + PROXY_ADMIN.upgrade( + TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), + address(new Burner()) + ); + Burner(address(EXISTING_TOKEN_POOL)).burn(address(GHO), bucketLevel); + PROXY_ADMIN.upgrade( + TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), + existingTokenPoolImpl + ); + + GHO.removeFacilitator(address(EXISTING_TOKEN_POOL)); + } + + function _setupAndRegisterNewPool() internal { + IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ + isEnabled: false, + capacity: 0, + rate: 0 + }); + + IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] + memory chains = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](1); + + bytes[] memory remotePoolAddresses = new bytes[](2); + remotePoolAddresses[0] = abi.encode(EXISTING_REMOTE_POOL_ETH); + remotePoolAddresses[1] = abi.encode(NEW_REMOTE_POOL_ETH); + + chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + remoteChainSelector: ETH_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(MiscEthereum.GHO_TOKEN), + outboundRateLimiterConfig: emptyRateLimiterConfig, + inboundRateLimiterConfig: emptyRateLimiterConfig + }); + + // setup new pool + NEW_TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); + NEW_TOKEN_POOL.setRateLimitAdmin(EXISTING_TOKEN_POOL.getRateLimitAdmin()); // GhoCcipSteward + + // register new pool + TOKEN_ADMIN_REGISTRY.setPool(address(GHO), address(NEW_TOKEN_POOL)); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index dd23bd9e9..deb7bf5f0 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -1,32 +1,482 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import 'forge-std/Test.sol'; + +import {IGhoToken} from 'src/interfaces/IGhoToken.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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; +import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; +import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; -import 'forge-std/Test.sol'; -import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; /** * @dev Test for AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol -vv */ -contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Test is ProtocolV3TestBase { +contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { + struct CCIPSendParams { + address sender; + uint256 amount; + CCIPUtils.PoolVersion poolVersion; + } + + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + + IGhoToken internal constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + address internal constant ETH_PROXY_POOL = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; + IEVM2EVMOnRamp internal constant ON_RAMP = + IEVM2EVMOnRamp(0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3); + IEVM2EVMOffRamp_1_5 internal constant OFF_RAMP = + IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); + IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); + address internal constant GHO_CCIP_STEWARD = 0xb329CEFF2c362F315900d245eC88afd24C4949D5; + + IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_4(MiscArbitrum.GHO_CCIP_TOKEN_POOL); // will be changed to 1.5.1 after AIP execution + IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; - function setUp() public { + address internal NEW_REMOTE_POOL_ETH = makeAddr('LockReleaseTokenPool 1.5.1'); + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + event Burned(address indexed sender, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + event CCIPSendRequested(IInternal.EVM2EVMMessage message); + + function setUp() public virtual { vm.createSelectFork(vm.rpcUrl('arbitrum'), 283036001); - proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); + NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); + proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ETH + ); + + // pre-req - chainlink transfers gho token pool ownership on token admin registry + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + + _validateConstants(); } /** * @dev executes the generic test suite including e2e and config snapshots */ - function test_defaultProposalExecution() public { + function skip_test_defaultProposalExecution() public { defaultTest( 'AaveV3Arbitrum_GHOCCIP151Upgrade_20241209', AaveV3Arbitrum.POOL, address(proposal) ); } + + function _deployNewTokenPoolArb() private returns (address) { + IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( + MiscArbitrum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolImpl = address( + new UpgradeableBurnMintTokenPool( + existingTokenPool.getToken(), + IGhoToken(existingTokenPool.getToken()).decimals(), + existingTokenPool.getArmProxy(), + existingTokenPool.getAllowListEnabled() + ) + ); + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + address(MiscArbitrum.PROXY_ADMIN), + abi.encodeCall( + IUpgradeableBurnMintTokenPool_1_5_1.initialize, + ( + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner + existingTokenPool.getAllowList(), + existingTokenPool.getRouter() + ) + ) + ) + ); + } + + function _validateConstants() private view { + assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); + assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); + assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); + assertEq(address(proposal.EXISTING_REMOTE_POOL_ETH()), ETH_PROXY_POOL); + assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(address(proposal.NEW_REMOTE_POOL_ETH()), NEW_REMOTE_POOL_ETH); + + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); + assertEq(EXISTING_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.4.0'); + assertEq( + ITypeAndVersion(EXISTING_TOKEN_POOL.getProxyPool()).typeAndVersion(), + 'BurnMintTokenPoolAndProxy 1.5.0' + ); + assertEq(ON_RAMP.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(OFF_RAMP.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + + assertEq(ROUTER.typeAndVersion(), 'Router 1.2.0'); + assertEq(EXISTING_TOKEN_POOL.getRouter(), address(ROUTER)); + + assertEq(ROUTER.getOnRamp(ETH_CHAIN_SELECTOR), address(ON_RAMP)); + assertTrue(ROUTER.isOffRamp(ETH_CHAIN_SELECTOR, address(OFF_RAMP))); + } + + 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: AaveV3ArbitrumAssets.GHO_UNDERLYING, + amount: params.amount + }); + + uint256 feeAmount = ROUTER.getFee(ETH_CHAIN_SELECTOR, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: ROUTER, + sourceChainSelector: ARB_CHAIN_SELECTOR, + feeTokenAmount: feeAmount, + originalSender: params.sender, + sourceToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, + destinationToken: MiscEthereum.GHO_TOKEN, + poolVersion: params.poolVersion + }) + ); + + return (message, eventArg); + } + + function _getStaticParams(address tokenPool) internal view returns (bytes memory) { + IUpgradeableBurnMintTokenPool_1_4 ghoTokenPool = IUpgradeableBurnMintTokenPool_1_4(tokenPool); + return + abi.encode( + ghoTokenPool.getToken(), + ghoTokenPool.getAllowListEnabled(), + ghoTokenPool.getAllowList(), + ghoTokenPool.getRouter() + ); + } + + function _getDynamicParams(address tokenPool) internal view returns (bytes memory) { + IUpgradeableBurnMintTokenPool_1_4 ghoTokenPool = IUpgradeableBurnMintTokenPool_1_4(tokenPool); + return + abi.encode( + ghoTokenPool.owner(), + ghoTokenPool.getSupportedChains(), + ghoTokenPool.getAllowListEnabled(), + ghoTokenPool.getRateLimitAdmin() + ); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() internal pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + } +} + +contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base +{ + function setUp() public override { + super.setUp(); + } + + function test_tokenPoolOwnershipTransfer() public { + assertFalse( + TOKEN_ADMIN_REGISTRY.isAdministrator(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1) + ); + ITokenAdminRegistry.TokenConfig memory tokenConfig = TOKEN_ADMIN_REGISTRY.getTokenConfig( + address(GHO) + ); + assertNotEq(tokenConfig.administrator, GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(tokenConfig.pendingAdministrator, GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(tokenConfig.tokenPool, EXISTING_TOKEN_POOL.getProxyPool()); + + executePayload(vm, address(proposal)); + + tokenConfig = TOKEN_ADMIN_REGISTRY.getTokenConfig(address(GHO)); + assertEq(tokenConfig.administrator, GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(tokenConfig.pendingAdministrator, address(0)); + assertEq(tokenConfig.tokenPool, address(NEW_TOKEN_POOL)); + } + + function test_tokenPoolLiquidityMigration() public { + IGhoToken.Facilitator memory existingFacilitator = GHO.getFacilitator( + address(EXISTING_TOKEN_POOL) + ); + IGhoToken.Facilitator memory newFacilitator = GHO.getFacilitator(address(NEW_TOKEN_POOL)); + + assertEq(bytes(newFacilitator.label).length, 0); + assertEq(newFacilitator.bucketCapacity, 0); + assertEq(newFacilitator.bucketLevel, 0); + + assertEq(existingFacilitator.label, 'CCIP TokenPool'); + assertGt(existingFacilitator.bucketCapacity, 0); + assertGt(existingFacilitator.bucketLevel, 0); + + executePayload(vm, address(proposal)); + + newFacilitator = GHO.getFacilitator(address(NEW_TOKEN_POOL)); + + assertEq(newFacilitator.label, 'CCIP v1.5.1 TokenPool'); + assertEq(newFacilitator.bucketCapacity, existingFacilitator.bucketCapacity); + assertEq(newFacilitator.bucketLevel, existingFacilitator.bucketLevel); + + existingFacilitator = GHO.getFacilitator(address(EXISTING_TOKEN_POOL)); + + assertEq(bytes(existingFacilitator.label).length, 0); + assertEq(existingFacilitator.bucketCapacity, 0); + assertEq(existingFacilitator.bucketLevel, 0); + } + + function test_newTokenPoolSetupAndRegistration() public { + bytes memory staticParams = _getStaticParams(address(EXISTING_TOKEN_POOL)); + bytes memory dynamicParams = _getDynamicParams(address(EXISTING_TOKEN_POOL)); + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); + + assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), EXISTING_TOKEN_POOL.getProxyPool()); + + executePayload(vm, address(proposal)); + + assertEq(staticParams, _getStaticParams(address(NEW_TOKEN_POOL))); + assertEq(dynamicParams, _getDynamicParams(address(NEW_TOKEN_POOL))); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); + assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 2); + assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(ETH_PROXY_POOL))); + assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ETH))); + assertEq(NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), abi.encode(MiscEthereum.GHO_TOKEN)); + assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 1); + assertTrue(NEW_TOKEN_POOL.isSupportedChain(ETH_CHAIN_SELECTOR)); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); // sanity check + + assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), address(NEW_TOKEN_POOL)); + } + + function test_newTokenPoolInitialization() public { + vm.expectRevert('Initializable: contract is already initialized'); + NEW_TOKEN_POOL.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); + assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); + assertEq(_readInitialized(_getImplementation(address(NEW_TOKEN_POOL))), 255); + } +} + +contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base +{ + function setUp() public override { + super.setUp(); + + executePayload(vm, address(proposal)); + } + + function test_sendMessageSucceedsAndRoutesViaNewPool() public { + uint256 amount = 100_000e18; + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, poolVersion: CCIPUtils.PoolVersion.V1_5_1}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); // new token pool + emit Burned(address(ON_RAMP), amount); + + vm.expectEmit(address(ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel - amount); + } + + // existing pool can no longer on ramp + function test_lockOrBurnRevertsOnExistingPool() public { + uint256 amount = 100_000e18; + + // prank router.gho.transferFrom(user, EXISTING_TOKEN_POOL, amount) + deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); + + vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); + // underflow expected at GHO.burn() => bucketLevel - amount + vm.expectRevert(stdError.arithmeticError); + EXISTING_TOKEN_POOL.lockOrBurn( + alice, + abi.encode(alice), + amount, + ETH_CHAIN_SELECTOR, + new bytes(0) + ); + } + + // on-ramp via new pool + function test_lockOrBurnSucceedsOnNewPool() public { + uint256 amount = 100_000e18; + + // prank router.gho.transferFrom(user, NEW_TOKEN_POOL, amount) + deal(address(GHO), address(NEW_TOKEN_POOL), amount); + + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Burned(address(ON_RAMP), amount); + + vm.prank(address(ON_RAMP)); + NEW_TOKEN_POOL.lockOrBurn( + IPool_CCIP.LockOrBurnInV1({ + receiver: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + originalSender: alice, + amount: amount, + localToken: address(GHO) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel - amount); + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), 0); // dealt amount is burned + } + + // existing pool can no longer off ramp + function test_releaseOrMintRevertsOnExistingPool() public { + uint256 amount = 100_000e18; + + vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); + vm.expectRevert('FACILITATOR_BUCKET_CAPACITY_EXCEEDED'); + EXISTING_TOKEN_POOL.releaseOrMint( + abi.encode(alice), + alice, + amount, + ETH_CHAIN_SELECTOR, + new bytes(0) + ); + } + + // off-ramp messages sent from new eth token pool (v1.5.1) + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth() public { + uint256 amount = 100_000e18; + + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + uint256 aliceBalance = GHO.balanceOf(alice); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Minted(address(OFF_RAMP), alice, amount); + + vm.prank(address(OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ETH)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel + amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + } + + // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth() public { + uint256 amount = 100_000e18; + + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + uint256 aliceBalance = GHO.balanceOf(alice); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Minted(address(OFF_RAMP), alice, amount); + + vm.prank(address(OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(ETH_PROXY_POOL)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel + amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol new file mode 100644 index 000000000..e1d42aa6c --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -0,0 +1,627 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Test.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 {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; + +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; + +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; +import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; +import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; + +/** + * @dev Test for AaveV3E2E_GHOCCIP151Upgrade_20241209 + * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol -vv + */ +contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { + struct CCIPSendParams { + IRouter router; + IGhoToken token; + uint256 amount; + uint64 sourceChainSelector; + uint64 destinationChainSelector; + address sender; + CCIPUtils.PoolVersion poolVersion; + } + + struct Common { + IRouter router; + IGhoToken token; + IEVM2EVMOnRamp EVM2EVMOnRamp; + IEVM2EVMOffRamp_1_5 EVM2EVMOffRamp; + ITokenAdminRegistry tokenAdminRegistry; + address proxyPool; + uint64 chainSelector; + uint256 forkId; + } + + struct L1 { + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 proposal; + IUpgradeableLockReleaseTokenPool_1_5_1 newTokenPool; + IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool; + Common c; + } + + struct L2 { + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 proposal; + IUpgradeableBurnMintTokenPool_1_5_1 newTokenPool; + IUpgradeableBurnMintTokenPool_1_4 existingTokenPool; + Common c; + } + + L1 internal l1; + L2 internal l2; + + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + 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'), 21366260); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 283036001); + + vm.selectFork(l1.c.forkId); + address newTokenPoolEth = _deployNewTokenPoolEth(); + vm.selectFork(l2.c.forkId); + address newTokenPoolArb = _deployNewTokenPoolArb(); + + vm.selectFork(l1.c.forkId); + l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(newTokenPoolEth, newTokenPoolArb); + l1.existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4(MiscEthereum.GHO_CCIP_TOKEN_POOL); + l1.newTokenPool = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); + l1.c.router = IRouter(l1.existingTokenPool.getRouter()); + l2.c.chainSelector = l1.existingTokenPool.getSupportedChains()[0]; + l1.c.token = IGhoToken(address(l1.existingTokenPool.getToken())); + l1.c.EVM2EVMOnRamp = IEVM2EVMOnRamp(l1.c.router.getOnRamp(l2.c.chainSelector)); + l1.c.EVM2EVMOffRamp = IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); // new offramp + l1.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + l1.c.proxyPool = l1.existingTokenPool.getProxyPool(); + + vm.selectFork(l2.c.forkId); + l2.proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(newTokenPoolArb, newTokenPoolEth); + l2.existingTokenPool = IUpgradeableBurnMintTokenPool_1_4(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + l2.newTokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); + l2.c.router = IRouter(l2.existingTokenPool.getRouter()); + l1.c.chainSelector = l2.existingTokenPool.getSupportedChains()[0]; + l2.c.token = IGhoToken(address(l2.existingTokenPool.getToken())); + l2.c.EVM2EVMOnRamp = IEVM2EVMOnRamp(l2.c.router.getOnRamp(l1.c.chainSelector)); + l2.c.EVM2EVMOffRamp = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); // new offramp + l2.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + l2.c.proxyPool = l2.existingTokenPool.getProxyPool(); + + _validateConfig({upgraded: false}); + + _performPoolTransferCLLPreReq(); // rm once CLL performs this action + } + + 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, + sourceToken: address(params.token), + destinationToken: address(params.token == l1.c.token ? l2.c.token : l1.c.token), + poolVersion: params.poolVersion + }) + ); + + return (message, eventArg); + } + + function _validateConfig(bool upgraded) internal { + vm.selectFork(l1.c.forkId); + assertEq(l1.c.chainSelector, 5009297550715157269); + assertEq(address(l1.c.token), MiscEthereum.GHO_TOKEN); + assertEq(l1.c.router.typeAndVersion(), 'Router 1.2.0'); + assertEq(l1.c.EVM2EVMOnRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(l1.c.EVM2EVMOffRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + + assertEq(l1.existingTokenPool.typeAndVersion(), 'LockReleaseTokenPool 1.4.0'); + assertEq(l1.newTokenPool.typeAndVersion(), 'LockReleaseTokenPool 1.5.1'); + + assertEq(l1.c.tokenAdminRegistry.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertTrue(l1.c.router.isOffRamp(l2.c.chainSelector, address(l1.c.EVM2EVMOffRamp))); + assertEq(l1.c.router.getOnRamp(l2.c.chainSelector), address(l1.c.EVM2EVMOnRamp)); + + // proposal constants + assertEq(address(l1.proposal.TOKEN_ADMIN_REGISTRY()), address(l1.c.tokenAdminRegistry)); + assertEq(l1.proposal.ARB_CHAIN_SELECTOR(), l2.c.chainSelector); + assertEq(address(l1.proposal.EXISTING_TOKEN_POOL()), address(l1.existingTokenPool)); + assertEq(address(l1.proposal.EXISTING_REMOTE_POOL_ARB()), l2.c.proxyPool); + assertEq(address(l1.proposal.NEW_TOKEN_POOL()), address(l1.newTokenPool)); + assertEq(address(l1.proposal.NEW_REMOTE_POOL_ARB()), address(l2.newTokenPool)); + + if (upgraded) { + assertEq(l1.c.tokenAdminRegistry.getPool(MiscEthereum.GHO_TOKEN), address(l1.newTokenPool)); + + assertEq(l1.c.token.balanceOf(address(l1.existingTokenPool)), 0); + // ! todo upgrade existing pool to reset bridgedAmount? not necessary since we reset bridgeLimit + // assertEq(l1.existingTokenPool.getCurrentBridgedAmount(), 0); + + assertGt(l1.c.token.balanceOf(address(l1.newTokenPool)), 0); + assertGt(l1.newTokenPool.getCurrentBridgedAmount(), 0); + } else { + assertEq(l1.c.tokenAdminRegistry.getPool(MiscEthereum.GHO_TOKEN), l1.c.proxyPool); + + assertGt(l1.c.token.balanceOf(address(l1.existingTokenPool)), 0); + assertGt(l1.existingTokenPool.getCurrentBridgedAmount(), 0); + + assertEq(l1.c.token.balanceOf(address(l1.newTokenPool)), 0); + assertEq(l1.newTokenPool.getCurrentBridgedAmount(), 0); + } + + vm.selectFork(l2.c.forkId); + assertEq(l2.c.chainSelector, 4949039107694359620); + assertEq(address(l2.c.token), 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33); + assertEq(l2.c.router.typeAndVersion(), 'Router 1.2.0'); + assertEq(l2.c.EVM2EVMOnRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(l2.c.EVM2EVMOffRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + assertEq(l2.existingTokenPool.typeAndVersion(), 'BurnMintTokenPool 1.4.0'); + assertEq(l2.newTokenPool.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); + assertEq(l2.c.tokenAdminRegistry.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertTrue(l2.c.router.isOffRamp(l1.c.chainSelector, address(l2.c.EVM2EVMOffRamp))); + + assertEq(l2.c.router.getOnRamp(l1.c.chainSelector), address(l2.c.EVM2EVMOnRamp)); + + // proposal constants + assertEq(address(l2.proposal.TOKEN_ADMIN_REGISTRY()), address(l2.c.tokenAdminRegistry)); + assertEq(l2.proposal.ETH_CHAIN_SELECTOR(), l1.c.chainSelector); + assertEq(address(l2.proposal.EXISTING_TOKEN_POOL()), address(l2.existingTokenPool)); + assertEq(address(l2.proposal.EXISTING_REMOTE_POOL_ETH()), l1.c.proxyPool); + assertEq(address(l2.proposal.NEW_TOKEN_POOL()), address(l2.newTokenPool)); + assertEq(address(l2.proposal.NEW_REMOTE_POOL_ETH()), address(l1.newTokenPool)); + + if (upgraded) { + assertEq( + l2.c.tokenAdminRegistry.getPool(AaveV3ArbitrumAssets.GHO_UNDERLYING), + address(l2.newTokenPool) + ); + assertEq(bytes(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label).length, 0); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP v1.5.1 TokenPool'); + } else { + assertEq( + l2.c.tokenAdminRegistry.getPool(AaveV3ArbitrumAssets.GHO_UNDERLYING), + l2.c.proxyPool + ); + assertEq(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label, 'CCIP TokenPool'); + assertEq(bytes(l2.c.token.getFacilitator(address(l2.newTokenPool)).label).length, 0); + } + } + + function _executeUpgradeAIP() internal { + vm.selectFork(l1.c.forkId); + executePayload(vm, address(l1.proposal)); + vm.selectFork(l2.c.forkId); + executePayload(vm, address(l2.proposal)); + } + + function _performPoolTransferCLLPreReq() private { + vm.selectFork(l1.c.forkId); + vm.prank(l1.c.tokenAdminRegistry.owner()); + l1.c.tokenAdminRegistry.transferAdminRole( + MiscEthereum.GHO_TOKEN, + GovernanceV3Ethereum.EXECUTOR_LVL_1 + ); + + vm.selectFork(l2.c.forkId); + vm.prank(l2.c.tokenAdminRegistry.owner()); + l2.c.tokenAdminRegistry.transferAdminRole( + AaveV3ArbitrumAssets.GHO_UNDERLYING, + GovernanceV3Arbitrum.EXECUTOR_LVL_1 + ); + } + + function _deployNewTokenPoolEth() private returns (address) { + IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( + MiscEthereum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolImpl = address( + new UpgradeableLockReleaseTokenPool( + existingTokenPool.getToken(), + IGhoToken(existingTokenPool.getToken()).decimals(), + existingTokenPool.getArmProxy(), + existingTokenPool.getAllowListEnabled(), + existingTokenPool.canAcceptLiquidity() + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + MiscEthereum.PROXY_ADMIN, + abi.encodeCall( + IUpgradeableLockReleaseTokenPool_1_5_1.initialize, + ( + GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner + existingTokenPool.getAllowList(), + existingTokenPool.getRouter(), + existingTokenPool.getBridgeLimit() + ) + ) + ) + ); + } + + function _deployNewTokenPoolArb() private returns (address) { + IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( + MiscArbitrum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolImpl = address( + new UpgradeableBurnMintTokenPool( + existingTokenPool.getToken(), + IGhoToken(existingTokenPool.getToken()).decimals(), + existingTokenPool.getArmProxy(), + existingTokenPool.getAllowListEnabled() + ) + ); + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + address(MiscArbitrum.PROXY_ADMIN), + abi.encodeCall( + IUpgradeableBurnMintTokenPool_1_5_1.initialize, + ( + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner + existingTokenPool.getAllowList(), + existingTokenPool.getRouter() + ) + ) + ) + ); + } + + // post upgrade + function _runEthToArb(address user, uint256 amount) internal { + vm.selectFork(l1.c.forkId); + + vm.prank(user); + l1.c.token.approve(address(l1.c.router), amount); + + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.newTokenPool)); + uint256 userBalance = l1.c.token.balanceOf(user); + uint256 bridgedAmount = l1.newTokenPool.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: user, + poolVersion: CCIPUtils.PoolVersion.V1_5_1 + }) + ); + + vm.expectEmit(address(l1.newTokenPool)); + emit Locked(address(l1.c.EVM2EVMOnRamp), amount); + + vm.expectEmit(address(l1.c.EVM2EVMOnRamp)); + emit CCIPSendRequested(eventArg); + vm.prank(user); + l1.c.router.ccipSend{value: eventArg.feeTokenAmount}(l2.c.chainSelector, message); + + assertEq(l1.c.token.balanceOf(address(l1.newTokenPool)), tokenPoolBalance + amount); + assertEq(l1.c.token.balanceOf(user), userBalance - amount); + assertEq(l1.newTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + + // ARB executeMessage + vm.selectFork(l2.c.forkId); + + userBalance = l2.c.token.balanceOf(user); + uint256 bucketLevel = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; + + vm.expectEmit(address(l2.newTokenPool)); + emit Minted(address(l2.c.EVM2EVMOffRamp), user, amount); + vm.prank(address(l2.c.EVM2EVMOffRamp)); + l2.c.EVM2EVMOffRamp.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](0) + ); + + assertEq(l2.c.token.balanceOf(user), userBalance + amount); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel, bucketLevel + amount); + } + + // post upgrade + function _runArbToEth(address user, uint256 amount) internal { + vm.selectFork(l2.c.forkId); + + vm.prank(user); + l2.c.token.approve(address(l2.c.router), amount); + + uint256 userBalance = l2.c.token.balanceOf(user); + uint256 bucketLevel = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; + + ( + 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: user, + poolVersion: CCIPUtils.PoolVersion.V1_5_1 + }) + ); + + vm.expectEmit(address(l2.newTokenPool)); + emit Burned(address(l2.c.EVM2EVMOnRamp), amount); + + vm.expectEmit(address(l2.c.EVM2EVMOnRamp)); + emit CCIPSendRequested(eventArg); + vm.prank(user); + l2.c.router.ccipSend{value: eventArg.feeTokenAmount}(l1.c.chainSelector, message); + + assertEq(l2.c.token.balanceOf(user), userBalance - amount); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel, bucketLevel - amount); + + // ETH executeMessage + vm.selectFork(l1.c.forkId); + + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.newTokenPool)); + uint256 bridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); + userBalance = l1.c.token.balanceOf(user); + + vm.expectEmit(address(l1.newTokenPool)); + emit Released(address(l1.c.EVM2EVMOffRamp), user, amount); + vm.prank(address(l1.c.EVM2EVMOffRamp)); + l1.c.EVM2EVMOffRamp.executeSingleMessage( + eventArg, + new bytes[](message.tokenAmounts.length), + new uint32[](1) // tokenGasOverrides + ); + + assertEq(l1.c.token.balanceOf(address(l1.newTokenPool)), tokenPoolBalance - amount); + assertEq(l1.newTokenPool.getCurrentBridgedAmount(), bridgedAmount - amount); + assertEq(l1.c.token.balanceOf(user), userBalance + amount); + } +} + +contract AaveV3E2E_GHOCCIP151Upgrade_20241209_PostUpgrade is + AaveV3E2E_GHOCCIP151Upgrade_20241209_Base +{ + function setUp() public override { + super.setUp(); + + _executeUpgradeAIP(); + + _validateConfig({upgraded: true}); + } + + function test_E2E_FromEth(uint256 amount) public { + vm.selectFork(l1.c.forkId); + uint256 currentBridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); + + amount = bound(amount, 1, currentBridgedAmount); + deal(address(l1.c.token), alice, amount); + + _runEthToArb(alice, amount); + _runArbToEth(alice, amount); + } + + function test_E2E_FromArb(uint256 amount) public { + vm.selectFork(l2.c.forkId); + uint256 currentBridgedAmount = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; + + amount = bound(amount, 1, currentBridgedAmount); + deal(address(l2.c.token), alice, amount); + + _runArbToEth(alice, amount); + _runEthToArb(alice, amount); + } + + function test_E2E_Multiple() public { + vm.selectFork(l1.c.forkId); + uint256 currentBridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); + uint256 amount = currentBridgedAmount / 3; + + deal(address(l1.c.token), alice, amount); + deal(address(l1.c.token), bob, amount); + + vm.selectFork(l2.c.forkId); + deal(address(l2.c.token), carol, amount); + + _runEthToArb(alice, amount); + _runEthToArb(bob, amount); + _runArbToEth(alice, amount); + _runArbToEth(carol, amount); + _runEthToArb(carol, amount); + _runArbToEth(bob, amount); + } +} + +// sendMsg => upgrade => executeMsg +contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is + AaveV3E2E_GHOCCIP151Upgrade_20241209_Base +{ + function setUp() public override { + super.setUp(); + } + + function test_E2E_InFlightMsg_FromEth() public { + vm.selectFork(l1.c.forkId); + + uint256 amount = 100_000e18; + deal(address(l1.c.token), alice, amount); + + vm.prank(alice); + l1.c.token.approve(address(l1.c.router), amount); + + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.existingTokenPool)); + uint256 aliceBalance = l1.c.token.balanceOf(alice); + uint256 bridgedAmount = l1.existingTokenPool.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, + poolVersion: CCIPUtils.PoolVersion.V1_5_0 // existing token pool + }) + ); + + // message sent from existing token pool, pre-AIP-execution + vm.expectEmit(address(l1.existingTokenPool)); + emit Locked(l1.c.proxyPool, amount); + vm.expectEmit(l1.c.proxyPool); + emit Locked(address(l1.c.EVM2EVMOnRamp), amount); + + vm.expectEmit(address(l1.c.EVM2EVMOnRamp)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l1.c.router.ccipSend{value: eventArg.feeTokenAmount}(l2.c.chainSelector, message); + + assertEq(l1.c.token.balanceOf(address(l1.existingTokenPool)), tokenPoolBalance + amount); + assertEq(l1.c.token.balanceOf(alice), aliceBalance - amount); + assertEq(l1.existingTokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + + _executeUpgradeAIP(); // token pools upgraded + + // ARB executeMessage + vm.selectFork(l2.c.forkId); + + aliceBalance = l2.c.token.balanceOf(alice); + uint256 bucketLevel = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; + + vm.expectEmit(address(l2.newTokenPool)); + emit Minted(address(l2.c.EVM2EVMOffRamp), alice, amount); + vm.prank(address(l2.c.EVM2EVMOffRamp)); + l2.c.EVM2EVMOffRamp.executeSingleMessage( + eventArg, // pre-upgrade message + new bytes[](message.tokenAmounts.length), + new uint32[](0) + ); + + assertEq(l2.c.token.balanceOf(alice), aliceBalance + amount); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel, bucketLevel + amount); + + // send tokens back to eth + _runArbToEth(alice, amount); + } + + function test_E2E_InFlightMsg_FromArb() public { + vm.selectFork(l2.c.forkId); + + uint256 amount = 100_000e18; + deal(address(l2.c.token), alice, amount); + + vm.prank(alice); + l2.c.token.approve(address(l2.c.router), amount); + + uint256 aliceBalance = l2.c.token.balanceOf(alice); + uint256 bucketLevel = l2.c.token.getFacilitator(address(l2.existingTokenPool)).bucketLevel; + + ( + 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, + poolVersion: CCIPUtils.PoolVersion.V1_5_0 // existing token pool + }) + ); + + // message sent from existing token pool, pre-AIP-execution + vm.expectEmit(address(l2.existingTokenPool)); + emit Burned(l2.c.proxyPool, amount); + vm.expectEmit(l2.c.proxyPool); + emit Burned(address(l2.c.EVM2EVMOnRamp), amount); + + vm.expectEmit(address(l2.c.EVM2EVMOnRamp)); + emit CCIPSendRequested(eventArg); + vm.prank(alice); + l2.c.router.ccipSend{value: eventArg.feeTokenAmount}(l1.c.chainSelector, message); + + assertEq(l2.c.token.balanceOf(alice), aliceBalance - amount); + assertEq( + l2.c.token.getFacilitator(address(l2.existingTokenPool)).bucketLevel, + bucketLevel - amount + ); + + _executeUpgradeAIP(); // token pools upgraded + + // ETH executeMessage + vm.selectFork(l1.c.forkId); + + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.newTokenPool)); + uint256 bridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); + aliceBalance = l1.c.token.balanceOf(alice); + + vm.expectEmit(address(l1.newTokenPool)); + emit Released(address(l1.c.EVM2EVMOffRamp), alice, amount); + vm.prank(address(l1.c.EVM2EVMOffRamp)); + l1.c.EVM2EVMOffRamp.executeSingleMessage( + eventArg, // pre-upgrade message + new bytes[](message.tokenAmounts.length), + new uint32[](1) // tokenGasOverrides + ); + + assertEq(l1.c.token.balanceOf(address(l1.newTokenPool)), tokenPoolBalance - amount); + assertEq(l1.newTokenPool.getCurrentBridgedAmount(), bridgedAmount - amount); + assertEq(l1.c.token.balanceOf(alice), aliceBalance + amount); + + // send tokens back to arb + _runEthToArb(alice, amount); + } +} diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 4ffc72b93..1385fb8b4 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -2,6 +2,12 @@ pragma solidity ^0.8.0; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; + /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs @@ -9,9 +15,76 @@ import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGen * - Discussion: TODO */ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { - uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + uint64 public constant ARB_CHAIN_SELECTOR = 4949039107694359620; + + // https://etherscan.io/address/0xb22764f98dD05c789929716D677382Df22C05Cb6 + ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + + // https://etherscan.io/address/0x5756880B6a1EAba0175227bf02a7E87c1e02B28C + IUpgradeableLockReleaseTokenPool_1_4 public constant EXISTING_TOKEN_POOL = + IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; -> not using since this will be overwritten with new token pool address + IUpgradeableLockReleaseTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; + + // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 + address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb + address public immutable NEW_REMOTE_POOL_ARB; + + constructor(address newTokenPoolEth, address newTokenPoolArb) { + NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); + NEW_REMOTE_POOL_ARB = newTokenPoolArb; + } function execute() external { - // custom code goes here + _acceptOwnership(); + _migrateLiquidity(); + _setupAndRegisterNewPool(); + } + + // pre-req - chainlink transfers gho token pool ownership on token admin registry + function _acceptOwnership() internal { + NEW_TOKEN_POOL.acceptOwnership(); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(MiscEthereum.GHO_TOKEN); + } + + function _migrateLiquidity() internal { + EXISTING_TOKEN_POOL.setRebalancer(address(NEW_TOKEN_POOL)); + NEW_TOKEN_POOL.transferLiquidity({ + from: address(EXISTING_TOKEN_POOL), + amount: EXISTING_TOKEN_POOL.getCurrentBridgedAmount() + }); + + // disable existing pool + EXISTING_TOKEN_POOL.setBridgeLimit(0); + } + + function _setupAndRegisterNewPool() internal { + bytes[] memory remotePoolAddresses = new bytes[](2); + remotePoolAddresses[0] = abi.encode(EXISTING_REMOTE_POOL_ARB); + remotePoolAddresses[1] = abi.encode(NEW_REMOTE_POOL_ARB); + IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ + isEnabled: false, + capacity: 0, + rate: 0 + }); + + IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[] + memory chains = new IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[](1); + + chains[0] = IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate({ + remoteChainSelector: ARB_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING), + outboundRateLimiterConfig: emptyRateLimiterConfig, + inboundRateLimiterConfig: emptyRateLimiterConfig + }); + + // setup new pool + NEW_TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); + NEW_TOKEN_POOL.setRateLimitAdmin(EXISTING_TOKEN_POOL.getRateLimitAdmin()); // GhoCcipSteward + NEW_TOKEN_POOL.setBridgeLimitAdmin(EXISTING_TOKEN_POOL.getBridgeLimitAdmin()); // GhoCcipSteward + + // register new pool + TOKEN_ADMIN_REGISTRY.setPool(MiscEthereum.GHO_TOKEN, address(NEW_TOKEN_POOL)); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 4e5857fe4..342a80551 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -1,32 +1,512 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import 'forge-std/Test.sol'; + +import {IGhoToken} from 'src/interfaces/IGhoToken.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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; +import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; +import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; -import 'forge-std/Test.sol'; -import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; /** * @dev Test for AaveV3Ethereum_GHOCCIP151Upgrade_20241209 * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol -vv */ -contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Test is ProtocolV3TestBase { +contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { + struct CCIPSendParams { + address sender; + uint256 amount; + CCIPUtils.PoolVersion poolVersion; + } + + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + + IGhoToken internal constant GHO = IGhoToken(MiscEthereum.GHO_TOKEN); + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + address internal constant ARB_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; + IEVM2EVMOnRamp internal constant ON_RAMP = + IEVM2EVMOnRamp(0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284); + IEVM2EVMOffRamp_1_5 internal constant OFF_RAMP = + IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); + IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); + address internal constant GHO_CCIP_STEWARD = 0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4; + + IUpgradeableLockReleaseTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = + IUpgradeableLockReleaseTokenPool_1_4(MiscEthereum.GHO_CCIP_TOKEN_POOL); // will be changed to 1.5.1 after AIP execution + IUpgradeableLockReleaseTokenPool_1_5_1 internal NEW_TOKEN_POOL; + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; - function setUp() public { + address internal NEW_REMOTE_POOL_ARB = makeAddr('BurnMintTokenPool 1.5.1'); + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + event Locked(address indexed sender, uint256 amount); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event CCIPSendRequested(IInternal.EVM2EVMMessage message); + + error BridgeLimitExceeded(uint256 limit); + + function setUp() public virtual { vm.createSelectFork(vm.rpcUrl('mainnet'), 21366260); - proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); + NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(_deployNewTokenPoolEth()); + proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ARB + ); + + // pre-req - chainlink transfers gho token pool ownership on token admin registry + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.transferAdminRole( + MiscEthereum.GHO_TOKEN, + GovernanceV3Ethereum.EXECUTOR_LVL_1 + ); + + _validateConstants(); } /** * @dev executes the generic test suite including e2e and config snapshots */ - function test_defaultProposalExecution() public { + function skip_test_defaultProposalExecution() public { defaultTest( 'AaveV3Ethereum_GHOCCIP151Upgrade_20241209', AaveV3Ethereum.POOL, address(proposal) ); } + + function _deployNewTokenPoolEth() private returns (address) { + IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( + MiscEthereum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolImpl = address( + new UpgradeableLockReleaseTokenPool( + existingTokenPool.getToken(), + IGhoToken(existingTokenPool.getToken()).decimals(), + existingTokenPool.getArmProxy(), + existingTokenPool.getAllowListEnabled(), + existingTokenPool.canAcceptLiquidity() + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + MiscEthereum.PROXY_ADMIN, + abi.encodeCall( + IUpgradeableLockReleaseTokenPool_1_5_1.initialize, + ( + GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner + existingTokenPool.getAllowList(), + existingTokenPool.getRouter(), + existingTokenPool.getBridgeLimit() + ) + ) + ) + ); + } + + function _validateConstants() private view { + assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); + assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); + assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); + assertEq(address(proposal.EXISTING_REMOTE_POOL_ARB()), ARB_PROXY_POOL); + assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(address(proposal.NEW_REMOTE_POOL_ARB()), NEW_REMOTE_POOL_ARB); + + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'LockReleaseTokenPool 1.5.1'); + assertEq(EXISTING_TOKEN_POOL.typeAndVersion(), 'LockReleaseTokenPool 1.4.0'); + assertEq( + ITypeAndVersion(EXISTING_TOKEN_POOL.getProxyPool()).typeAndVersion(), + 'LockReleaseTokenPoolAndProxy 1.5.0' + ); + assertEq(ON_RAMP.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(OFF_RAMP.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + + assertEq(ROUTER.typeAndVersion(), 'Router 1.2.0'); + assertEq(EXISTING_TOKEN_POOL.getRouter(), address(ROUTER)); + + assertEq(ROUTER.getOnRamp(ARB_CHAIN_SELECTOR), address(ON_RAMP)); + assertTrue(ROUTER.isOffRamp(ARB_CHAIN_SELECTOR, address(OFF_RAMP))); + } + + 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: MiscEthereum.GHO_TOKEN, + amount: params.amount + }); + + uint256 feeAmount = ROUTER.getFee(ARB_CHAIN_SELECTOR, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: ROUTER, + sourceChainSelector: ETH_CHAIN_SELECTOR, + feeTokenAmount: feeAmount, + originalSender: params.sender, + sourceToken: MiscEthereum.GHO_TOKEN, + destinationToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, + poolVersion: params.poolVersion + }) + ); + + return (message, eventArg); + } + + function _getStaticParams(address tokenPool) internal view returns (bytes memory) { + IUpgradeableLockReleaseTokenPool_1_4 ghoTokenPool = IUpgradeableLockReleaseTokenPool_1_4( + tokenPool + ); + return + abi.encode( + ghoTokenPool.getToken(), + ghoTokenPool.getAllowListEnabled(), + ghoTokenPool.getAllowList(), + ghoTokenPool.canAcceptLiquidity(), + ghoTokenPool.getRouter() + ); + } + + function _getDynamicParams(address tokenPool) internal view returns (bytes memory) { + IUpgradeableLockReleaseTokenPool_1_4 ghoTokenPool = IUpgradeableLockReleaseTokenPool_1_4( + tokenPool + ); + return + abi.encode( + ghoTokenPool.owner(), + ghoTokenPool.getSupportedChains(), + ghoTokenPool.getAllowListEnabled(), + ghoTokenPool.getRateLimitAdmin(), + ghoTokenPool.getBridgeLimitAdmin(), + ghoTokenPool.getRebalancer(), + ghoTokenPool.getBridgeLimit() + ); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() internal 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)); + } + + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } +} + +contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is + AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base +{ + function setUp() public override { + super.setUp(); + } + + function test_tokenPoolOwnershipTransfer() public { + assertFalse( + TOKEN_ADMIN_REGISTRY.isAdministrator(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1) + ); + ITokenAdminRegistry.TokenConfig memory tokenConfig = TOKEN_ADMIN_REGISTRY.getTokenConfig( + address(GHO) + ); + assertNotEq(tokenConfig.administrator, GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(tokenConfig.pendingAdministrator, GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(tokenConfig.tokenPool, EXISTING_TOKEN_POOL.getProxyPool()); + + executePayload(vm, address(proposal)); + + tokenConfig = TOKEN_ADMIN_REGISTRY.getTokenConfig(address(GHO)); + assertEq(tokenConfig.administrator, GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(tokenConfig.pendingAdministrator, address(0)); + assertEq(tokenConfig.tokenPool, address(NEW_TOKEN_POOL)); + } + + function test_tokenPoolLiquidityMigration() public { + assertEq(EXISTING_TOKEN_POOL.getRebalancer(), address(0)); + uint256 balance = GHO.balanceOf(address(EXISTING_TOKEN_POOL)); + uint256 bridgedAmount = EXISTING_TOKEN_POOL.getCurrentBridgedAmount(); + + assertGt(balance, 0); + assertGt(bridgedAmount, 0); + + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), 0); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), 0); + + assertEq(bridgedAmount, balance); // bridgedAmountInvariant + + executePayload(vm, address(proposal)); + + assertEq(EXISTING_TOKEN_POOL.getRebalancer(), address(NEW_TOKEN_POOL)); + + assertEq(GHO.balanceOf(address(EXISTING_TOKEN_POOL)), 0); + // ! todo upgrade existing pool to reset bridgedAmount? not necessary since we reset bridgeLimit + // assertEq(EXISTING_TOKEN_POOL.getCurrentBridgedAmount(), 0); + + assertEq(balance, GHO.balanceOf(address(NEW_TOKEN_POOL))); + assertEq(bridgedAmount, NEW_TOKEN_POOL.getCurrentBridgedAmount()); + } + + function test_newTokenPoolSetupAndRegistration() public { + bytes memory staticParams = _getStaticParams(address(EXISTING_TOKEN_POOL)); + bytes memory dynamicParams = _getDynamicParams(address(EXISTING_TOKEN_POOL)); + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); + + assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), EXISTING_TOKEN_POOL.getProxyPool()); + + executePayload(vm, address(proposal)); + + assertEq(staticParams, _getStaticParams(address(NEW_TOKEN_POOL))); + assertEq(dynamicParams, _getDynamicParams(address(NEW_TOKEN_POOL))); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); + assertEq(NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR).length, 2); + assertTrue(NEW_TOKEN_POOL.isRemotePool(ARB_CHAIN_SELECTOR, abi.encode(ARB_PROXY_POOL))); + assertTrue(NEW_TOKEN_POOL.isRemotePool(ARB_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ARB))); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ARB_CHAIN_SELECTOR), + abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING) + ); + assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 1); + assertTrue(NEW_TOKEN_POOL.isSupportedChain(ARB_CHAIN_SELECTOR)); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); // sanity check + assertEq(NEW_TOKEN_POOL.getBridgeLimitAdmin(), GHO_CCIP_STEWARD); // sanity check + + assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), address(NEW_TOKEN_POOL)); + } + + function test_newTokenPoolInitialization() public { + vm.expectRevert('Initializable: contract is already initialized'); + NEW_TOKEN_POOL.initialize(makeAddr('owner'), new address[](0), makeAddr('router'), 13e7); + assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); + assertEq(_readInitialized(_getImplementation(address(NEW_TOKEN_POOL))), 255); + } +} + +contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is + AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base +{ + function setUp() public override { + super.setUp(); + + executePayload(vm, address(proposal)); + } + + function test_sendMessageSucceedsAndRoutesViaNewPool() public { + uint256 amount = 100_000e18; + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + uint256 bridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, poolVersion: CCIPUtils.PoolVersion.V1_5_1}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); // new token pool + emit Locked(address(ON_RAMP), amount); + + vm.expectEmit(address(ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), tokenPoolBalance + amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount + amount); + } + + // existing pool can no longer on ramp + function test_lockOrBurnRevertsOnExistingPool() public { + uint256 amount = 100_000e18; + + // prank router.gho.transferFrom(user, EXISTING_TOKEN_POOL, amount) + deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); + + vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); + vm.expectRevert(abi.encodeWithSelector(BridgeLimitExceeded.selector, 0)); + EXISTING_TOKEN_POOL.lockOrBurn( + alice, + abi.encode(alice), + amount, + ARB_CHAIN_SELECTOR, + new bytes(0) + ); + } + + // on-ramp via new pool + function test_lockOrBurnSucceedsOnNewPool() public { + uint256 amount = 100_000e18; + + // prank router.gho.transferFrom(user, NEW_TOKEN_POOL, amount) + // we don't override NEW_TOKEN_POOL balance here & instead transfer because we want + // to check the invariant GHO.balanceOf(tokenPool) == tokenPool.currentBridgedAmount() + deal(address(GHO), address(alice), amount); + vm.prank(alice); + GHO.transfer(address(NEW_TOKEN_POOL), amount); + + uint256 bridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Locked(address(ON_RAMP), amount); + + vm.prank(address(ON_RAMP)); + NEW_TOKEN_POOL.lockOrBurn( + IPool_CCIP.LockOrBurnInV1({ + receiver: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + originalSender: alice, + amount: amount, + localToken: address(GHO) + }) + ); + + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), NEW_TOKEN_POOL.getCurrentBridgedAmount()); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount + amount); + } + + // existing pool can no longer off ramp + function test_releaseOrMintRevertsOnExistingPool() public { + uint256 amount = 100_000e18; + + assertEq(GHO.balanceOf(address(EXISTING_TOKEN_POOL)), 0); + + vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); + // underflow expected at tokenPool.GHO.transfer() since existing + // token pool does not hold any gho + vm.expectRevert(stdError.arithmeticError); + EXISTING_TOKEN_POOL.releaseOrMint( + abi.encode(alice), + alice, + amount, + ARB_CHAIN_SELECTOR, + new bytes(0) + ); + } + + // off-ramp messages sent from new eth token pool (v1.5.1) + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth() public { + uint256 amount = 100_000e18; + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + uint256 bridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Released(address(OFF_RAMP), alice, amount); + + vm.prank(address(OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ARB)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), tokenPoolBalance - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount - amount); + } + + // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth() public { + uint256 amount = 100_000e18; + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + uint256 bridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Released(address(OFF_RAMP), alice, amount); + + vm.prank(address(OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(ARB_PROXY_POOL)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), tokenPoolBalance - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount - amount); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol b/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol index b7e6f2f1b..e853cd8cc 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/utils/CCIPUtils.sol @@ -17,6 +17,11 @@ library CCIPUtils { bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256('EVM2EVMMessageHashV2'); bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + enum PoolVersion { + V1_5_0, + V1_5_1 + } + struct SourceTokenData { bytes sourcePoolAddress; bytes destTokenAddress; @@ -30,7 +35,9 @@ library CCIPUtils { uint64 sourceChainSelector; uint256 feeTokenAmount; address originalSender; + address sourceToken; address destinationToken; + PoolVersion poolVersion; } function generateMessage( @@ -83,7 +90,9 @@ library CCIPUtils { onRamp.getPoolBySourceToken(destChainSelector, params.message.tokenAmounts[i].token) ), destTokenAddress: abi.encode(params.destinationToken), - extraData: '', + extraData: params.poolVersion == PoolVersion.V1_5_1 + ? abi.encode(getTokenDecimals(params.sourceToken)) + : new bytes(0), destGasAmount: getDestGasAmount(onRamp, params.message.tokenAmounts[i].token) }) ); @@ -154,4 +163,10 @@ library CCIPUtils { ? config.destGasOverhead : onRamp.getDynamicConfig().defaultTokenDestGasOverhead; } + + function getTokenDecimals(address token) internal view returns (uint8) { + (bool success, bytes memory data) = token.staticcall(abi.encodeWithSignature('decimals()')); + require(success, 'CCIPUtils: failed to get token decimals'); + return abi.decode(data, (uint8)); + } } diff --git a/src/interfaces/IGhoToken.sol b/src/interfaces/IGhoToken.sol index 2c78aeebd..96fc71c24 100644 --- a/src/interfaces/IGhoToken.sol +++ b/src/interfaces/IGhoToken.sol @@ -1,14 +1,51 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface IGhoToken { +import {IERC20} from 'forge-std/interfaces/IERC20.sol'; + +interface IGhoToken is IERC20 { struct Facilitator { uint128 bucketCapacity; uint128 bucketLevel; string label; } - function balanceOf(address user) external returns (uint256); + /** + * @notice Mints the requested amount of tokens to the account address. + * @dev Only facilitators with enough bucket capacity available can mint. + * @dev The bucket level is increased upon minting. + * @param account The address receiving the GHO tokens + * @param amount The amount to mint + */ + function mint(address account, uint256 amount) external; + + /** + * @notice Burns the requested amount of tokens from the account address. + * @dev Only active facilitators (bucket level > 0) can burn. + * @dev The bucket level is decreased upon burning. + * @param amount The amount to burn + */ + function burn(uint256 amount) external; + + /** + * @notice Add the facilitator passed with the parameters to the facilitators list. + * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function + * @param facilitatorAddress The address of the facilitator to add + * @param facilitatorLabel A human readable identifier for the facilitator + * @param bucketCapacity The upward limit of GHO can be minted by the facilitator + */ + function addFacilitator( + address facilitatorAddress, + string calldata facilitatorLabel, + uint128 bucketCapacity + ) external; + + /** + * @notice Remove the facilitator from the facilitators list. + * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function + * @param facilitatorAddress The address of the facilitator to remove + */ + function removeFacilitator(address facilitatorAddress) external; /** * @notice Set the bucket capacity of the facilitator. diff --git a/src/interfaces/ccip/IEVM2EVMOffRamp.sol b/src/interfaces/ccip/IEVM2EVMOffRamp.sol index b900be64b..d9d132f5f 100644 --- a/src/interfaces/ccip/IEVM2EVMOffRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOffRamp.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.0; -import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; +import {IInternal} from './IInternal.sol'; +import {ITypeAndVersion} from './ITypeAndVersion.sol'; -interface IEVM2EVMOffRamp { +interface IEVM2EVMOffRamp_1_2 is ITypeAndVersion { /// @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 +18,18 @@ interface IEVM2EVMOffRamp { bytes[] memory offchainTokenData ) external; } + +interface IEVM2EVMOffRamp_1_5 is ITypeAndVersion { + /// @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..13affbc6e --- /dev/null +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {IInternal} from './IInternal.sol'; +import {ITypeAndVersion} from './ITypeAndVersion.sol'; + +interface IEVM2EVMOnRamp is ITypeAndVersion { + 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); + + /// @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); + + /// @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); +} 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/IRateLimiter.sol b/src/interfaces/ccip/IRateLimiter.sol new file mode 100644 index 000000000..d4cb9ffa4 --- /dev/null +++ b/src/interfaces/ccip/IRateLimiter.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT + +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 + 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..7792d09cc 100644 --- a/src/interfaces/ccip/IRouter.sol +++ b/src/interfaces/ccip/IRouter.sol @@ -2,26 +2,42 @@ pragma solidity ^0.8.0; -import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IClient} from './IClient.sol'; +import {ITypeAndVersion} from './ITypeAndVersion.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. +interface IRouter is ITypeAndVersion { + 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..6cdaf7bf4 --- /dev/null +++ b/src/interfaces/ccip/ITokenAdminRegistry.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +interface ITokenAdminRegistry { + struct TokenConfig { + address administrator; + address pendingAdministrator; + address tokenPool; + } + + error AlreadyRegistered(address token); + error InvalidTokenPoolToken(address token); + error OnlyAdministrator(address sender, address token); + error OnlyPendingAdministrator(address sender, address token); + error OnlyRegistryModuleOrOwner(address sender); + error ZeroAddress(); + + event AdministratorTransferRequested( + address indexed token, + address indexed currentAdmin, + address indexed newAdmin + ); + event AdministratorTransferred(address indexed token, address indexed newAdmin); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event PoolSet(address indexed token, address indexed previousPool, address indexed newPool); + event RegistryModuleAdded(address module); + event RegistryModuleRemoved(address indexed module); + + function acceptAdminRole(address localToken) external; + function acceptOwnership() external; + function addRegistryModule(address module) external; + function getAllConfiguredTokens( + uint64 startIndex, + uint64 maxCount + ) external view returns (address[] memory tokens); + function getPool(address token) external view returns (address); + function getPools(address[] memory tokens) external view returns (address[] memory); + function getTokenConfig(address token) external view returns (TokenConfig memory); + function isAdministrator(address localToken, address administrator) external view returns (bool); + function isRegistryModule(address module) external view returns (bool); + function owner() external view returns (address); + function proposeAdministrator(address localToken, address administrator) external; + function removeRegistryModule(address module) external; + function setPool(address localToken, address pool) external; + function transferAdminRole(address localToken, address newAdmin) external; + function transferOwnership(address to) external; + function typeAndVersion() external view returns (string memory); +} 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); +} diff --git a/src/interfaces/ccip/tokenPool/IPool.sol b/src/interfaces/ccip/tokenPool/IPool.sol new file mode 100644 index 000000000..f85af151e --- /dev/null +++ b/src/interfaces/ccip/tokenPool/IPool.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IPool { + struct LockOrBurnInV1 { + bytes receiver; + uint64 remoteChainSelector; + address originalSender; + uint256 amount; + address localToken; + } + + struct LockOrBurnOutV1 { + bytes destTokenAddress; + bytes destPoolData; + } + + struct ReleaseOrMintInV1 { + bytes originalSender; + uint64 remoteChainSelector; + address receiver; + uint256 amount; + address localToken; + bytes sourcePoolAddress; + bytes sourcePoolData; + bytes offchainTokenData; + } + + struct ReleaseOrMintOutV1 { + uint256 destinationAmount; + } +} diff --git a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol new file mode 100644 index 000000000..b1d773a5e --- /dev/null +++ b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IRateLimiter} from '../IRateLimiter.sol'; +import {IPool} from './IPool.sol'; + +interface IUpgradeableBurnMintTokenPool_1_4 { + struct ChainUpdate { + uint64 remoteChainSelector; + bool allowed; + IRateLimiter.Config outboundIRateLimiterConfig; + IRateLimiter.Config inboundIRateLimiterConfig; + } + + 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 IRateLimiterConfig); + 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 outboundIRateLimiterConfig, + IRateLimiter.Config inboundIRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + IRateLimiter.Config outboundIRateLimiterConfig, + IRateLimiter.Config inboundIRateLimiterConfig + ); + 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 applyChainUpdates(ChainUpdate[] memory chains) external; + function getAllowList() external view returns (address[] memory); + function getAllowListEnabled() external view returns (bool); + function getArmProxy() external view returns (address armProxy); + function getCurrentInboundIRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getCurrentOutboundIRateLimiterState( + 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 setChainIRateLimiterConfig( + 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); +} + +interface IUpgradeableBurnMintTokenPool_1_5_1 { + struct ChainUpdate { + uint64 remoteChainSelector; + bytes[] remotePoolAddresses; + bytes remoteTokenAddress; + IRateLimiter.Config outboundRateLimiterConfig; + IRateLimiter.Config inboundRateLimiterConfig; + } + + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error AllowListNotEnabled(); + error BucketOverfilled(); + error CallerIsNotARampOnRouter(address caller); + error CannotTransferToSelf(); + error ChainAlreadyExists(uint64 chainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error CursedByRMN(); + error DisabledNonZeroRateLimit(IRateLimiter.Config config); + error InvalidDecimalArgs(uint8 expected, uint8 actual); + error InvalidRateLimitRate(IRateLimiter.Config IRateLimiterConfig); + error InvalidRemoteChainDecimals(bytes sourcePoolData); + error InvalidRemotePoolForChain(uint64 remoteChainSelector, bytes remotePoolAddress); + error InvalidSourcePoolAddress(bytes sourcePoolAddress); + error InvalidToken(address token); + error MustBeProposedOwner(); + error NonExistentChain(uint64 remoteChainSelector); + error OnlyCallableByOwner(); + error OverflowDetected(uint8 remoteDecimals, uint8 localDecimals, uint256 remoteAmount); + error OwnerCannotBeZero(); + error PoolAlreadyAdded(uint64 remoteChainSelector, bytes remotePoolAddress); + 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, + bytes remoteToken, + IRateLimiter.Config outboundIRateLimiterConfig, + IRateLimiter.Config inboundIRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + IRateLimiter.Config outboundIRateLimiterConfig, + IRateLimiter.Config inboundIRateLimiterConfig + ); + 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 RateLimitAdminSet(address rateLimitAdmin); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event RemotePoolAdded(uint64 indexed remoteChainSelector, bytes remotePoolAddress); + event RemotePoolRemoved(uint64 indexed remoteChainSelector, bytes remotePoolAddress); + event RouterUpdated(address oldRouter, address newRouter); + event TokensConsumed(uint256 tokens); + + function transferLiquidity(address to, uint256 amount) external; + function acceptOwnership() external; + function addRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; + function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; + function applyChainUpdates( + uint64[] memory remoteChainSelectorsToRemove, + ChainUpdate[] memory chainsToAdd + ) external; + function getAllowList() external view returns (address[] memory); + function getAllowListEnabled() external view returns (bool); + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (IRateLimiter.TokenBucket memory); + function getRateLimitAdmin() external view returns (address); + function getRemotePools(uint64 remoteChainSelector) external view returns (bytes[] memory); + function getRemoteToken(uint64 remoteChainSelector) external view returns (bytes memory); + function getRmnProxy() external view returns (address rmnProxy); + function getRouter() external view returns (address router); + function getSupportedChains() external view returns (uint64[] memory); + function getToken() external view returns (address token); + function getTokenDecimals() external view returns (uint8 decimals); + function initialize(address owner_, address[] memory allowlist, address router) external; + function isRemotePool( + uint64 remoteChainSelector, + bytes memory remotePoolAddress + ) external view returns (bool); + function isSupportedChain(uint64 remoteChainSelector) external view returns (bool); + function isSupportedToken(address token) external view returns (bool); + function lockOrBurn( + IPool.LockOrBurnInV1 memory lockOrBurnIn + ) external returns (IPool.LockOrBurnOutV1 memory); + function owner() external view returns (address); + function releaseOrMint( + IPool.ReleaseOrMintInV1 memory releaseOrMintIn + ) external returns (IPool.ReleaseOrMintOutV1 memory); + function removeRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; + function setChainIRateLimiterConfig( + uint64 remoteChainSelector, + IRateLimiter.Config memory outboundConfig, + IRateLimiter.Config memory inboundConfig + ) 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/tokenPool/IUpgradeableLockReleaseTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol new file mode 100644 index 000000000..873611b80 --- /dev/null +++ b/src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IRateLimiter} from '../IRateLimiter.sol'; +import {IPool} from './IPool.sol'; + +interface IUpgradeableLockReleaseTokenPool_1_4 { + struct ChainUpdate { + uint64 remoteChainSelector; + bool allowed; + IRateLimiter.Config outboundIRateLimiterConfig; + IRateLimiter.Config inboundIRateLimiterConfig; + } + + 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 IRateLimiterConfig); + 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(); + + 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); + + function acceptOwnership() external; + function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; + function applyChainUpdates(ChainUpdate[] memory chains) 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); + 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; + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + IRateLimiter.Config memory outboundConfig, + IRateLimiter.Config memory inboundConfig + ) external; + function setProxyPool(address proxyPool) external; + function setRateLimitAdmin(address rateLimitAdmin) external; + 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; +} + +interface IUpgradeableLockReleaseTokenPool_1_5_1 { + struct ChainUpdate { + uint64 remoteChainSelector; + bytes[] remotePoolAddresses; + bytes remoteTokenAddress; + IRateLimiter.Config outboundRateLimiterConfig; + IRateLimiter.Config inboundRateLimiterConfig; + } + + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error AllowListNotEnabled(); + error BridgeLimitExceeded(uint256 bridgeLimit); + error BucketOverfilled(); + error CallerIsNotARampOnRouter(address caller); + error CannotTransferToSelf(); + error ChainAlreadyExists(uint64 chainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error CursedByRMN(); + error DisabledNonZeroRateLimit(IRateLimiter.Config config); + error InsufficientLiquidity(); + error InvalidDecimalArgs(uint8 expected, uint8 actual); + error InvalidRateLimitRate(IRateLimiter.Config IRateLimiterConfig); + error InvalidRemoteChainDecimals(bytes sourcePoolData); + error InvalidRemotePoolForChain(uint64 remoteChainSelector, bytes remotePoolAddress); + error InvalidSourcePoolAddress(bytes sourcePoolAddress); + error InvalidToken(address token); + error LiquidityNotAccepted(); + error MustBeProposedOwner(); + error NonExistentChain(uint64 remoteChainSelector); + error NotEnoughBridgedAmount(); + error OnlyCallableByOwner(); + error OverflowDetected(uint8 remoteDecimals, uint8 localDecimals, uint256 remoteAmount); + error OwnerCannotBeZero(); + error PoolAlreadyAdded(uint64 remoteChainSelector, bytes remotePoolAddress); + 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 BridgeLimitAdminUpdated(address indexed oldAdmin, address indexed newAdmin); + event BridgeLimitUpdated(uint256 oldBridgeLimit, uint256 newBridgeLimit); + event Burned(address indexed sender, uint256 amount); + event ChainAdded( + uint64 remoteChainSelector, + bytes remoteToken, + 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 LiquidityTransferred(address indexed from, uint256 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 RateLimitAdminSet(address rateLimitAdmin); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event RemotePoolAdded(uint64 indexed remoteChainSelector, bytes remotePoolAddress); + event RemotePoolRemoved(uint64 indexed remoteChainSelector, bytes remotePoolAddress); + event RouterUpdated(address oldRouter, address newRouter); + event TokensConsumed(uint256 tokens); + + function acceptOwnership() external; + function addRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; + function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; + function applyChainUpdates( + uint64[] memory remoteChainSelectorsToRemove, + ChainUpdate[] memory chainsToAdd + ) external; + function canAcceptLiquidity() external view returns (bool); + function getAllowList() external view returns (address[] memory); + function getAllowListEnabled() external view returns (bool); + 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 getRateLimitAdmin() external view returns (address); + function getRebalancer() external view returns (address); + function getRemotePools(uint64 remoteChainSelector) external view returns (bytes[] memory); + function getRemoteToken(uint64 remoteChainSelector) external view returns (bytes memory); + function getRmnProxy() external view returns (address rmnProxy); + function getRouter() external view returns (address router); + function getSupportedChains() external view returns (uint64[] memory); + function getToken() external view returns (address token); + function getTokenDecimals() external view returns (uint8 decimals); + function initialize( + address owner_, + address[] memory allowlist, + address router, + uint256 bridgeLimit + ) external; + function isRemotePool( + uint64 remoteChainSelector, + bytes memory remotePoolAddress + ) external view returns (bool); + function isSupportedChain(uint64 remoteChainSelector) external view returns (bool); + function isSupportedToken(address token) external view returns (bool); + function lockOrBurn( + IPool.LockOrBurnInV1 memory lockOrBurnIn + ) external returns (IPool.LockOrBurnOutV1 memory); + function owner() external view returns (address); + function provideLiquidity(uint256 amount) external; + function releaseOrMint( + IPool.ReleaseOrMintInV1 memory releaseOrMintIn + ) external returns (IPool.ReleaseOrMintOutV1 memory); + function removeRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; + function setBridgeLimit(uint256 newBridgeLimit) external; + function setBridgeLimitAdmin(address bridgeLimitAdmin) external; + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + IRateLimiter.Config memory outboundConfig, + IRateLimiter.Config memory inboundConfig + ) external; + function setRateLimitAdmin(address rateLimitAdmin) external; + function setRebalancer(address rebalancer) external; + function setRouter(address newRouter) external; + function supportsInterface(bytes4 interfaceId) external pure returns (bool); + function transferLiquidity(address from, uint256 amount) external; + function transferOwnership(address to) external; + function typeAndVersion() external view returns (string memory); + function withdrawLiquidity(uint256 amount) external; +} From b7017e374438abf4221f787bbf761e3f6c6a9ee6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 00:57:29 +0530 Subject: [PATCH 012/123] tmp: fix ci for aave org, to rm for bdg --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f186f228..a68532181 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,9 @@ 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 }}" with: mode: "CHANGED" From ca059fd9049821c3e7c7c46c17c346e7f6c69b79 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 01:06:23 +0530 Subject: [PATCH 013/123] tmp: add 1.4 pool with withdrawLiq flattended, to be removed once impl is deployed --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 38 +- ...eableBurnMintTokenPool_1_4_WithdrawLiq.sol | 1818 +++++++++++++++++ 2 files changed, 1837 insertions(+), 19 deletions(-) create mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 218894346..8b4405496 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -11,12 +11,7 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; - -contract Burner { - function burn(address token, uint256 amount) external { - IGhoToken(token).burn(amount); - } -} +import {UpgradeableBurnMintTokenPool} from './utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol'; /** * @title GHO CCIP 1.5.1 Upgrade @@ -67,20 +62,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { ); GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); - NEW_TOKEN_POOL.transferLiquidity(address(EXISTING_TOKEN_POOL), bucketLevel); + NEW_TOKEN_POOL.transferLiquidity(address(EXISTING_TOKEN_POOL), bucketLevel); // mintTo - address existingTokenPoolImpl = PROXY_ADMIN.getProxyImplementation( - TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))) - ); - PROXY_ADMIN.upgrade( - TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), - address(new Burner()) - ); - Burner(address(EXISTING_TOKEN_POOL)).burn(address(GHO), bucketLevel); - PROXY_ADMIN.upgrade( - TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), - existingTokenPoolImpl - ); + _upgradeExistingTokenPool(); + UpgradeableBurnMintTokenPool(address(EXISTING_TOKEN_POOL)).withdrawLiquidity(bucketLevel); // burn GHO.removeFacilitator(address(EXISTING_TOKEN_POOL)); } @@ -114,4 +99,19 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // register new pool TOKEN_ADMIN_REGISTRY.setPool(address(GHO), address(NEW_TOKEN_POOL)); } + + function _upgradeExistingTokenPool() internal { + address newImplementation = address( + new UpgradeableBurnMintTokenPool( + EXISTING_TOKEN_POOL.getToken(), + EXISTING_TOKEN_POOL.getArmProxy(), + EXISTING_TOKEN_POOL.getAllowListEnabled() + ) + ); + + PROXY_ADMIN.upgrade( + TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), + newImplementation + ); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol new file mode 100644 index 000000000..63ca6da9b --- /dev/null +++ b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol @@ -0,0 +1,1818 @@ +/// Flattened UpgradeableBurnMintTokenPool from https://github.com/aave/ccip/pull/21 +/// Will be removed once PR is merged and contract implementation is deployed + +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +// foundry-lib/solidity-utils/src/contracts/oz-common/Address.sol + +// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) +// From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/8b778fa20d6d76340c5fac1ed66c80273f05b95a + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev Returns true if `account` is a contract. + * + * [IMPORTANT] + * ==== + * It is unsafe to assume that an address for which this function returns + * false is an externally-owned account (EOA) and not a contract. + * + * Among others, `isContract` will return false for the following + * types of addresses: + * + * - an externally-owned account + * - a contract in construction + * - an address where a contract will be created + * - an address where a contract lived, but was destroyed + * ==== + * + * [IMPORTANT] + * ==== + * You shouldn't rely on `isContract` to protect against flash loan attacks! + * + * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets + * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract + * constructor. + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies on extcodesize/address.code.length, which returns 0 + // for contracts in construction, since the code is only stored at the end + // of the constructor execution. + + return account.code.length > 0; + } + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, 'Address: insufficient balance'); + + (bool success, ) = recipient.call{value: amount}(''); + require(success, 'Address: unable to send value, recipient may have reverted'); + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain `call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason, it is bubbled up by this + * function (like regular Solidity function calls). + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, 'Address: low-level call failed'); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with + * `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, value, 'Address: low-level call with value failed'); + } + + /** + * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but + * with `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { + require(address(this).balance >= value, 'Address: insufficient balance for call'); + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data + ) internal view returns (bytes memory) { + return functionStaticCall(target, data, 'Address: low-level static call failed'); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data, + string memory errorMessage + ) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { + return functionDelegateCall(target, data, 'Address: low-level delegate call failed'); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + (bool success, bytes memory returndata) = target.delegatecall(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling + * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. + * + * _Available since v4.8._ + */ + function verifyCallResultFromTarget( + address target, + bool success, + bytes memory returndata, + string memory errorMessage + ) internal view returns (bytes memory) { + if (success) { + if (returndata.length == 0) { + // only check isContract if the call was successful and the return data is empty + // otherwise we already know that it was a contract + require(isContract(target), 'Address: call to non-contract'); + } + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + /** + * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the + * revert reason or using the provided one. + * + * _Available since v4.3._ + */ + function verifyCallResult( + bool success, + bytes memory returndata, + string memory errorMessage + ) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + function _revert(bytes memory returndata, string memory errorMessage) private pure { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + /// @solidity memory-safe-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } +} + +// src/v0.8/ccip/interfaces/IARM.sol + +/// @notice This interface contains the only ARM-related functions that might be used on-chain by other CCIP contracts. +interface IARM { + /// @notice A Merkle root tagged with the address of the commit store contract it is destined for. + struct TaggedRoot { + address commitStore; + bytes32 root; + } + + /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. + function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool); + + /// @notice When the ARM is "cursed", CCIP pauses until the curse is lifted. + function isCursed() external view returns (bool); +} + +// src/v0.8/ccip/libraries/Client.sol + +// End consumer library. +library Client { + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct EVMTokenAmount { + address token; // token address on the local chain. + uint256 amount; // Amount of tokens. + } + + struct Any2EVMMessage { + bytes32 messageId; // MessageId corresponding to ccipSend on source. + uint64 sourceChainSelector; // Source chain selector. + bytes sender; // abi.decode(sender) if coming from an EVM chain. + bytes data; // payload sent in original message. + EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. + } + + // If extraArgs is empty bytes, the default is 200k gas limit. + struct EVM2AnyMessage { + bytes receiver; // abi.encode(receiver address) for dest EVM chains + bytes data; // Data payload + EVMTokenAmount[] tokenAmounts; // Token transfers + address feeToken; // Address of feeToken. address(0) means you will send msg.value. + bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1) + } + + // bytes4(keccak256("CCIP EVMExtraArgsV1")); + bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + struct EVMExtraArgsV1 { + uint256 gasLimit; + } + + function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { + return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); + } +} + +// src/v0.8/ccip/libraries/RateLimiter.sol + +/// @notice Implements Token Bucket rate limiting. +/// @dev uint128 is safe for rate limiter state. +/// For USD value rate limiting, it can adequately store USD value in 18 decimals. +/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most +/// a supply of uint128.max tokens, and it will therefore not overflow the bucket. +/// In exceptional scenarios where tokens consumed may be larger than uint128, +/// e.g. compromised issuer, an enabled RateLimiter will check and revert. +library RateLimiter { + error BucketOverfilled(); + error OnlyCallableByAdminOrOwner(); + error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); + error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error InvalidRatelimitRate(Config rateLimiterConfig); + error DisabledNonZeroRateLimit(Config config); + error RateLimitMustBeDisabled(); + + event TokensConsumed(uint256 tokens); + event ConfigChanged(Config config); + + 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 + uint128 rate; // ───────╯ Specifies the rate of the rate limiter + } + + /// @notice _consume removes the given tokens from the pool, lowering the + /// rate tokens allowed to be consumed for subsequent calls. + /// @param requestTokens The total tokens to be consumed from the bucket. + /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity. + /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket + /// @dev emits removal of requestTokens if requestTokens is > 0 + function _consume( + TokenBucket storage s_bucket, + uint256 requestTokens, + address tokenAddress + ) internal { + // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage + if (!s_bucket.isEnabled || requestTokens == 0) { + return; + } + + uint256 tokens = s_bucket.tokens; + uint256 capacity = s_bucket.capacity; + uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; + + if (timeDiff != 0) { + if (tokens > capacity) revert BucketOverfilled(); + + // Refill tokens when arriving at a new block time + tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate); + + s_bucket.lastUpdated = uint32(block.timestamp); + } + + if (capacity < requestTokens) { + // Token address 0 indicates consuming aggregate value rate limit capacity. + if (tokenAddress == address(0)) + revert AggregateValueMaxCapacityExceeded(capacity, requestTokens); + revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress); + } + if (tokens < requestTokens) { + uint256 rate = s_bucket.rate; + // Wait required until the bucket is refilled enough to accept this value, round up to next higher second + // Consume is not guaranteed to succeed after wait time passes if there is competing traffic. + // This acts as a lower bound of wait time. + uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate; + + if (tokenAddress == address(0)) + revert AggregateValueRateLimitReached(minWaitInSeconds, tokens); + revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress); + } + tokens -= requestTokens; + + // Downcast is safe here, as tokens is not larger than capacity + s_bucket.tokens = uint128(tokens); + emit TokensConsumed(requestTokens); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function _currentTokenBucketState( + TokenBucket memory bucket + ) internal view returns (TokenBucket memory) { + // We update the bucket to reflect the status at the exact time of the + // call. This means we might need to refill a part of the bucket based + // on the time that has passed since the last update. + bucket.tokens = uint128( + _calculateRefill( + bucket.capacity, + bucket.tokens, + block.timestamp - bucket.lastUpdated, + bucket.rate + ) + ); + bucket.lastUpdated = uint32(block.timestamp); + return bucket; + } + + /// @notice Sets the rate limited config. + /// @param s_bucket The token bucket + /// @param config The new config + function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal { + // First update the bucket to make sure the proper rate is used for all the time + // up until the config change. + uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; + if (timeDiff != 0) { + s_bucket.tokens = uint128( + _calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate) + ); + + s_bucket.lastUpdated = uint32(block.timestamp); + } + + s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens)); + s_bucket.isEnabled = config.isEnabled; + s_bucket.capacity = config.capacity; + s_bucket.rate = config.rate; + + emit ConfigChanged(config); + } + + /// @notice Validates the token bucket config + function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure { + if (config.isEnabled) { + if (config.rate >= config.capacity || config.rate == 0) { + revert InvalidRatelimitRate(config); + } + if (mustBeDisabled) { + revert RateLimitMustBeDisabled(); + } + } else { + if (config.rate != 0 || config.capacity != 0) { + revert DisabledNonZeroRateLimit(config); + } + } + } + + /// @notice Calculate refilled tokens + /// @param capacity bucket capacity + /// @param tokens current bucket tokens + /// @param timeDiff block time difference since last refill + /// @param rate bucket refill rate + /// @return the value of tokens after refill + function _calculateRefill( + uint256 capacity, + uint256 tokens, + uint256 timeDiff, + uint256 rate + ) private pure returns (uint256) { + return _min(capacity, tokens + timeDiff * rate); + } + + /// @notice Return the smallest of two integers + /// @param a first int + /// @param b second int + /// @return smallest + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} + +// src/v0.8/shared/interfaces/IOwnable.sol + +interface IOwnable { + function owner() external returns (address); + + function transferOwnership(address recipient) external; + + function acceptOwnership() external; +} + +// src/v0.8/shared/interfaces/ITypeAndVersion.sol + +interface ITypeAndVersion { + function typeAndVersion() external pure returns (string memory); +} + +// src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol + +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + +/** + * @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); +} + +// src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol + +// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) + +/** + * @dev Interface of the ERC165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[EIP]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} + +// src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol + +// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position of the value in the `values` array, plus 1 because index 0 + // means a value is not in the set. + mapping(bytes32 => uint256) _indexes; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._indexes[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We read and store the value's index to prevent multiple reads from the same storage slot + uint256 valueIndex = set._indexes[value]; + + if (valueIndex != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 toDeleteIndex = valueIndex - 1; + uint256 lastIndex = set._values.length - 1; + + if (lastIndex != toDeleteIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the last value to the index where the value to delete is + set._values[toDeleteIndex] = lastValue; + // Update the index for the moved value + set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the index for the deleted slot + delete set._indexes[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._indexes[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} + +// foundry-lib/solidity-utils/src/contracts/transparent-proxy/Initializable.sol + +/** + * @dev OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) + * From https://github.com/OpenZeppelin/openzeppelin-contracts/tree/8b778fa20d6d76340c5fac1ed66c80273f05b95a + * + * BGD Labs adaptations: + * - Added a constructor disabling initialization for implementation contracts + * - Linting + */ + +/** + * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed + * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an + * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer + * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. + * + * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be + * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in + * case an upgrade adds a module that needs to be initialized. + * + * For example: + * + * [.hljs-theme-light.nopadding] + * ``` + * contract MyToken is ERC20Upgradeable { + * function initialize() initializer public { + * __ERC20_init("MyToken", "MTK"); + * } + * } + * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { + * function initializeV2() reinitializer(2) public { + * __ERC20Permit_init("MyToken"); + * } + * } + * ``` + * + * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as + * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. + * + * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure + * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. + * + * [CAUTION] + * ==== + * Avoid leaving a contract uninitialized. + * + * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation + * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke + * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: + * + * [.hljs-theme-light.nopadding] + * ``` + * /// @custom:oz-upgrades-unsafe-allow constructor + * constructor() { + * _disableInitializers(); + * } + * ``` + * ==== + */ +abstract contract Initializable { + /** + * @dev Indicates that the contract has been initialized. + * @custom:oz-retyped-from bool + */ + uint8 private _initialized; + + /** + * @dev Indicates that the contract is in the process of being initialized. + */ + bool private _initializing; + + /** + * @dev Triggered when the contract has been initialized or reinitialized. + */ + event Initialized(uint8 version); + + /** + * @dev OPINIONATED. Generally is not a good practise to allow initialization of implementations + */ + constructor() { + _disableInitializers(); + } + + /** + * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, + * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. + */ + modifier initializer() { + bool isTopLevelCall = !_initializing; + require( + (isTopLevelCall && _initialized < 1) || + (!Address.isContract(address(this)) && _initialized == 1), + 'Initializable: contract is already initialized' + ); + _initialized = 1; + if (isTopLevelCall) { + _initializing = true; + } + _; + if (isTopLevelCall) { + _initializing = false; + emit Initialized(1); + } + } + + /** + * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the + * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be + * used to initialize parent contracts. + * + * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original + * initialization step. This is essential to configure modules that are added through upgrades and that require + * initialization. + * + * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in + * a contract, executing them in the right order is up to the developer or operator. + */ + modifier reinitializer(uint8 version) { + require( + !_initializing && _initialized < version, + 'Initializable: contract is already initialized' + ); + _initialized = version; + _initializing = true; + _; + _initializing = false; + emit Initialized(version); + } + + /** + * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the + * {initializer} and {reinitializer} modifiers, directly or indirectly. + */ + modifier onlyInitializing() { + require(_initializing, 'Initializable: contract is not initializing'); + _; + } + + /** + * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. + * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized + * to any version. It is recommended to use this to lock implementation contracts that are designed to be called + * through proxies. + */ + function _disableInitializers() internal virtual { + require(!_initializing, 'Initializable: contract is initializing'); + if (_initialized < type(uint8).max) { + _initialized = type(uint8).max; + emit Initialized(type(uint8).max); + } + } +} + +// src/v0.8/ccip/interfaces/IRouter.sol + +interface IRouter { + error OnlyOffRamp(); + + /// @notice Route the message to its intended receiver contract. + /// @param message Client.Any2EVMMessage struct. + /// @param gasForCallExactCheck of params for exec + /// @param gasLimit set of params for exec + /// @param receiver set of params for exec + /// @dev if the receiver is a contracts that signals support for CCIP execution through EIP-165. + /// the contract is called. If not, only tokens are transferred. + /// @return success A boolean value indicating whether the ccip message was received without errors. + /// @return retBytes A bytes array containing return data form CCIP receiver. + /// @return gasUsed the gas used by the external customer call. Does not include any overhead. + function routeMessage( + Client.Any2EVMMessage calldata message, + uint16 gasForCallExactCheck, + uint256 gasLimit, + address receiver + ) external returns (bool success, bytes memory retBytes, uint256 gasUsed); + + /// @notice Returns the configured onramp for a specific destination chain. + /// @param destChainSelector The destination chain Id to get the onRamp for. + /// @return onRampAddress The address of the onRamp. + function getOnRamp(uint64 destChainSelector) external view returns (address onRampAddress); + + /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. + /// @param sourceChainSelector The source chain selector to check. + /// @param offRamp The address of the offRamp to check. + function isOffRamp( + uint64 sourceChainSelector, + address offRamp + ) external view returns (bool isOffRamp); +} + +// src/v0.8/ccip/interfaces/pools/IPool.sol + +// Shared public interface for multiple pool types. +// Each pool type handles a different child token model (lock/unlock, mint/burn.) +interface IPool { + /// @notice Lock tokens into the pool or burn the tokens. + /// @param originalSender Original sender of the tokens. + /// @param receiver Receiver of the tokens on destination chain. + /// @param amount Amount to lock or burn. + /// @param remoteChainSelector Destination chain Id. + /// @param extraArgs Additional data passed in by sender for lockOrBurn processing + /// in custom pools on source chain. + /// @return retData Optional field that contains bytes. Unused for now but already + /// implemented to allow future upgrades while preserving the interface. + function lockOrBurn( + address originalSender, + bytes calldata receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes calldata extraArgs + ) external returns (bytes memory); + + /// @notice Releases or mints tokens to the receiver address. + /// @param originalSender Original sender of the tokens. + /// @param receiver Receiver of the tokens. + /// @param amount Amount to release or mint. + /// @param remoteChainSelector Source chain Id. + /// @param extraData Additional data supplied offchain for releaseOrMint processing in + /// custom pools on dest chain. This could be an attestation that was retrieved through a + /// third party API. + /// @dev offchainData can come from any untrusted source. + function releaseOrMint( + bytes memory originalSender, + address receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes memory extraData + ) external; + + /// @notice Gets the IERC20 token that this pool can lock or burn. + /// @return token The IERC20 token representation. + function getToken() external view returns (IERC20 token); +} + +// src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol + +/// @title The ConfirmedOwner contract +/// @notice A contract with helpers for basic contract ownership. +contract ConfirmedOwnerWithProposal is IOwnable { + address private s_owner; + address private s_pendingOwner; + + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + + constructor(address newOwner, address pendingOwner) { + // solhint-disable-next-line custom-errors + require(newOwner != address(0), 'Cannot set owner to zero'); + + s_owner = newOwner; + if (pendingOwner != address(0)) { + _transferOwnership(pendingOwner); + } + } + + /// @notice Allows an owner to begin transferring ownership to a new address. + function transferOwnership(address to) public override onlyOwner { + _transferOwnership(to); + } + + /// @notice Allows an ownership transfer to be completed by the recipient. + function acceptOwnership() external override { + // solhint-disable-next-line custom-errors + require(msg.sender == s_pendingOwner, 'Must be proposed owner'); + + address oldOwner = s_owner; + s_owner = msg.sender; + s_pendingOwner = address(0); + + emit OwnershipTransferred(oldOwner, msg.sender); + } + + /// @notice Get the current owner + function owner() public view override returns (address) { + return s_owner; + } + + /// @notice validate, transfer ownership, and emit relevant events + function _transferOwnership(address to) internal { + s_pendingOwner = to; + + emit OwnershipTransferRequested(s_owner, to); + } + + /// @notice validate access + function _validateOwnership() internal view { + // solhint-disable-next-line custom-errors + require(msg.sender == s_owner, 'Only callable by owner'); + } + + /// @notice Reverts if called by anyone other than the contract owner. + modifier onlyOwner() { + _validateOwnership(); + _; + } +} + +// src/v0.8/shared/token/ERC20/IBurnMintERC20.sol + +interface IBurnMintERC20 is IERC20 { + /// @notice Mints new tokens for a given address. + /// @param account The address to mint the new tokens to. + /// @param amount The number of tokens to be minted. + /// @dev this function increases the total supply. + function mint(address account, uint256 amount) external; + + /// @notice Burns tokens from the sender. + /// @param amount The number of tokens to be burned. + /// @dev this function decreases the total supply. + function burn(uint256 amount) external; + + /// @notice Burns tokens from a given address.. + /// @param account The address to burn tokens from. + /// @param amount The number of tokens to be burned. + /// @dev this function decreases the total supply. + function burn(address account, uint256 amount) external; + + /// @notice Burns tokens from a given address.. + /// @param account The address to burn tokens from. + /// @param amount The number of tokens to be burned. + /// @dev this function decreases the total supply. + function burnFrom(address account, uint256 amount) external; +} + +// src/v0.8/shared/access/ConfirmedOwner.sol + +/// @title The ConfirmedOwner contract +/// @notice A contract with helpers for basic contract ownership. +contract ConfirmedOwner is ConfirmedOwnerWithProposal { + constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} +} + +// src/v0.8/shared/access/OwnerIsCreator.sol + +/// @title The OwnerIsCreator contract +/// @notice A contract with helpers for basic contract ownership. +contract OwnerIsCreator is ConfirmedOwner { + constructor() ConfirmedOwner(msg.sender) {} +} + +// src/v0.8/ccip/pools/GHO/UpgradeableTokenPool.sol + +/// @title UpgradeableTokenPool +/// @author Aave Labs +/// @notice Upgradeable version of Chainlink's CCIP TokenPool +/// @dev Contract adaptations: +/// - Setters & Getters for new ProxyPool (to support 1.5 CCIP migration on the existing 1.4 Pool) +/// - Modify `onlyOnRamp` & `onlyOffRamp` modifier to accept transactions from ProxyPool +abstract contract UpgradeableTokenPool is IPool, OwnerIsCreator, IERC165 { + using EnumerableSet for EnumerableSet.AddressSet; + using EnumerableSet for EnumerableSet.UintSet; + using RateLimiter for RateLimiter.TokenBucket; + + error CallerIsNotARampOnRouter(address caller); + error ZeroAddressNotAllowed(); + error SenderNotAllowed(address sender); + error AllowListNotEnabled(); + error NonExistentChain(uint64 remoteChainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error BadARMSignal(); + error ChainAlreadyExists(uint64 chainSelector); + + 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); + event ChainAdded( + uint64 remoteChainSelector, + RateLimiter.Config outboundRateLimiterConfig, + RateLimiter.Config inboundRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + RateLimiter.Config outboundRateLimiterConfig, + RateLimiter.Config inboundRateLimiterConfig + ); + event ChainRemoved(uint64 remoteChainSelector); + event AllowListAdd(address sender); + event AllowListRemove(address sender); + event RouterUpdated(address oldRouter, address newRouter); + + struct ChainUpdate { + uint64 remoteChainSelector; // ──╮ Remote chain selector + bool allowed; // ────────────────╯ Whether the chain is allowed + RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain + RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain + } + + /// @dev The storage slot for Proxy Pool address, act as an on ramp "wrapper" post ccip 1.5 migration. + /// @dev This was added to continue support for 1.2 onRamp during 1.5 migration, and is stored + /// this way to avoid storage collision. + // bytes32(uint256(keccak256("ccip.pools.GHO.UpgradeableTokenPool.proxyPool")) - 1) + bytes32 internal constant PROXY_POOL_SLOT = + 0x75bb68f1b335d4dab6963140ecff58281174ef4362bb85a8593ab9379f24fae2; + + /// @dev The bridgeable token that is managed by this pool. + IERC20 internal immutable i_token; + /// @dev The address of the arm proxy + address internal immutable i_armProxy; + /// @dev The immutable flag that indicates if the pool is access-controlled. + bool internal immutable i_allowlistEnabled; + /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. + /// Only takes effect if i_allowlistEnabled is true. + /// This can be used to ensure only token-issuer specified addresses can + /// move tokens. + EnumerableSet.AddressSet internal s_allowList; + /// @dev The address of the router + IRouter internal s_router; + /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to + /// be able to quickly determine (without parsing logs) who can access the pool. + /// @dev The chain selectors are in uin256 format because of the EnumerableSet implementation. + EnumerableSet.UintSet internal s_remoteChainSelectors; + /// @dev Outbound rate limits. Corresponds to the inbound rate limit for the pool + /// on the remote chain. + mapping(uint64 => RateLimiter.TokenBucket) internal s_outboundRateLimits; + /// @dev Inbound rate limits. This allows per destination chain + /// token issuer specified rate limiting (e.g. issuers may trust chains to varying + /// degrees and prefer different limits) + mapping(uint64 => RateLimiter.TokenBucket) internal s_inboundRateLimits; + + constructor(IERC20 token, address armProxy, bool allowlistEnabled) { + if (address(token) == address(0)) revert ZeroAddressNotAllowed(); + i_token = token; + i_armProxy = armProxy; + i_allowlistEnabled = allowlistEnabled; + } + + /// @notice Get ARM proxy address + /// @return armProxy Address of arm proxy + function getArmProxy() public view returns (address armProxy) { + return i_armProxy; + } + + /// @inheritdoc IPool + function getToken() public view override returns (IERC20 token) { + return i_token; + } + + /// @notice Gets the pool's Router + /// @return router The pool's Router + function getRouter() public view returns (address router) { + return address(s_router); + } + + /// @notice Sets the pool's Router + /// @param newRouter The new Router + function setRouter(address newRouter) public onlyOwner { + if (newRouter == address(0)) revert ZeroAddressNotAllowed(); + address oldRouter = address(s_router); + s_router = IRouter(newRouter); + + emit RouterUpdated(oldRouter, newRouter); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return interfaceId == type(IPool).interfaceId || interfaceId == type(IERC165).interfaceId; + } + + // ================================================================ + // │ Chain permissions │ + // ================================================================ + + /// @notice Checks whether a chain selector is permissioned on this contract. + /// @return true if the given chain selector is a permissioned remote chain. + function isSupportedChain(uint64 remoteChainSelector) public view returns (bool) { + return s_remoteChainSelectors.contains(remoteChainSelector); + } + + /// @notice Get list of allowed chains + /// @return list of chains. + function getSupportedChains() public view returns (uint64[] memory) { + uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); + uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); + for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { + chainSelectors[i] = uint64(uint256ChainSelectors[i]); + } + + return chainSelectors; + } + + /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains + /// need to be allowed on the Router to interact with this pool. + /// @dev Only callable by the owner + /// @param chains A list of chains and their new permission status & rate limits. Rate limits + /// are only used when the chain is being added through `allowed` being true. + function applyChainUpdates(ChainUpdate[] calldata chains) external virtual onlyOwner { + for (uint256 i = 0; i < chains.length; ++i) { + ChainUpdate memory update = chains[i]; + RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); + RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); + + if (update.allowed) { + // If the chain already exists, revert + if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { + revert ChainAlreadyExists(update.remoteChainSelector); + } + + s_outboundRateLimits[update.remoteChainSelector] = RateLimiter.TokenBucket({ + rate: update.outboundRateLimiterConfig.rate, + capacity: update.outboundRateLimiterConfig.capacity, + tokens: update.outboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.outboundRateLimiterConfig.isEnabled + }); + + s_inboundRateLimits[update.remoteChainSelector] = RateLimiter.TokenBucket({ + rate: update.inboundRateLimiterConfig.rate, + capacity: update.inboundRateLimiterConfig.capacity, + tokens: update.inboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.inboundRateLimiterConfig.isEnabled + }); + emit ChainAdded( + update.remoteChainSelector, + update.outboundRateLimiterConfig, + update.inboundRateLimiterConfig + ); + } else { + // If the chain doesn't exist, revert + if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { + revert NonExistentChain(update.remoteChainSelector); + } + + delete s_inboundRateLimits[update.remoteChainSelector]; + delete s_outboundRateLimits[update.remoteChainSelector]; + emit ChainRemoved(update.remoteChainSelector); + } + } + } + + // ================================================================ + // │ Rate limiting │ + // ================================================================ + + /// @notice Consumes outbound rate limiting capacity in this pool + function _consumeOutboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { + s_outboundRateLimits[remoteChainSelector]._consume(amount, address(i_token)); + } + + /// @notice Consumes inbound rate limiting capacity in this pool + function _consumeInboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { + s_inboundRateLimits[remoteChainSelector]._consume(amount, address(i_token)); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { + return s_outboundRateLimits[remoteChainSelector]._currentTokenBucketState(); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { + return s_inboundRateLimits[remoteChainSelector]._currentTokenBucketState(); + } + + /// @notice Sets the chain rate limiter config. + /// @param remoteChainSelector The remote chain selector for which the rate limits apply. + /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. + /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + RateLimiter.Config memory outboundConfig, + RateLimiter.Config memory inboundConfig + ) external virtual onlyOwner { + _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); + } + + function _setRateLimitConfig( + uint64 remoteChainSelector, + RateLimiter.Config memory outboundConfig, + RateLimiter.Config memory inboundConfig + ) internal { + if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); + RateLimiter._validateTokenBucketConfig(outboundConfig, false); + s_outboundRateLimits[remoteChainSelector]._setTokenBucketConfig(outboundConfig); + RateLimiter._validateTokenBucketConfig(inboundConfig, false); + s_inboundRateLimits[remoteChainSelector]._setTokenBucketConfig(inboundConfig); + emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); + } + + // ================================================================ + // │ Access │ + // ================================================================ + + /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender + /// is a permissioned onRamp for the given chain on the Router. + modifier onlyOnRamp(uint64 remoteChainSelector) { + if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); + if (!(msg.sender == getProxyPool() || msg.sender == s_router.getOnRamp(remoteChainSelector))) { + revert CallerIsNotARampOnRouter(msg.sender); + } + _; + } + + /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender + /// is a permissioned offRamp for the given chain on the Router. + modifier onlyOffRamp(uint64 remoteChainSelector) { + if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); + if (!(msg.sender == getProxyPool() || s_router.isOffRamp(remoteChainSelector, msg.sender))) { + revert CallerIsNotARampOnRouter(msg.sender); + } + _; + } + + // ================================================================ + // │ Allowlist │ + // ================================================================ + + modifier checkAllowList(address sender) { + if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); + _; + } + + /// @notice Gets whether the allowList functionality is enabled. + /// @return true is enabled, false if not. + function getAllowListEnabled() external view returns (bool) { + return i_allowlistEnabled; + } + + /// @notice Gets the allowed addresses. + /// @return The allowed addresses. + function getAllowList() external view returns (address[] memory) { + return s_allowList.values(); + } + + /// @notice Apply updates to the allow list. + /// @param removes The addresses to be removed. + /// @param adds The addresses to be added. + /// @dev allowListing will be removed before public launch + function applyAllowListUpdates( + address[] calldata removes, + address[] calldata adds + ) external onlyOwner { + _applyAllowListUpdates(removes, adds); + } + + /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. + function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { + if (!i_allowlistEnabled) revert AllowListNotEnabled(); + + for (uint256 i = 0; i < removes.length; ++i) { + address toRemove = removes[i]; + if (s_allowList.remove(toRemove)) { + emit AllowListRemove(toRemove); + } + } + for (uint256 i = 0; i < adds.length; ++i) { + address toAdd = adds[i]; + if (toAdd == address(0)) { + continue; + } + if (s_allowList.add(toAdd)) { + emit AllowListAdd(toAdd); + } + } + } + + /// @notice Ensure that there is no active curse. + modifier whenHealthy() { + if (IARM(i_armProxy).isCursed()) revert BadARMSignal(); + _; + } + + /// @notice Getter for proxy pool address. + /// @return proxyPool The proxy pool address. + function getProxyPool() public view returns (address proxyPool) { + assembly ('memory-safe') { + proxyPool := shr(96, shl(96, sload(PROXY_POOL_SLOT))) + } + } + + /// @notice Setter for proxy pool address, only callable by the DAO. + /// @param proxyPool The address of the proxy pool. + function setProxyPool(address proxyPool) external onlyOwner { + if (proxyPool == address(0)) revert ZeroAddressNotAllowed(); + assembly ('memory-safe') { + sstore(PROXY_POOL_SLOT, proxyPool) + } + } +} + +// src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPoolAbstract.sol + +abstract contract UpgradeableBurnMintTokenPoolAbstract is UpgradeableTokenPool { + /// @notice Contains the specific burn call for a pool. + /// @dev overriding this method allows us to create pools with different burn signatures + /// without duplicating the underlying logic. + function _burn(uint256 amount) internal virtual; + + /// @notice Burn the token in the pool + /// @param amount Amount to burn + /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised + /// we're able to stop token movement via ARM. + function lockOrBurn( + address originalSender, + bytes calldata, + uint256 amount, + uint64 remoteChainSelector, + bytes calldata + ) + external + virtual + override + onlyOnRamp(remoteChainSelector) + checkAllowList(originalSender) + whenHealthy + returns (bytes memory) + { + _consumeOutboundRateLimit(remoteChainSelector, amount); + _burn(amount); + emit Burned(msg.sender, amount); + return ''; + } + + /// @notice Mint tokens from the pool to the recipient + /// @param receiver Recipient address + /// @param amount Amount to mint + /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised + /// we're able to stop token movement via ARM. + function releaseOrMint( + bytes memory, + address receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes memory + ) external virtual override whenHealthy onlyOffRamp(remoteChainSelector) { + _consumeInboundRateLimit(remoteChainSelector, amount); + IBurnMintERC20(address(i_token)).mint(receiver, amount); + emit Minted(msg.sender, receiver, amount); + } +} + +// src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol + +/// @title UpgradeableBurnMintTokenPool +/// @author Aave Labs +/// @notice Upgradeable version of Chainlink's CCIP BurnMintTokenPool +/// @dev Contract adaptations: +/// - Implementation of Initializable to allow upgrades +/// - Move of allowlist and router definition to initialization stage +/// - Inclusion of rate limit admin who may configure rate limits in addition to owner +/// - Modifications from inherited contract (see contract for more details): +/// - UpgradeableTokenPool: Modify `onlyOnRamp` & `onlyOffRamp` modifier to accept transactions from ProxyPool +contract UpgradeableBurnMintTokenPool is + Initializable, + UpgradeableBurnMintTokenPoolAbstract, + ITypeAndVersion +{ + error Unauthorized(address caller); + + string public constant override typeAndVersion = 'BurnMintTokenPool 1.4.0'; + + /// @notice The address of the rate limiter admin. + /// @dev Can be address(0) if none is configured. + address internal s_rateLimitAdmin; + + /// @dev Constructor + /// @param token The bridgeable token that is managed by this pool. + /// @param armProxy The address of the arm proxy + /// @param allowlistEnabled True if pool is set to access-controlled mode, false otherwise + constructor( + address token, + address armProxy, + bool allowlistEnabled + ) UpgradeableTokenPool(IBurnMintERC20(token), armProxy, allowlistEnabled) {} + + /// @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 + ) public virtual initializer { + if (owner == address(0) || router == address(0)) revert ZeroAddressNotAllowed(); + _transferOwnership(owner); + + s_router = IRouter(router); + + // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. + if (i_allowlistEnabled) { + _applyAllowListUpdates(new address[](0), allowlist); + } + } + + /// @notice Sets the rate limiter admin address. + /// @dev Only callable by the owner. + /// @param rateLimitAdmin The new rate limiter admin address. + function setRateLimitAdmin(address rateLimitAdmin) external onlyOwner { + s_rateLimitAdmin = rateLimitAdmin; + } + + /// @notice Gets the rate limiter admin address. + function getRateLimitAdmin() external view returns (address) { + return s_rateLimitAdmin; + } + + /// @notice Sets the chain rate limiter config. + /// @dev Only callable by the owner or the rate limiter admin. NOTE: overwrites the normal + /// onlyAdmin check in the base implementation to also allow the rate limiter admin. + /// @param remoteChainSelector The remote chain selector for which the rate limits apply. + /// @param outboundConfig The new outbound rate limiter config. + /// @param inboundConfig The new inbound rate limiter config. + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + RateLimiter.Config memory outboundConfig, + RateLimiter.Config memory inboundConfig + ) external override { + if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); + + _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); + } + + /// @notice This function allows the owner to burn `amount` of the pool's token. This is + /// expected to be called while migrating liquidity to another pool and offboarding this + /// facilitator. + /// @dev New token pool should mint and transfer liquidity to this pool (since it does not + /// hold tokens any point in point, only mints/burns) which can be burnt and hence will reset + /// the facilitator bucket level GHO. This is needed to migrate facilitators, by offboarding + /// this token pool subsequently. + /// @param amount The amount of tokens to burn. + function withdrawLiquidity(uint256 amount) external onlyOwner { + IBurnMintERC20(address(i_token)).burn(amount); + } + + /// @inheritdoc UpgradeableBurnMintTokenPoolAbstract + function _burn(uint256 amount) internal virtual override { + IBurnMintERC20(address(i_token)).burn(amount); + } +} From 4b8049ab40cd158c9b3304ce77f104245c5234d4 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:33:23 +0530 Subject: [PATCH 014/123] tmp: fix ci for aave org --- .github/workflows/test.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a68532181..977839ab4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,6 +33,16 @@ jobs: 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 f8180d9d5ecfa9997ddae27e4925c35a43712ab1 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:36:51 +0530 Subject: [PATCH 015/123] revert: test ci secrets updates --- .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 e57070dbd3358db582b6d916850d2006ac9745c2 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 03:26:13 +0530 Subject: [PATCH 016/123] chore: fix comments --- ...bitrum_GHOCCIP151Upgrade_20241209_after.md | 15 +++++++++++++ lib/ccip | 2 +- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 2 +- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 19 +++++++--------- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 2 +- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 22 +++++++++---------- 6 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md diff --git a/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md b/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md new file mode 100644 index 000000000..4d686addb --- /dev/null +++ b/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md @@ -0,0 +1,15 @@ +## Emodes changed + +### EMode: Stablecoins(id: 1) + + + +### EMode: ETH correlated(id: 2) + + + +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/lib/ccip b/lib/ccip index 5f84e6eaa..8fea66bb8 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit 5f84e6eaa1393ce19c50c3dfbbc026a77d1998c7 +Subproject commit 8fea66bb81dbcb6d4c2332c1d45b68765766f3e2 diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 8b4405496..ffcee61a2 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -28,7 +28,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://arbiscan.io/address/0xF168B83598516A532a85995b52504a2Fa058C068 IUpgradeableBurnMintTokenPool_1_4 public constant EXISTING_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; -> not using since this will be overwritten with new token pool address + IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index deb7bf5f0..6bf01691f 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -83,17 +83,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { _validateConstants(); } - /** - * @dev executes the generic test suite including e2e and config snapshots - */ - function skip_test_defaultProposalExecution() public { - defaultTest( - 'AaveV3Arbitrum_GHOCCIP151Upgrade_20241209', - AaveV3Arbitrum.POOL, - address(proposal) - ); - } - function _deployNewTokenPoolArb() private returns (address) { IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( MiscArbitrum.GHO_CCIP_TOKEN_POOL @@ -237,6 +226,14 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is super.setUp(); } + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Arbitrum_GHOCCIP151Upgrade_20241209', + AaveV3Arbitrum.POOL, + address(proposal) + ); + } + function test_tokenPoolOwnershipTransfer() public { assertFalse( TOKEN_ADMIN_REGISTRY.isAdministrator(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 1385fb8b4..445726ba7 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -23,7 +23,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://etherscan.io/address/0x5756880B6a1EAba0175227bf02a7E87c1e02B28C IUpgradeableLockReleaseTokenPool_1_4 public constant EXISTING_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; -> not using since this will be overwritten with new token pool address + IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 342a80551..fc2fbb97d 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -89,17 +89,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { _validateConstants(); } - /** - * @dev executes the generic test suite including e2e and config snapshots - */ - function skip_test_defaultProposalExecution() public { - defaultTest( - 'AaveV3Ethereum_GHOCCIP151Upgrade_20241209', - AaveV3Ethereum.POOL, - address(proposal) - ); - } - function _deployNewTokenPoolEth() private returns (address) { IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( MiscEthereum.GHO_CCIP_TOKEN_POOL @@ -254,6 +243,17 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is super.setUp(); } + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_GHOCCIP151Upgrade_20241209', + AaveV3Ethereum.POOL, + address(proposal) + ); + } + function test_tokenPoolOwnershipTransfer() public { assertFalse( TOKEN_ADMIN_REGISTRY.isAdministrator(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1) From c0e439beb7a90d8ddebe555f1e0389200a57c8b4 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 03:44:08 +0530 Subject: [PATCH 017/123] chore: rm duplicate check --- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 1 - ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 20 +++++++++---------- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 1 - 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 6bf01691f..0c632fe20 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -293,7 +293,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(staticParams, _getStaticParams(address(NEW_TOKEN_POOL))); assertEq(dynamicParams, _getDynamicParams(address(NEW_TOKEN_POOL))); - assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 2); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(ETH_PROXY_POOL))); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ETH))); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index e1d42aa6c..38f29674a 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -172,27 +172,31 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(l1.proposal.NEW_REMOTE_POOL_ARB()), address(l2.newTokenPool)); if (upgraded) { - assertEq(l1.c.tokenAdminRegistry.getPool(MiscEthereum.GHO_TOKEN), address(l1.newTokenPool)); + assertEq(l1.c.tokenAdminRegistry.getPool(address(l1.c.token)), address(l1.newTokenPool)); assertEq(l1.c.token.balanceOf(address(l1.existingTokenPool)), 0); // ! todo upgrade existing pool to reset bridgedAmount? not necessary since we reset bridgeLimit // assertEq(l1.existingTokenPool.getCurrentBridgedAmount(), 0); + assertEq(l1.existingTokenPool.getBridgeLimit(), 0); assertGt(l1.c.token.balanceOf(address(l1.newTokenPool)), 0); assertGt(l1.newTokenPool.getCurrentBridgedAmount(), 0); + assertGt(l1.newTokenPool.getBridgeLimit(), 0); } else { - assertEq(l1.c.tokenAdminRegistry.getPool(MiscEthereum.GHO_TOKEN), l1.c.proxyPool); + assertEq(l1.c.tokenAdminRegistry.getPool(address(l1.c.token)), l1.c.proxyPool); assertGt(l1.c.token.balanceOf(address(l1.existingTokenPool)), 0); assertGt(l1.existingTokenPool.getCurrentBridgedAmount(), 0); + assertGt(l1.existingTokenPool.getBridgeLimit(), 0); assertEq(l1.c.token.balanceOf(address(l1.newTokenPool)), 0); assertEq(l1.newTokenPool.getCurrentBridgedAmount(), 0); + assertGt(l1.newTokenPool.getBridgeLimit(), 0); } vm.selectFork(l2.c.forkId); assertEq(l2.c.chainSelector, 4949039107694359620); - assertEq(address(l2.c.token), 0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33); + assertEq(address(l2.c.token), AaveV3ArbitrumAssets.GHO_UNDERLYING); assertEq(l2.c.router.typeAndVersion(), 'Router 1.2.0'); assertEq(l2.c.EVM2EVMOnRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(l2.c.EVM2EVMOffRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); @@ -212,17 +216,11 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(l2.proposal.NEW_REMOTE_POOL_ETH()), address(l1.newTokenPool)); if (upgraded) { - assertEq( - l2.c.tokenAdminRegistry.getPool(AaveV3ArbitrumAssets.GHO_UNDERLYING), - address(l2.newTokenPool) - ); + assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), address(l2.newTokenPool)); assertEq(bytes(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label).length, 0); assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP v1.5.1 TokenPool'); } else { - assertEq( - l2.c.tokenAdminRegistry.getPool(AaveV3ArbitrumAssets.GHO_UNDERLYING), - l2.c.proxyPool - ); + assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), l2.c.proxyPool); assertEq(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label, 'CCIP TokenPool'); assertEq(bytes(l2.c.token.getFacilitator(address(l2.newTokenPool)).label).length, 0); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index fc2fbb97d..a7f929b4e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -309,7 +309,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(staticParams, _getStaticParams(address(NEW_TOKEN_POOL))); assertEq(dynamicParams, _getDynamicParams(address(NEW_TOKEN_POOL))); - assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); assertEq(NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR).length, 2); assertTrue(NEW_TOKEN_POOL.isRemotePool(ARB_CHAIN_SELECTOR, abi.encode(ARB_PROXY_POOL))); assertTrue(NEW_TOKEN_POOL.isRemotePool(ARB_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ARB))); From 01431e15af4431fcb7f0829b5945f509f102ccfd Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 12 Dec 2024 19:21:31 +0530 Subject: [PATCH 018/123] chore: reorder imports, pending automation --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 13 +++++++------ .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 6 +++--- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 6 +++--- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 7 +++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index ffcee61a2..d9110312b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -1,16 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; -import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; + import {UpgradeableBurnMintTokenPool} from './utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol'; /** diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 0c632fe20..4f4b15c40 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -3,7 +3,8 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.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'; @@ -12,8 +13,7 @@ import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; -import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; -import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 38f29674a..a68745049 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -3,6 +3,8 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.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'; @@ -10,8 +12,6 @@ import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; -import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 445726ba7..0da88b41e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; -import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; -import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** * @title GHO CCIP 1.5.1 Upgrade diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index a7f929b4e..96b3b9c7b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -3,7 +3,8 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.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'; @@ -12,8 +13,7 @@ import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; -import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; -import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; @@ -21,7 +21,6 @@ import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; From 0ea5517a5aea627effa21438e530bccd8fe5e50e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:31:32 +0530 Subject: [PATCH 019/123] chore: import order --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index d9110312b..90adc4b82 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -6,8 +6,8 @@ import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin. import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; -import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; From 1a30ddae65c468668786c439a4bda99c893874d8 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:22:40 +0530 Subject: [PATCH 020/123] chore: imports order, re-frame comment --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 2 +- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 90adc4b82..b41168a33 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -4,10 +4,10 @@ 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 {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; -import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 4f4b15c40..6627f2c83 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -363,7 +363,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_lockOrBurnRevertsOnExistingPool() public { uint256 amount = 100_000e18; - // prank router.gho.transferFrom(user, EXISTING_TOKEN_POOL, amount) + // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); @@ -382,7 +382,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_lockOrBurnSucceedsOnNewPool() public { uint256 amount = 100_000e18; - // prank router.gho.transferFrom(user, NEW_TOKEN_POOL, amount) + // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(NEW_TOKEN_POOL), amount); uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index a68745049..0070a9bac 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -19,12 +19,12 @@ import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; -import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; - import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; + import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 96b3b9c7b..a73504b7c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -384,7 +384,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_lockOrBurnRevertsOnExistingPool() public { uint256 amount = 100_000e18; - // prank router.gho.transferFrom(user, EXISTING_TOKEN_POOL, amount) + // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); @@ -402,7 +402,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_lockOrBurnSucceedsOnNewPool() public { uint256 amount = 100_000e18; - // prank router.gho.transferFrom(user, NEW_TOKEN_POOL, amount) + // router pulls tokens from the user & sends to the token pool during onRamps // we don't override NEW_TOKEN_POOL balance here & instead transfer because we want // to check the invariant GHO.balanceOf(tokenPool) == tokenPool.currentBridgedAmount() deal(address(GHO), address(alice), amount); From bbc3daa039362f810e8a3738ff362ce60635128d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:39:14 +0530 Subject: [PATCH 021/123] feat: update to latest spec: naming changes, setCurrentBridgedAmount, resolve existing pool bridgeAmount comment --- lib/ccip | 2 +- ...veV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 5 +++-- ...veV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 7 +++---- ...deableBurnMintTokenPool_1_4_WithdrawLiq.sol | 18 +++++++++--------- .../IUpgradeableBurnMintTokenPool.sol | 2 +- .../IUpgradeableLockReleaseTokenPool.sol | 1 + 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/lib/ccip b/lib/ccip index 8fea66bb8..3667707a5 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit 8fea66bb81dbcb6d4c2332c1d45b68765766f3e2 +Subproject commit 3667707a5e3a0de9d1cff62f6cdac8dc14f20ed2 diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index b41168a33..9b37b5666 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -63,10 +63,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { ); GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); - NEW_TOKEN_POOL.transferLiquidity(address(EXISTING_TOKEN_POOL), bucketLevel); // mintTo + NEW_TOKEN_POOL.mintAndTransferLiquidity(address(EXISTING_TOKEN_POOL), bucketLevel); // mintTo _upgradeExistingTokenPool(); - UpgradeableBurnMintTokenPool(address(EXISTING_TOKEN_POOL)).withdrawLiquidity(bucketLevel); // burn + UpgradeableBurnMintTokenPool(address(EXISTING_TOKEN_POOL)).burnLiquidity(bucketLevel); // burn GHO.removeFacilitator(address(EXISTING_TOKEN_POOL)); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 0070a9bac..9f6c94622 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -175,8 +175,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(l1.c.tokenAdminRegistry.getPool(address(l1.c.token)), address(l1.newTokenPool)); assertEq(l1.c.token.balanceOf(address(l1.existingTokenPool)), 0); - // ! todo upgrade existing pool to reset bridgedAmount? not necessary since we reset bridgeLimit - // assertEq(l1.existingTokenPool.getCurrentBridgedAmount(), 0); + // we are not resetting currentBridgedAmount on the existing pool, the pool is deprecated by + // resetting the bridge limit + assertNotEq(l1.existingTokenPool.getCurrentBridgedAmount(), 0); assertEq(l1.existingTokenPool.getBridgeLimit(), 0); assertGt(l1.c.token.balanceOf(address(l1.newTokenPool)), 0); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 0da88b41e..ea494bfd0 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -49,10 +49,9 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { function _migrateLiquidity() internal { EXISTING_TOKEN_POOL.setRebalancer(address(NEW_TOKEN_POOL)); - NEW_TOKEN_POOL.transferLiquidity({ - from: address(EXISTING_TOKEN_POOL), - amount: EXISTING_TOKEN_POOL.getCurrentBridgedAmount() - }); + uint256 bridgeAmount = EXISTING_TOKEN_POOL.getCurrentBridgedAmount(); + NEW_TOKEN_POOL.transferLiquidity(address(EXISTING_TOKEN_POOL), bridgeAmount); + NEW_TOKEN_POOL.setCurrentBridgedAmount(bridgeAmount); // disable existing pool EXISTING_TOKEN_POOL.setBridgeLimit(0); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol index 63ca6da9b..17fd351c5 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol @@ -1,4 +1,4 @@ -/// Flattened UpgradeableBurnMintTokenPool from https://github.com/aave/ccip/pull/21 +/// Flattened UpgradeableBurnMintTokenPool from https://github.com/aave/ccip/pull/21 (last commit 0c15ea8abfff732f921329b19ebe8f2c81d0b692) /// Will be removed once PR is merged and contract implementation is deployed // SPDX-License-Identifier: BUSL-1.1 @@ -1800,15 +1800,15 @@ contract UpgradeableBurnMintTokenPool is } /// @notice This function allows the owner to burn `amount` of the pool's token. This is - /// expected to be called while migrating liquidity to another pool and offboarding this - /// facilitator. - /// @dev New token pool should mint and transfer liquidity to this pool (since it does not - /// hold tokens any point in point, only mints/burns) which can be burnt and hence will reset - /// the facilitator bucket level GHO. This is needed to migrate facilitators, by offboarding - /// this token pool subsequently. + /// expected to be called while migrating facilitators by offboarding this facilitator in + /// favor of a new token pool. + /// @dev New token pool should mint and transfer liquidity to this pool (since this pool + /// does not hold tokens at any point in time) which can be burnt and hence will reduce + /// the facilitator bucket level on GHO. The naming convention is inspired from that in + /// LockRelease type token pools for the sake of consistency. /// @param amount The amount of tokens to burn. - function withdrawLiquidity(uint256 amount) external onlyOwner { - IBurnMintERC20(address(i_token)).burn(amount); + function burnLiquidity(uint256 amount) external onlyOwner { + _burn(amount); } /// @inheritdoc UpgradeableBurnMintTokenPoolAbstract diff --git a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol index b1d773a5e..0ab51b5b7 100644 --- a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol +++ b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol @@ -167,7 +167,6 @@ interface IUpgradeableBurnMintTokenPool_1_5_1 { event RouterUpdated(address oldRouter, address newRouter); event TokensConsumed(uint256 tokens); - function transferLiquidity(address to, uint256 amount) external; function acceptOwnership() external; function addRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; @@ -201,6 +200,7 @@ interface IUpgradeableBurnMintTokenPool_1_5_1 { function lockOrBurn( IPool.LockOrBurnInV1 memory lockOrBurnIn ) external returns (IPool.LockOrBurnOutV1 memory); + function mintAndTransferLiquidity(address to, uint256 amount) external; function owner() external view returns (address); function releaseOrMint( IPool.ReleaseOrMintInV1 memory releaseOrMintIn diff --git a/src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol index 873611b80..96a3dbe0f 100644 --- a/src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol +++ b/src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol @@ -250,6 +250,7 @@ interface IUpgradeableLockReleaseTokenPool_1_5_1 { ) external returns (IPool.ReleaseOrMintOutV1 memory); function removeRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; function setBridgeLimit(uint256 newBridgeLimit) external; + function setCurrentBridgedAmount(uint256 newBridgedAmount) external; function setBridgeLimitAdmin(address bridgeLimitAdmin) external; function setChainRateLimiterConfig( uint64 remoteChainSelector, From af3b44d59d88552dae5d89bd2f64914458906b02 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 19 Dec 2024 19:15:53 +0530 Subject: [PATCH 022/123] chore: consistency, cleanup comment based on latest approach --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 8 ++++++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 11 ++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 6627f2c83..6f4bdc55d 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -54,7 +54,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address internal constant GHO_CCIP_STEWARD = 0xb329CEFF2c362F315900d245eC88afd24C4949D5; IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_4(MiscArbitrum.GHO_CCIP_TOKEN_POOL); // will be changed to 1.5.1 after AIP execution + IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 9f6c94622..3b4916963 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -93,7 +93,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(newTokenPoolEth, newTokenPoolArb); - l1.existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4(MiscEthereum.GHO_CCIP_TOKEN_POOL); + l1.existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( + 0x5756880B6a1EAba0175227bf02a7E87c1e02B28C + ); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP l1.newTokenPool = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); l1.c.router = IRouter(l1.existingTokenPool.getRouter()); l2.c.chainSelector = l1.existingTokenPool.getSupportedChains()[0]; @@ -105,7 +107,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { vm.selectFork(l2.c.forkId); l2.proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(newTokenPoolArb, newTokenPoolEth); - l2.existingTokenPool = IUpgradeableBurnMintTokenPool_1_4(MiscArbitrum.GHO_CCIP_TOKEN_POOL); + l2.existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( + 0xF168B83598516A532a85995b52504a2Fa058C068 + ); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP l2.newTokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); l2.c.router = IRouter(l2.existingTokenPool.getRouter()); l1.c.chainSelector = l2.existingTokenPool.getSupportedChains()[0]; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index a73504b7c..f52447871 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -54,7 +54,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address internal constant GHO_CCIP_STEWARD = 0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4; IUpgradeableLockReleaseTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_4(MiscEthereum.GHO_CCIP_TOKEN_POOL); // will be changed to 1.5.1 after AIP execution + IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; @@ -290,11 +290,12 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(EXISTING_TOKEN_POOL.getRebalancer(), address(NEW_TOKEN_POOL)); assertEq(GHO.balanceOf(address(EXISTING_TOKEN_POOL)), 0); - // ! todo upgrade existing pool to reset bridgedAmount? not necessary since we reset bridgeLimit - // assertEq(EXISTING_TOKEN_POOL.getCurrentBridgedAmount(), 0); + // we do not reset bridgedAmount in the existing token pool, since bridge limit is reset + assertNotEq(EXISTING_TOKEN_POOL.getCurrentBridgedAmount(), 0); + assertEq(EXISTING_TOKEN_POOL.getBridgeLimit(), 0); - assertEq(balance, GHO.balanceOf(address(NEW_TOKEN_POOL))); - assertEq(bridgedAmount, NEW_TOKEN_POOL.getCurrentBridgedAmount()); + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), balance); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount); } function test_newTokenPoolSetupAndRegistration() public { From 688a9220f3323dc8df98e9fd0eb6aa95729fac23 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 23 Dec 2024 11:36:00 +0530 Subject: [PATCH 023/123] upd: `directMint` & `directBurn` --- lib/ccip | 2 +- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol | 5 +++-- .../ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/ccip b/lib/ccip index 3667707a5..a2e92d0e7 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit 3667707a5e3a0de9d1cff62f6cdac8dc14f20ed2 +Subproject commit a2e92d0e7fdae6f62f94ce90e1fac613fa04371d diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 9b37b5666..e5d83cfd4 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -63,10 +63,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { ); GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); - NEW_TOKEN_POOL.mintAndTransferLiquidity(address(EXISTING_TOKEN_POOL), bucketLevel); // mintTo + NEW_TOKEN_POOL.directMint(address(EXISTING_TOKEN_POOL), bucketLevel); // increase facilitator level _upgradeExistingTokenPool(); - UpgradeableBurnMintTokenPool(address(EXISTING_TOKEN_POOL)).burnLiquidity(bucketLevel); // burn + UpgradeableBurnMintTokenPool(address(EXISTING_TOKEN_POOL)).directBurn(bucketLevel); // decrease facilitator level GHO.removeFacilitator(address(EXISTING_TOKEN_POOL)); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol index 17fd351c5..41df48d61 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol @@ -1,4 +1,4 @@ -/// Flattened UpgradeableBurnMintTokenPool from https://github.com/aave/ccip/pull/21 (last commit 0c15ea8abfff732f921329b19ebe8f2c81d0b692) +/// Flattened UpgradeableBurnMintTokenPool from https://github.com/aave/ccip/pull/21 (commit e8bf9ad6e9967ce4f6a06d916d8ea4af8c07a595) /// Will be removed once PR is merged and contract implementation is deployed // SPDX-License-Identifier: BUSL-1.1 @@ -1724,6 +1724,7 @@ abstract contract UpgradeableBurnMintTokenPoolAbstract is UpgradeableTokenPool { /// - Implementation of Initializable to allow upgrades /// - Move of allowlist and router definition to initialization stage /// - Inclusion of rate limit admin who may configure rate limits in addition to owner +/// - Add GHO-Specific onlyOwner `directBurn` which burns liquidity & reduces facilitator level. /// - Modifications from inherited contract (see contract for more details): /// - UpgradeableTokenPool: Modify `onlyOnRamp` & `onlyOffRamp` modifier to accept transactions from ProxyPool contract UpgradeableBurnMintTokenPool is @@ -1807,7 +1808,7 @@ contract UpgradeableBurnMintTokenPool is /// the facilitator bucket level on GHO. The naming convention is inspired from that in /// LockRelease type token pools for the sake of consistency. /// @param amount The amount of tokens to burn. - function burnLiquidity(uint256 amount) external onlyOwner { + function directBurn(uint256 amount) external onlyOwner { _burn(amount); } diff --git a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol index 0ab51b5b7..10e966bd9 100644 --- a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol +++ b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol @@ -174,6 +174,7 @@ interface IUpgradeableBurnMintTokenPool_1_5_1 { uint64[] memory remoteChainSelectorsToRemove, ChainUpdate[] memory chainsToAdd ) external; + function directMint(address to, uint256 amount) external; function getAllowList() external view returns (address[] memory); function getAllowListEnabled() external view returns (bool); function getCurrentInboundRateLimiterState( @@ -200,7 +201,6 @@ interface IUpgradeableBurnMintTokenPool_1_5_1 { function lockOrBurn( IPool.LockOrBurnInV1 memory lockOrBurnIn ) external returns (IPool.LockOrBurnOutV1 memory); - function mintAndTransferLiquidity(address to, uint256 amount) external; function owner() external view returns (address); function releaseOrMint( IPool.ReleaseOrMintInV1 memory releaseOrMintIn From 478a7b56a22245890da21e9aaf9ed1c1f2db9f56 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:57:49 +0530 Subject: [PATCH 024/123] feat: add `gho-core` lib temporarily, fix interface --- .gitmodules | 3 +++ lib/gho-core | 1 + remappings.txt | 1 + .../ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol | 4 ++-- 4 files changed, 7 insertions(+), 2 deletions(-) create mode 160000 lib/gho-core diff --git a/.gitmodules b/.gitmodules index df7437c38..ad4e901de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ path = lib/ccip url = https://github.com/aave/ccip branch = feat/1_5_1_token_pool +[submodule "lib/gho-core"] + path = lib/gho-core + url = https://github.com/aave/gho-core diff --git a/lib/gho-core b/lib/gho-core new file mode 160000 index 000000000..0a6fbd4d4 --- /dev/null +++ b/lib/gho-core @@ -0,0 +1 @@ +Subproject commit 0a6fbd4d4167f6e0e777aec0ae12bf4f18b4b0a8 diff --git a/remappings.txt b/remappings.txt index 8f62b1c9f..1cd25c526 100644 --- a/remappings.txt +++ b/remappings.txt @@ -4,3 +4,4 @@ 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/ccip/contracts/src/v0.8/ccip +gho-core/=lib/gho-core/src/contracts diff --git a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol index 10e966bd9..6a7bbe0a7 100644 --- a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol +++ b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol @@ -88,7 +88,7 @@ interface IUpgradeableBurnMintTokenPool_1_4 { uint64 remoteChainSelector, bytes memory ) external; - function setChainIRateLimiterConfig( + function setChainRateLimiterConfig( uint64 remoteChainSelector, IRateLimiter.Config memory outboundConfig, IRateLimiter.Config memory inboundConfig @@ -206,7 +206,7 @@ interface IUpgradeableBurnMintTokenPool_1_5_1 { IPool.ReleaseOrMintInV1 memory releaseOrMintIn ) external returns (IPool.ReleaseOrMintOutV1 memory); function removeRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) external; - function setChainIRateLimiterConfig( + function setChainRateLimiterConfig( uint64 remoteChainSelector, IRateLimiter.Config memory outboundConfig, IRateLimiter.Config memory inboundConfig From 142d68b0f8e2eb2411976979f3a3a134adfdf2df Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:58:13 +0530 Subject: [PATCH 025/123] feat: new gho ccip steward --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 7 +- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 111 +++++++++++++-- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 36 ++++- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 9 +- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 131 ++++++++++++++++-- 5 files changed, 270 insertions(+), 24 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index e5d83cfd4..297261f48 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -32,6 +32,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; + address public immutable NEW_GHO_CCIP_STEWARD; + // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH address public immutable NEW_REMOTE_POOL_ETH; @@ -39,9 +41,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); - constructor(address newTokenPoolArb, address newTokenPoolEth) { + constructor(address newTokenPoolArb, address newTokenPoolEth, address newGhoCcipSteward) { NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); NEW_REMOTE_POOL_ETH = newTokenPoolEth; + NEW_GHO_CCIP_STEWARD = newGhoCcipSteward; } function execute() external { @@ -95,7 +98,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // setup new pool NEW_TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); - NEW_TOKEN_POOL.setRateLimitAdmin(EXISTING_TOKEN_POOL.getRateLimitAdmin()); // GhoCcipSteward + NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); // register new pool TOKEN_ADMIN_REGISTRY.setPool(address(GHO), address(NEW_TOKEN_POOL)); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 6f4bdc55d..d09338769 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -14,6 +14,7 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -24,6 +25,7 @@ import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; @@ -51,7 +53,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5 internal constant OFF_RAMP = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); - address internal constant GHO_CCIP_STEWARD = 0xb329CEFF2c362F315900d245eC88afd24C4949D5; + + IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = + IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); + IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP @@ -71,9 +76,11 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function setUp() public virtual { vm.createSelectFork(vm.rpcUrl('arbitrum'), 283036001); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); + NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ETH + NEW_REMOTE_POOL_ETH, + address(NEW_GHO_CCIP_STEWARD) ); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -112,6 +119,18 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ); } + function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { + return + address( + new GhoCcipSteward( + address(GHO), + newTokenPool, + EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL(), + false // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool + ) + ); + } + function _validateConstants() private view { assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); @@ -135,6 +154,13 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(ROUTER.getOnRamp(ETH_CHAIN_SELECTOR), address(ON_RAMP)); assertTrue(ROUTER.isOffRamp(ETH_CHAIN_SELECTOR, address(OFF_RAMP))); + + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); + + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); + assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *not present* in remote token pool, only on eth } function _getTokenMessage( @@ -182,8 +208,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { abi.encode( ghoTokenPool.owner(), ghoTokenPool.getSupportedChains(), - ghoTokenPool.getAllowListEnabled(), - ghoTokenPool.getRateLimitAdmin() + ghoTokenPool.getAllowListEnabled() ); } @@ -285,7 +310,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is function test_newTokenPoolSetupAndRegistration() public { bytes memory staticParams = _getStaticParams(address(EXISTING_TOKEN_POOL)); bytes memory dynamicParams = _getDynamicParams(address(EXISTING_TOKEN_POOL)); - assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), EXISTING_TOKEN_POOL.getProxyPool()); @@ -293,12 +318,17 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(staticParams, _getStaticParams(address(NEW_TOKEN_POOL))); assertEq(dynamicParams, _getDynamicParams(address(NEW_TOKEN_POOL))); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); + + assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), address(NEW_TOKEN_POOL)); + assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 2); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(ETH_PROXY_POOL))); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ETH))); assertEq(NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), abi.encode(MiscEthereum.GHO_TOKEN)); assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 1); assertTrue(NEW_TOKEN_POOL.isSupportedChain(ETH_CHAIN_SELECTOR)); + assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), _getDisabledConfig() @@ -307,9 +337,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), _getDisabledConfig() ); - assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); // sanity check - - assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), address(NEW_TOKEN_POOL)); } function test_newTokenPoolInitialization() public { @@ -475,4 +502,72 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel + amount); assertEq(GHO.balanceOf(alice), aliceBalance + amount); } + + function test_stewardCanSetAndDisableRateLimit() public { + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); // sanity + + // currently disabled + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + + IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 500_000e18, + rate: 100e18 + }); + IRateLimiter.Config memory inboundConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 100_000e18, + rate: 50e18 + }); + + // since only the DAO can re-enable disabled rate limit, + // first we set the rate limit through an AIP directly on the token pool + vm.prank(GovernanceV3Arbitrum.EXECUTOR_LVL_1); + NEW_TOKEN_POOL.setChainRateLimiterConfig(ETH_CHAIN_SELECTOR, outboundConfig, inboundConfig); + + skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); + + // change capacity + outboundConfig.capacity += 1; + outboundConfig.rate += 1; + inboundConfig.capacity += 1; + inboundConfig.rate += 1; + + // now we assert the steward can change the rate limit + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateRateLimit( + ETH_CHAIN_SELECTOR, + outboundConfig.isEnabled, + outboundConfig.capacity, + outboundConfig.rate, + inboundConfig.isEnabled, + inboundConfig.capacity, + inboundConfig.rate + ); + + assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), outboundConfig); + assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), inboundConfig); + + skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); + + // now we assert the steward can disable the rate limit + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateRateLimit(ETH_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); + + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 3b4916963..29f587cb2 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -12,6 +12,7 @@ import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; @@ -22,6 +23,7 @@ import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -50,6 +52,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IEVM2EVMOnRamp EVM2EVMOnRamp; IEVM2EVMOffRamp_1_5 EVM2EVMOffRamp; ITokenAdminRegistry tokenAdminRegistry; + IGhoCcipSteward newGhoCcipSteward; address proxyPool; uint64 chainSelector; uint256 forkId; @@ -88,11 +91,27 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { vm.selectFork(l1.c.forkId); address newTokenPoolEth = _deployNewTokenPoolEth(); + address newGhoCcipStewardEth = _deployNewGhoCcipSteward( + newTokenPoolEth, + MiscEthereum.GHO_TOKEN, + GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience + true // bridgeLimitEnabled + ); vm.selectFork(l2.c.forkId); address newTokenPoolArb = _deployNewTokenPoolArb(); + address newGhoCcipStewardArb = _deployNewGhoCcipSteward( + newTokenPoolArb, + AaveV3ArbitrumAssets.GHO_UNDERLYING, + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience + false // bridgeLimitEnabled + ); vm.selectFork(l1.c.forkId); - l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(newTokenPoolEth, newTokenPoolArb); + l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( + newTokenPoolEth, + newTokenPoolArb, + newGhoCcipStewardEth + ); l1.existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( 0x5756880B6a1EAba0175227bf02a7E87c1e02B28C ); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP @@ -106,7 +125,11 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { l1.c.proxyPool = l1.existingTokenPool.getProxyPool(); vm.selectFork(l2.c.forkId); - l2.proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(newTokenPoolArb, newTokenPoolEth); + l2.proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( + newTokenPoolArb, + newTokenPoolEth, + newGhoCcipStewardArb + ); l2.existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( 0xF168B83598516A532a85995b52504a2Fa058C068 ); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP @@ -315,6 +338,15 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ); } + function _deployNewGhoCcipSteward( + address newTokenPool, + address ghoToken, + address riskCouncil, + bool bridgeLimitEnabled + ) internal returns (address) { + return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); + } + // post upgrade function _runEthToArb(address user, uint256 amount) internal { vm.selectFork(l1.c.forkId); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index ea494bfd0..6f594f7f9 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -26,13 +26,16 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; + address public immutable NEW_GHO_CCIP_STEWARD; + // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb address public immutable NEW_REMOTE_POOL_ARB; - constructor(address newTokenPoolEth, address newTokenPoolArb) { + constructor(address newTokenPoolEth, address newTokenPoolArb, address newGhoCcipSteward) { NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); NEW_REMOTE_POOL_ARB = newTokenPoolArb; + NEW_GHO_CCIP_STEWARD = newGhoCcipSteward; } function execute() external { @@ -80,8 +83,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // setup new pool NEW_TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); - NEW_TOKEN_POOL.setRateLimitAdmin(EXISTING_TOKEN_POOL.getRateLimitAdmin()); // GhoCcipSteward - NEW_TOKEN_POOL.setBridgeLimitAdmin(EXISTING_TOKEN_POOL.getBridgeLimitAdmin()); // GhoCcipSteward + NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); + NEW_TOKEN_POOL.setBridgeLimitAdmin(NEW_GHO_CCIP_STEWARD); // register new pool TOKEN_ADMIN_REGISTRY.setPool(MiscEthereum.GHO_TOKEN, address(NEW_TOKEN_POOL)); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index f52447871..81ab6cfcf 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -14,6 +14,7 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; @@ -24,6 +25,7 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; @@ -51,7 +53,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5 internal constant OFF_RAMP = IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); - address internal constant GHO_CCIP_STEWARD = 0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4; + + IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = + IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); + IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; IUpgradeableLockReleaseTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP @@ -73,9 +78,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function setUp() public virtual { vm.createSelectFork(vm.rpcUrl('mainnet'), 21366260); NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(_deployNewTokenPoolEth()); + NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ARB + NEW_REMOTE_POOL_ARB, + address(NEW_GHO_CCIP_STEWARD) ); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -120,6 +127,18 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ); } + function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { + return + address( + new GhoCcipSteward( + address(GHO), + newTokenPool, + EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL(), + true // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool + ) + ); + } + function _validateConstants() private view { assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); @@ -143,6 +162,13 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(ROUTER.getOnRamp(ARB_CHAIN_SELECTOR), address(ON_RAMP)); assertTrue(ROUTER.isOffRamp(ARB_CHAIN_SELECTOR, address(OFF_RAMP))); + + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); + + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); + assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *present* on eth token pool } function _getTokenMessage( @@ -196,8 +222,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ghoTokenPool.owner(), ghoTokenPool.getSupportedChains(), ghoTokenPool.getAllowListEnabled(), - ghoTokenPool.getRateLimitAdmin(), - ghoTokenPool.getBridgeLimitAdmin(), ghoTokenPool.getRebalancer(), ghoTokenPool.getBridgeLimit() ); @@ -301,7 +325,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is function test_newTokenPoolSetupAndRegistration() public { bytes memory staticParams = _getStaticParams(address(EXISTING_TOKEN_POOL)); bytes memory dynamicParams = _getDynamicParams(address(EXISTING_TOKEN_POOL)); - assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), EXISTING_TOKEN_POOL.getProxyPool()); @@ -309,6 +333,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(staticParams, _getStaticParams(address(NEW_TOKEN_POOL))); assertEq(dynamicParams, _getDynamicParams(address(NEW_TOKEN_POOL))); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); + + assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), address(NEW_TOKEN_POOL)); + assertEq(NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR).length, 2); assertTrue(NEW_TOKEN_POOL.isRemotePool(ARB_CHAIN_SELECTOR, abi.encode(ARB_PROXY_POOL))); assertTrue(NEW_TOKEN_POOL.isRemotePool(ARB_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ARB))); @@ -318,6 +346,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is ); assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 1); assertTrue(NEW_TOKEN_POOL.isSupportedChain(ARB_CHAIN_SELECTOR)); + assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), _getDisabledConfig() @@ -326,10 +355,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), _getDisabledConfig() ); - assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), GHO_CCIP_STEWARD); // sanity check - assertEq(NEW_TOKEN_POOL.getBridgeLimitAdmin(), GHO_CCIP_STEWARD); // sanity check - - assertEq(TOKEN_ADMIN_REGISTRY.getPool(address(GHO)), address(NEW_TOKEN_POOL)); } function test_newTokenPoolInitialization() public { @@ -508,4 +533,92 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), tokenPoolBalance - amount); assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount - amount); } + + function test_stewardCanSetAndDisableRateLimit() public { + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); // sanity + + // currently disabled + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + + IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 500_000e18, + rate: 100e18 + }); + IRateLimiter.Config memory inboundConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 100_000e18, + rate: 50e18 + }); + + // since only the DAO can re-enable disabled rate limit, + // first we set the rate limit through an AIP directly on the token pool + vm.prank(GovernanceV3Ethereum.EXECUTOR_LVL_1); + NEW_TOKEN_POOL.setChainRateLimiterConfig(ARB_CHAIN_SELECTOR, outboundConfig, inboundConfig); + + skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); + + // change capacity + outboundConfig.capacity += 1; + outboundConfig.rate += 1; + inboundConfig.capacity += 1; + inboundConfig.rate += 1; + + // now we assert the new steward can change the rate limit + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateRateLimit( + ARB_CHAIN_SELECTOR, + outboundConfig.isEnabled, + outboundConfig.capacity, + outboundConfig.rate, + inboundConfig.isEnabled, + inboundConfig.capacity, + inboundConfig.rate + ); + + assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), outboundConfig); + assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), inboundConfig); + + skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); + + // now we assert the new steward can disable the rate limit + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateRateLimit(ARB_CHAIN_SELECTOR, false, 0, 0, false, 0, 0); + + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + } + + function test_stewardCanSetBridgeLimit(uint256 newBridgeLimit) public { + uint256 currentBridgeLimit = NEW_TOKEN_POOL.getBridgeLimit(); + vm.assume( + newBridgeLimit != currentBridgeLimit && + _isDifferenceLowerThanMax(currentBridgeLimit, newBridgeLimit, currentBridgeLimit) + ); + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateBridgeLimit(newBridgeLimit); + + assertEq(NEW_TOKEN_POOL.getBridgeLimit(), newBridgeLimit); + } + + function _isDifferenceLowerThanMax( + uint256 from, + uint256 to, + uint256 max + ) internal pure returns (bool) { + return from < to ? to - from <= max : from - to <= max; + } } From acbf6e542053f9616f1ef7b1e8da8bdfc642d342 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 23 Dec 2024 17:06:50 +0530 Subject: [PATCH 026/123] feat: reference existing pool upgrade impl deployment --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 20 +- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../config.ts | 2 +- ...eableBurnMintTokenPool_1_4_WithdrawLiq.sol | 1819 ----------------- .../IUpgradeableBurnMintTokenPool.sol | 1 + 6 files changed, 11 insertions(+), 1835 deletions(-) delete mode 100644 src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 297261f48..1019b5be7 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -12,8 +12,6 @@ import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; -import {UpgradeableBurnMintTokenPool} from './utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol'; - /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs @@ -38,6 +36,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH address public immutable NEW_REMOTE_POOL_ETH; + // https://arbiscan.io/address/0x360d8aa8F6b09B7BC57aF34db2Eb84dD87bf4d12 + address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = + 0x360d8aa8F6b09B7BC57aF34db2Eb84dD87bf4d12; // from https://github.com/aave/ccip/pull/21 (commit f684d950178fbdc95f543382fac472cf47434d55) + ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); @@ -68,8 +70,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); NEW_TOKEN_POOL.directMint(address(EXISTING_TOKEN_POOL), bucketLevel); // increase facilitator level - _upgradeExistingTokenPool(); - UpgradeableBurnMintTokenPool(address(EXISTING_TOKEN_POOL)).directBurn(bucketLevel); // decrease facilitator level + _upgradeExistingTokenPool(); // introduce `directBurn` method + EXISTING_TOKEN_POOL.directBurn(bucketLevel); // decrease facilitator level GHO.removeFacilitator(address(EXISTING_TOKEN_POOL)); } @@ -105,17 +107,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { } function _upgradeExistingTokenPool() internal { - address newImplementation = address( - new UpgradeableBurnMintTokenPool( - EXISTING_TOKEN_POOL.getToken(), - EXISTING_TOKEN_POOL.getArmProxy(), - EXISTING_TOKEN_POOL.getAllowListEnabled() - ) - ); - PROXY_ADMIN.upgrade( TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), - newImplementation + EXISTING_TOKEN_POOL_UPGRADE_IMPL ); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index d09338769..65c3bab80 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -74,7 +74,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 283036001); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 287752362); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 29f587cb2..46fdbe722 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -87,7 +87,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function setUp() public virtual { l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21366260); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 283036001); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 287752362); vm.selectFork(l1.c.forkId); address newTokenPoolEth = _deployNewTokenPoolEth(); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index 0647cfa65..833e1934b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -12,6 +12,6 @@ export const config: ConfigFile = { }, poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21366260}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 283036001}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 287752362}}, }, }; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol b/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol deleted file mode 100644 index 41df48d61..000000000 --- a/src/20241209_Multi_GHOCCIP151Upgrade/utils/UpgradeableBurnMintTokenPool_1_4_WithdrawLiq.sol +++ /dev/null @@ -1,1819 +0,0 @@ -/// Flattened UpgradeableBurnMintTokenPool from https://github.com/aave/ccip/pull/21 (commit e8bf9ad6e9967ce4f6a06d916d8ea4af8c07a595) -/// Will be removed once PR is merged and contract implementation is deployed - -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -// foundry-lib/solidity-utils/src/contracts/oz-common/Address.sol - -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) -// From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/8b778fa20d6d76340c5fac1ed66c80273f05b95a - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, 'Address: insufficient balance'); - - (bool success, ) = recipient.call{value: amount}(''); - require(success, 'Address: unable to send value, recipient may have reverted'); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, 'Address: low-level call failed'); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, 'Address: low-level call with value failed'); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, 'Address: insufficient balance for call'); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data - ) internal view returns (bytes memory) { - return functionStaticCall(target, data, 'Address: low-level static call failed'); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, 'Address: low-level delegate call failed'); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), 'Address: call to non-contract'); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// src/v0.8/ccip/interfaces/IARM.sol - -/// @notice This interface contains the only ARM-related functions that might be used on-chain by other CCIP contracts. -interface IARM { - /// @notice A Merkle root tagged with the address of the commit store contract it is destined for. - struct TaggedRoot { - address commitStore; - bytes32 root; - } - - /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. - function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool); - - /// @notice When the ARM is "cursed", CCIP pauses until the curse is lifted. - function isCursed() external view returns (bool); -} - -// src/v0.8/ccip/libraries/Client.sol - -// End consumer library. -library Client { - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct EVMTokenAmount { - address token; // token address on the local chain. - uint256 amount; // Amount of tokens. - } - - struct Any2EVMMessage { - bytes32 messageId; // MessageId corresponding to ccipSend on source. - uint64 sourceChainSelector; // Source chain selector. - bytes sender; // abi.decode(sender) if coming from an EVM chain. - bytes data; // payload sent in original message. - EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. - } - - // If extraArgs is empty bytes, the default is 200k gas limit. - struct EVM2AnyMessage { - bytes receiver; // abi.encode(receiver address) for dest EVM chains - bytes data; // Data payload - EVMTokenAmount[] tokenAmounts; // Token transfers - address feeToken; // Address of feeToken. address(0) means you will send msg.value. - bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1) - } - - // bytes4(keccak256("CCIP EVMExtraArgsV1")); - bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; - struct EVMExtraArgsV1 { - uint256 gasLimit; - } - - function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { - return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); - } -} - -// src/v0.8/ccip/libraries/RateLimiter.sol - -/// @notice Implements Token Bucket rate limiting. -/// @dev uint128 is safe for rate limiter state. -/// For USD value rate limiting, it can adequately store USD value in 18 decimals. -/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most -/// a supply of uint128.max tokens, and it will therefore not overflow the bucket. -/// In exceptional scenarios where tokens consumed may be larger than uint128, -/// e.g. compromised issuer, an enabled RateLimiter will check and revert. -library RateLimiter { - error BucketOverfilled(); - error OnlyCallableByAdminOrOwner(); - error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); - error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); - error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); - error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); - error InvalidRatelimitRate(Config rateLimiterConfig); - error DisabledNonZeroRateLimit(Config config); - error RateLimitMustBeDisabled(); - - event TokensConsumed(uint256 tokens); - event ConfigChanged(Config config); - - 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 - uint128 rate; // ───────╯ Specifies the rate of the rate limiter - } - - /// @notice _consume removes the given tokens from the pool, lowering the - /// rate tokens allowed to be consumed for subsequent calls. - /// @param requestTokens The total tokens to be consumed from the bucket. - /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity. - /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket - /// @dev emits removal of requestTokens if requestTokens is > 0 - function _consume( - TokenBucket storage s_bucket, - uint256 requestTokens, - address tokenAddress - ) internal { - // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage - if (!s_bucket.isEnabled || requestTokens == 0) { - return; - } - - uint256 tokens = s_bucket.tokens; - uint256 capacity = s_bucket.capacity; - uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; - - if (timeDiff != 0) { - if (tokens > capacity) revert BucketOverfilled(); - - // Refill tokens when arriving at a new block time - tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate); - - s_bucket.lastUpdated = uint32(block.timestamp); - } - - if (capacity < requestTokens) { - // Token address 0 indicates consuming aggregate value rate limit capacity. - if (tokenAddress == address(0)) - revert AggregateValueMaxCapacityExceeded(capacity, requestTokens); - revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress); - } - if (tokens < requestTokens) { - uint256 rate = s_bucket.rate; - // Wait required until the bucket is refilled enough to accept this value, round up to next higher second - // Consume is not guaranteed to succeed after wait time passes if there is competing traffic. - // This acts as a lower bound of wait time. - uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate; - - if (tokenAddress == address(0)) - revert AggregateValueRateLimitReached(minWaitInSeconds, tokens); - revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress); - } - tokens -= requestTokens; - - // Downcast is safe here, as tokens is not larger than capacity - s_bucket.tokens = uint128(tokens); - emit TokensConsumed(requestTokens); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function _currentTokenBucketState( - TokenBucket memory bucket - ) internal view returns (TokenBucket memory) { - // We update the bucket to reflect the status at the exact time of the - // call. This means we might need to refill a part of the bucket based - // on the time that has passed since the last update. - bucket.tokens = uint128( - _calculateRefill( - bucket.capacity, - bucket.tokens, - block.timestamp - bucket.lastUpdated, - bucket.rate - ) - ); - bucket.lastUpdated = uint32(block.timestamp); - return bucket; - } - - /// @notice Sets the rate limited config. - /// @param s_bucket The token bucket - /// @param config The new config - function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal { - // First update the bucket to make sure the proper rate is used for all the time - // up until the config change. - uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; - if (timeDiff != 0) { - s_bucket.tokens = uint128( - _calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate) - ); - - s_bucket.lastUpdated = uint32(block.timestamp); - } - - s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens)); - s_bucket.isEnabled = config.isEnabled; - s_bucket.capacity = config.capacity; - s_bucket.rate = config.rate; - - emit ConfigChanged(config); - } - - /// @notice Validates the token bucket config - function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure { - if (config.isEnabled) { - if (config.rate >= config.capacity || config.rate == 0) { - revert InvalidRatelimitRate(config); - } - if (mustBeDisabled) { - revert RateLimitMustBeDisabled(); - } - } else { - if (config.rate != 0 || config.capacity != 0) { - revert DisabledNonZeroRateLimit(config); - } - } - } - - /// @notice Calculate refilled tokens - /// @param capacity bucket capacity - /// @param tokens current bucket tokens - /// @param timeDiff block time difference since last refill - /// @param rate bucket refill rate - /// @return the value of tokens after refill - function _calculateRefill( - uint256 capacity, - uint256 tokens, - uint256 timeDiff, - uint256 rate - ) private pure returns (uint256) { - return _min(capacity, tokens + timeDiff * rate); - } - - /// @notice Return the smallest of two integers - /// @param a first int - /// @param b second int - /// @return smallest - function _min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} - -// src/v0.8/shared/interfaces/IOwnable.sol - -interface IOwnable { - function owner() external returns (address); - - function transferOwnership(address recipient) external; - - function acceptOwnership() external; -} - -// src/v0.8/shared/interfaces/ITypeAndVersion.sol - -interface ITypeAndVersion { - function typeAndVersion() external pure returns (string memory); -} - -// src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - -/** - * @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); -} - -// src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol - -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol - -// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - bytes32[] memory store = _values(set._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - -// foundry-lib/solidity-utils/src/contracts/transparent-proxy/Initializable.sol - -/** - * @dev OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) - * From https://github.com/OpenZeppelin/openzeppelin-contracts/tree/8b778fa20d6d76340c5fac1ed66c80273f05b95a - * - * BGD Labs adaptations: - * - Added a constructor disabling initialization for implementation contracts - * - Linting - */ - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be - * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in - * case an upgrade adds a module that needs to be initialized. - * - * For example: - * - * [.hljs-theme-light.nopadding] - * ``` - * contract MyToken is ERC20Upgradeable { - * function initialize() initializer public { - * __ERC20_init("MyToken", "MTK"); - * } - * } - * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { - * function initializeV2() reinitializer(2) public { - * __ERC20Permit_init("MyToken"); - * } - * } - * ``` - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke - * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() { - * _disableInitializers(); - * } - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev OPINIONATED. Generally is not a good practise to allow initialization of implementations - */ - constructor() { - _disableInitializers(); - } - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = !_initializing; - require( - (isTopLevelCall && _initialized < 1) || - (!Address.isContract(address(this)) && _initialized == 1), - 'Initializable: contract is already initialized' - ); - _initialized = 1; - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - require( - !_initializing && _initialized < version, - 'Initializable: contract is already initialized' - ); - _initialized = version; - _initializing = true; - _; - _initializing = false; - emit Initialized(version); - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, 'Initializable: contract is not initializing'); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - require(!_initializing, 'Initializable: contract is initializing'); - if (_initialized < type(uint8).max) { - _initialized = type(uint8).max; - emit Initialized(type(uint8).max); - } - } -} - -// src/v0.8/ccip/interfaces/IRouter.sol - -interface IRouter { - error OnlyOffRamp(); - - /// @notice Route the message to its intended receiver contract. - /// @param message Client.Any2EVMMessage struct. - /// @param gasForCallExactCheck of params for exec - /// @param gasLimit set of params for exec - /// @param receiver set of params for exec - /// @dev if the receiver is a contracts that signals support for CCIP execution through EIP-165. - /// the contract is called. If not, only tokens are transferred. - /// @return success A boolean value indicating whether the ccip message was received without errors. - /// @return retBytes A bytes array containing return data form CCIP receiver. - /// @return gasUsed the gas used by the external customer call. Does not include any overhead. - function routeMessage( - Client.Any2EVMMessage calldata message, - uint16 gasForCallExactCheck, - uint256 gasLimit, - address receiver - ) external returns (bool success, bytes memory retBytes, uint256 gasUsed); - - /// @notice Returns the configured onramp for a specific destination chain. - /// @param destChainSelector The destination chain Id to get the onRamp for. - /// @return onRampAddress The address of the onRamp. - function getOnRamp(uint64 destChainSelector) external view returns (address onRampAddress); - - /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. - /// @param sourceChainSelector The source chain selector to check. - /// @param offRamp The address of the offRamp to check. - function isOffRamp( - uint64 sourceChainSelector, - address offRamp - ) external view returns (bool isOffRamp); -} - -// src/v0.8/ccip/interfaces/pools/IPool.sol - -// Shared public interface for multiple pool types. -// Each pool type handles a different child token model (lock/unlock, mint/burn.) -interface IPool { - /// @notice Lock tokens into the pool or burn the tokens. - /// @param originalSender Original sender of the tokens. - /// @param receiver Receiver of the tokens on destination chain. - /// @param amount Amount to lock or burn. - /// @param remoteChainSelector Destination chain Id. - /// @param extraArgs Additional data passed in by sender for lockOrBurn processing - /// in custom pools on source chain. - /// @return retData Optional field that contains bytes. Unused for now but already - /// implemented to allow future upgrades while preserving the interface. - function lockOrBurn( - address originalSender, - bytes calldata receiver, - uint256 amount, - uint64 remoteChainSelector, - bytes calldata extraArgs - ) external returns (bytes memory); - - /// @notice Releases or mints tokens to the receiver address. - /// @param originalSender Original sender of the tokens. - /// @param receiver Receiver of the tokens. - /// @param amount Amount to release or mint. - /// @param remoteChainSelector Source chain Id. - /// @param extraData Additional data supplied offchain for releaseOrMint processing in - /// custom pools on dest chain. This could be an attestation that was retrieved through a - /// third party API. - /// @dev offchainData can come from any untrusted source. - function releaseOrMint( - bytes memory originalSender, - address receiver, - uint256 amount, - uint64 remoteChainSelector, - bytes memory extraData - ) external; - - /// @notice Gets the IERC20 token that this pool can lock or burn. - /// @return token The IERC20 token representation. - function getToken() external view returns (IERC20 token); -} - -// src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol - -/// @title The ConfirmedOwner contract -/// @notice A contract with helpers for basic contract ownership. -contract ConfirmedOwnerWithProposal is IOwnable { - address private s_owner; - address private s_pendingOwner; - - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - - constructor(address newOwner, address pendingOwner) { - // solhint-disable-next-line custom-errors - require(newOwner != address(0), 'Cannot set owner to zero'); - - s_owner = newOwner; - if (pendingOwner != address(0)) { - _transferOwnership(pendingOwner); - } - } - - /// @notice Allows an owner to begin transferring ownership to a new address. - function transferOwnership(address to) public override onlyOwner { - _transferOwnership(to); - } - - /// @notice Allows an ownership transfer to be completed by the recipient. - function acceptOwnership() external override { - // solhint-disable-next-line custom-errors - require(msg.sender == s_pendingOwner, 'Must be proposed owner'); - - address oldOwner = s_owner; - s_owner = msg.sender; - s_pendingOwner = address(0); - - emit OwnershipTransferred(oldOwner, msg.sender); - } - - /// @notice Get the current owner - function owner() public view override returns (address) { - return s_owner; - } - - /// @notice validate, transfer ownership, and emit relevant events - function _transferOwnership(address to) internal { - s_pendingOwner = to; - - emit OwnershipTransferRequested(s_owner, to); - } - - /// @notice validate access - function _validateOwnership() internal view { - // solhint-disable-next-line custom-errors - require(msg.sender == s_owner, 'Only callable by owner'); - } - - /// @notice Reverts if called by anyone other than the contract owner. - modifier onlyOwner() { - _validateOwnership(); - _; - } -} - -// src/v0.8/shared/token/ERC20/IBurnMintERC20.sol - -interface IBurnMintERC20 is IERC20 { - /// @notice Mints new tokens for a given address. - /// @param account The address to mint the new tokens to. - /// @param amount The number of tokens to be minted. - /// @dev this function increases the total supply. - function mint(address account, uint256 amount) external; - - /// @notice Burns tokens from the sender. - /// @param amount The number of tokens to be burned. - /// @dev this function decreases the total supply. - function burn(uint256 amount) external; - - /// @notice Burns tokens from a given address.. - /// @param account The address to burn tokens from. - /// @param amount The number of tokens to be burned. - /// @dev this function decreases the total supply. - function burn(address account, uint256 amount) external; - - /// @notice Burns tokens from a given address.. - /// @param account The address to burn tokens from. - /// @param amount The number of tokens to be burned. - /// @dev this function decreases the total supply. - function burnFrom(address account, uint256 amount) external; -} - -// src/v0.8/shared/access/ConfirmedOwner.sol - -/// @title The ConfirmedOwner contract -/// @notice A contract with helpers for basic contract ownership. -contract ConfirmedOwner is ConfirmedOwnerWithProposal { - constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} -} - -// src/v0.8/shared/access/OwnerIsCreator.sol - -/// @title The OwnerIsCreator contract -/// @notice A contract with helpers for basic contract ownership. -contract OwnerIsCreator is ConfirmedOwner { - constructor() ConfirmedOwner(msg.sender) {} -} - -// src/v0.8/ccip/pools/GHO/UpgradeableTokenPool.sol - -/// @title UpgradeableTokenPool -/// @author Aave Labs -/// @notice Upgradeable version of Chainlink's CCIP TokenPool -/// @dev Contract adaptations: -/// - Setters & Getters for new ProxyPool (to support 1.5 CCIP migration on the existing 1.4 Pool) -/// - Modify `onlyOnRamp` & `onlyOffRamp` modifier to accept transactions from ProxyPool -abstract contract UpgradeableTokenPool is IPool, OwnerIsCreator, IERC165 { - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - using RateLimiter for RateLimiter.TokenBucket; - - error CallerIsNotARampOnRouter(address caller); - error ZeroAddressNotAllowed(); - error SenderNotAllowed(address sender); - error AllowListNotEnabled(); - error NonExistentChain(uint64 remoteChainSelector); - error ChainNotAllowed(uint64 remoteChainSelector); - error BadARMSignal(); - error ChainAlreadyExists(uint64 chainSelector); - - 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); - event ChainAdded( - uint64 remoteChainSelector, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainConfigured( - uint64 remoteChainSelector, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainRemoved(uint64 remoteChainSelector); - event AllowListAdd(address sender); - event AllowListRemove(address sender); - event RouterUpdated(address oldRouter, address newRouter); - - struct ChainUpdate { - uint64 remoteChainSelector; // ──╮ Remote chain selector - bool allowed; // ────────────────╯ Whether the chain is allowed - RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain - RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - } - - /// @dev The storage slot for Proxy Pool address, act as an on ramp "wrapper" post ccip 1.5 migration. - /// @dev This was added to continue support for 1.2 onRamp during 1.5 migration, and is stored - /// this way to avoid storage collision. - // bytes32(uint256(keccak256("ccip.pools.GHO.UpgradeableTokenPool.proxyPool")) - 1) - bytes32 internal constant PROXY_POOL_SLOT = - 0x75bb68f1b335d4dab6963140ecff58281174ef4362bb85a8593ab9379f24fae2; - - /// @dev The bridgeable token that is managed by this pool. - IERC20 internal immutable i_token; - /// @dev The address of the arm proxy - address internal immutable i_armProxy; - /// @dev The immutable flag that indicates if the pool is access-controlled. - bool internal immutable i_allowlistEnabled; - /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. - /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can - /// move tokens. - EnumerableSet.AddressSet internal s_allowList; - /// @dev The address of the router - IRouter internal s_router; - /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to - /// be able to quickly determine (without parsing logs) who can access the pool. - /// @dev The chain selectors are in uin256 format because of the EnumerableSet implementation. - EnumerableSet.UintSet internal s_remoteChainSelectors; - /// @dev Outbound rate limits. Corresponds to the inbound rate limit for the pool - /// on the remote chain. - mapping(uint64 => RateLimiter.TokenBucket) internal s_outboundRateLimits; - /// @dev Inbound rate limits. This allows per destination chain - /// token issuer specified rate limiting (e.g. issuers may trust chains to varying - /// degrees and prefer different limits) - mapping(uint64 => RateLimiter.TokenBucket) internal s_inboundRateLimits; - - constructor(IERC20 token, address armProxy, bool allowlistEnabled) { - if (address(token) == address(0)) revert ZeroAddressNotAllowed(); - i_token = token; - i_armProxy = armProxy; - i_allowlistEnabled = allowlistEnabled; - } - - /// @notice Get ARM proxy address - /// @return armProxy Address of arm proxy - function getArmProxy() public view returns (address armProxy) { - return i_armProxy; - } - - /// @inheritdoc IPool - function getToken() public view override returns (IERC20 token) { - return i_token; - } - - /// @notice Gets the pool's Router - /// @return router The pool's Router - function getRouter() public view returns (address router) { - return address(s_router); - } - - /// @notice Sets the pool's Router - /// @param newRouter The new Router - function setRouter(address newRouter) public onlyOwner { - if (newRouter == address(0)) revert ZeroAddressNotAllowed(); - address oldRouter = address(s_router); - s_router = IRouter(newRouter); - - emit RouterUpdated(oldRouter, newRouter); - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { - return interfaceId == type(IPool).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // │ Chain permissions │ - // ================================================================ - - /// @notice Checks whether a chain selector is permissioned on this contract. - /// @return true if the given chain selector is a permissioned remote chain. - function isSupportedChain(uint64 remoteChainSelector) public view returns (bool) { - return s_remoteChainSelectors.contains(remoteChainSelector); - } - - /// @notice Get list of allowed chains - /// @return list of chains. - function getSupportedChains() public view returns (uint64[] memory) { - uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); - uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); - for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { - chainSelectors[i] = uint64(uint256ChainSelectors[i]); - } - - return chainSelectors; - } - - /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains - /// need to be allowed on the Router to interact with this pool. - /// @dev Only callable by the owner - /// @param chains A list of chains and their new permission status & rate limits. Rate limits - /// are only used when the chain is being added through `allowed` being true. - function applyChainUpdates(ChainUpdate[] calldata chains) external virtual onlyOwner { - for (uint256 i = 0; i < chains.length; ++i) { - ChainUpdate memory update = chains[i]; - RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); - RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); - - if (update.allowed) { - // If the chain already exists, revert - if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { - revert ChainAlreadyExists(update.remoteChainSelector); - } - - s_outboundRateLimits[update.remoteChainSelector] = RateLimiter.TokenBucket({ - rate: update.outboundRateLimiterConfig.rate, - capacity: update.outboundRateLimiterConfig.capacity, - tokens: update.outboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.outboundRateLimiterConfig.isEnabled - }); - - s_inboundRateLimits[update.remoteChainSelector] = RateLimiter.TokenBucket({ - rate: update.inboundRateLimiterConfig.rate, - capacity: update.inboundRateLimiterConfig.capacity, - tokens: update.inboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.inboundRateLimiterConfig.isEnabled - }); - emit ChainAdded( - update.remoteChainSelector, - update.outboundRateLimiterConfig, - update.inboundRateLimiterConfig - ); - } else { - // If the chain doesn't exist, revert - if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { - revert NonExistentChain(update.remoteChainSelector); - } - - delete s_inboundRateLimits[update.remoteChainSelector]; - delete s_outboundRateLimits[update.remoteChainSelector]; - emit ChainRemoved(update.remoteChainSelector); - } - } - } - - // ================================================================ - // │ Rate limiting │ - // ================================================================ - - /// @notice Consumes outbound rate limiting capacity in this pool - function _consumeOutboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { - s_outboundRateLimits[remoteChainSelector]._consume(amount, address(i_token)); - } - - /// @notice Consumes inbound rate limiting capacity in this pool - function _consumeInboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { - s_inboundRateLimits[remoteChainSelector]._consume(amount, address(i_token)); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentOutboundRateLimiterState( - uint64 remoteChainSelector - ) external view returns (RateLimiter.TokenBucket memory) { - return s_outboundRateLimits[remoteChainSelector]._currentTokenBucketState(); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentInboundRateLimiterState( - uint64 remoteChainSelector - ) external view returns (RateLimiter.TokenBucket memory) { - return s_inboundRateLimits[remoteChainSelector]._currentTokenBucketState(); - } - - /// @notice Sets the chain rate limiter config. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. - /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. - function setChainRateLimiterConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) external virtual onlyOwner { - _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); - } - - function _setRateLimitConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) internal { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - RateLimiter._validateTokenBucketConfig(outboundConfig, false); - s_outboundRateLimits[remoteChainSelector]._setTokenBucketConfig(outboundConfig); - RateLimiter._validateTokenBucketConfig(inboundConfig, false); - s_inboundRateLimits[remoteChainSelector]._setTokenBucketConfig(inboundConfig); - emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned onRamp for the given chain on the Router. - modifier onlyOnRamp(uint64 remoteChainSelector) { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!(msg.sender == getProxyPool() || msg.sender == s_router.getOnRamp(remoteChainSelector))) { - revert CallerIsNotARampOnRouter(msg.sender); - } - _; - } - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned offRamp for the given chain on the Router. - modifier onlyOffRamp(uint64 remoteChainSelector) { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!(msg.sender == getProxyPool() || s_router.isOffRamp(remoteChainSelector, msg.sender))) { - revert CallerIsNotARampOnRouter(msg.sender); - } - _; - } - - // ================================================================ - // │ Allowlist │ - // ================================================================ - - modifier checkAllowList(address sender) { - if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); - _; - } - - /// @notice Gets whether the allowList functionality is enabled. - /// @return true is enabled, false if not. - function getAllowListEnabled() external view returns (bool) { - return i_allowlistEnabled; - } - - /// @notice Gets the allowed addresses. - /// @return The allowed addresses. - function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); - } - - /// @notice Apply updates to the allow list. - /// @param removes The addresses to be removed. - /// @param adds The addresses to be added. - /// @dev allowListing will be removed before public launch - function applyAllowListUpdates( - address[] calldata removes, - address[] calldata adds - ) external onlyOwner { - _applyAllowListUpdates(removes, adds); - } - - /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. - function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { - if (!i_allowlistEnabled) revert AllowListNotEnabled(); - - for (uint256 i = 0; i < removes.length; ++i) { - address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { - emit AllowListRemove(toRemove); - } - } - for (uint256 i = 0; i < adds.length; ++i) { - address toAdd = adds[i]; - if (toAdd == address(0)) { - continue; - } - if (s_allowList.add(toAdd)) { - emit AllowListAdd(toAdd); - } - } - } - - /// @notice Ensure that there is no active curse. - modifier whenHealthy() { - if (IARM(i_armProxy).isCursed()) revert BadARMSignal(); - _; - } - - /// @notice Getter for proxy pool address. - /// @return proxyPool The proxy pool address. - function getProxyPool() public view returns (address proxyPool) { - assembly ('memory-safe') { - proxyPool := shr(96, shl(96, sload(PROXY_POOL_SLOT))) - } - } - - /// @notice Setter for proxy pool address, only callable by the DAO. - /// @param proxyPool The address of the proxy pool. - function setProxyPool(address proxyPool) external onlyOwner { - if (proxyPool == address(0)) revert ZeroAddressNotAllowed(); - assembly ('memory-safe') { - sstore(PROXY_POOL_SLOT, proxyPool) - } - } -} - -// src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPoolAbstract.sol - -abstract contract UpgradeableBurnMintTokenPoolAbstract is UpgradeableTokenPool { - /// @notice Contains the specific burn call for a pool. - /// @dev overriding this method allows us to create pools with different burn signatures - /// without duplicating the underlying logic. - function _burn(uint256 amount) internal virtual; - - /// @notice Burn the token in the pool - /// @param amount Amount to burn - /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised - /// we're able to stop token movement via ARM. - function lockOrBurn( - address originalSender, - bytes calldata, - uint256 amount, - uint64 remoteChainSelector, - bytes calldata - ) - external - virtual - override - onlyOnRamp(remoteChainSelector) - checkAllowList(originalSender) - whenHealthy - returns (bytes memory) - { - _consumeOutboundRateLimit(remoteChainSelector, amount); - _burn(amount); - emit Burned(msg.sender, amount); - return ''; - } - - /// @notice Mint tokens from the pool to the recipient - /// @param receiver Recipient address - /// @param amount Amount to mint - /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised - /// we're able to stop token movement via ARM. - function releaseOrMint( - bytes memory, - address receiver, - uint256 amount, - uint64 remoteChainSelector, - bytes memory - ) external virtual override whenHealthy onlyOffRamp(remoteChainSelector) { - _consumeInboundRateLimit(remoteChainSelector, amount); - IBurnMintERC20(address(i_token)).mint(receiver, amount); - emit Minted(msg.sender, receiver, amount); - } -} - -// src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol - -/// @title UpgradeableBurnMintTokenPool -/// @author Aave Labs -/// @notice Upgradeable version of Chainlink's CCIP BurnMintTokenPool -/// @dev Contract adaptations: -/// - Implementation of Initializable to allow upgrades -/// - Move of allowlist and router definition to initialization stage -/// - Inclusion of rate limit admin who may configure rate limits in addition to owner -/// - Add GHO-Specific onlyOwner `directBurn` which burns liquidity & reduces facilitator level. -/// - Modifications from inherited contract (see contract for more details): -/// - UpgradeableTokenPool: Modify `onlyOnRamp` & `onlyOffRamp` modifier to accept transactions from ProxyPool -contract UpgradeableBurnMintTokenPool is - Initializable, - UpgradeableBurnMintTokenPoolAbstract, - ITypeAndVersion -{ - error Unauthorized(address caller); - - string public constant override typeAndVersion = 'BurnMintTokenPool 1.4.0'; - - /// @notice The address of the rate limiter admin. - /// @dev Can be address(0) if none is configured. - address internal s_rateLimitAdmin; - - /// @dev Constructor - /// @param token The bridgeable token that is managed by this pool. - /// @param armProxy The address of the arm proxy - /// @param allowlistEnabled True if pool is set to access-controlled mode, false otherwise - constructor( - address token, - address armProxy, - bool allowlistEnabled - ) UpgradeableTokenPool(IBurnMintERC20(token), armProxy, allowlistEnabled) {} - - /// @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 - ) public virtual initializer { - if (owner == address(0) || router == address(0)) revert ZeroAddressNotAllowed(); - _transferOwnership(owner); - - s_router = IRouter(router); - - // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. - if (i_allowlistEnabled) { - _applyAllowListUpdates(new address[](0), allowlist); - } - } - - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner. - /// @param rateLimitAdmin The new rate limiter admin address. - function setRateLimitAdmin(address rateLimitAdmin) external onlyOwner { - s_rateLimitAdmin = rateLimitAdmin; - } - - /// @notice Gets the rate limiter admin address. - function getRateLimitAdmin() external view returns (address) { - return s_rateLimitAdmin; - } - - /// @notice Sets the chain rate limiter config. - /// @dev Only callable by the owner or the rate limiter admin. NOTE: overwrites the normal - /// onlyAdmin check in the base implementation to also allow the rate limiter admin. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config. - /// @param inboundConfig The new inbound rate limiter config. - function setChainRateLimiterConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) external override { - if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); - - _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); - } - - /// @notice This function allows the owner to burn `amount` of the pool's token. This is - /// expected to be called while migrating facilitators by offboarding this facilitator in - /// favor of a new token pool. - /// @dev New token pool should mint and transfer liquidity to this pool (since this pool - /// does not hold tokens at any point in time) which can be burnt and hence will reduce - /// the facilitator bucket level on GHO. The naming convention is inspired from that in - /// LockRelease type token pools for the sake of consistency. - /// @param amount The amount of tokens to burn. - function directBurn(uint256 amount) external onlyOwner { - _burn(amount); - } - - /// @inheritdoc UpgradeableBurnMintTokenPoolAbstract - function _burn(uint256 amount) internal virtual override { - IBurnMintERC20(address(i_token)).burn(amount); - } -} diff --git a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol index 6a7bbe0a7..00bedbab6 100644 --- a/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol +++ b/src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol @@ -57,6 +57,7 @@ interface IUpgradeableBurnMintTokenPool_1_4 { function acceptOwnership() external; function applyAllowListUpdates(address[] memory removes, address[] memory adds) external; function applyChainUpdates(ChainUpdate[] memory chains) external; + function directBurn(uint256 amount) external; function getAllowList() external view returns (address[] memory); function getAllowListEnabled() external view returns (bool); function getArmProxy() external view returns (address armProxy); From c95c114b995c3307f79ddb6b6f5e4ddd6f1ad83d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 23 Dec 2024 20:32:26 +0530 Subject: [PATCH 027/123] feat: more verbose and efficient --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 5 ++++- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 8 +++++--- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 5 ++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 1019b5be7..d03a8df00 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -99,7 +99,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { }); // setup new pool - NEW_TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); + NEW_TOKEN_POOL.applyChainUpdates({ + remoteChainSelectorsToRemove: new uint64[](0), + chainsToAdd: chains + }); NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); // register new pool diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 46fdbe722..b428a7f46 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -475,9 +475,11 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_E2E_FromEth(uint256 amount) public { vm.selectFork(l1.c.forkId); - uint256 currentBridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); - - amount = bound(amount, 1, currentBridgedAmount); + amount = bound( + amount, + 1, + l1.newTokenPool.getBridgeLimit() - l1.newTokenPool.getCurrentBridgedAmount() + ); deal(address(l1.c.token), alice, amount); _runEthToArb(alice, amount); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 6f594f7f9..6372a59c1 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -82,7 +82,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { }); // setup new pool - NEW_TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); + NEW_TOKEN_POOL.applyChainUpdates({ + remoteChainSelectorsToRemove: new uint64[](0), + chainsToAdd: chains + }); NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); NEW_TOKEN_POOL.setBridgeLimitAdmin(NEW_GHO_CCIP_STEWARD); From b289a4c7063e264c81718c61484d190b5f21d309 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 23 Dec 2024 21:57:48 +0530 Subject: [PATCH 028/123] feat: base expansion --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 54 ++ ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 28 + .../AaveV3Base_GHOBaseLaunch_20241223.sol | 119 ++++ .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 34 + .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 609 ++++++++++++++++++ .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 51 ++ ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 28 + .../GHOBaseLaunch.md | 22 + .../GHOBaseLaunch_20241223.s.sol | 115 ++++ src/20241223_Multi_GHOBaseLaunch/config.ts | 18 + .../utils/CCIPUtils.sol | 165 +++++ src/interfaces/IGhoToken.sol | 6 + 12 files changed, 1249 insertions(+) create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md create mode 100644 src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/config.ts create mode 100644 src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol new file mode 100644 index 000000000..dfb20feeb --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; + +/** + * @title GHO Base Launch + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { + uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; + + IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; // replace with MiscArbitrum.GHO_CCIP_TOKEN_POOL once address-book is updated + + address public immutable REMOTE_TOKEN_POOL_BASE; + address public immutable REMOTE_GHO_TOKEN_BASE; // new deployment, not present in address-book + + constructor(address tokenPoolArb, address tokenPoolBase, address ghoTokenBase) { + TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPoolArb); + REMOTE_TOKEN_POOL_BASE = tokenPoolBase; + REMOTE_GHO_TOKEN_BASE = ghoTokenBase; + } + + function execute() external { + IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ + isEnabled: false, + capacity: 0, + rate: 0 + }); + + IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] + memory chains = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](1); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_BASE); + + chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + remoteChainSelector: BASE_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(REMOTE_GHO_TOKEN_BASE), + outboundRateLimiterConfig: emptyRateLimiterConfig, + inboundRateLimiterConfig: emptyRateLimiterConfig + }); + + TOKEN_POOL.applyChainUpdates({ + remoteChainSelectorsToRemove: new uint64[](0), + chainsToAdd: chains + }); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol new file mode 100644 index 000000000..4dcb21a81 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; + +/** + * @dev Test for AaveV3Arbitrum_GHOBaseLaunch_20241223 + * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol -vv + */ +contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { + AaveV3Arbitrum_GHOBaseLaunch_20241223 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('arbitrum'), 287752362); + proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(address(0), address(0), address(0)); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest('AaveV3Arbitrum_GHOBaseLaunch_20241223', AaveV3Arbitrum.POOL, address(proposal)); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol new file mode 100644 index 000000000..79c538865 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +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 {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; + +import {MiscBase} from 'aave-address-book/MiscBase.sol'; +import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; + +/** + * @title GHO Base Launch + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { + uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 public constant ARB_CHAIN_SELECTOR = 4949039107694359620; + + uint128 public constant CCIP_BUCKET_CAPACITY = 25_000_000e18; // 25M GHO + + ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); + + IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; + + address public immutable GHO_TOKEN_IMPL; + address public immutable GHO_CCIP_STEWARD; + + address public immutable REMOTE_TOKEN_POOL_ETH; + address public immutable REMOTE_TOKEN_POOL_ARB; + + constructor( + address tokenPool, + address ghoTokenImpl, + address ghoCcipSteward, + address tokenPoolEth, + address tokenPoolArb + ) { + TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPool); + GHO_TOKEN_IMPL = ghoTokenImpl; + GHO_CCIP_STEWARD = ghoCcipSteward; + REMOTE_TOKEN_POOL_ETH = tokenPoolEth; + REMOTE_TOKEN_POOL_ARB = tokenPoolArb; + } + + function execute() external { + IGhoToken GHO_TOKEN = _deployAndInitializeGhoToken(); + + GHO_TOKEN.grantRole(GHO_TOKEN.FACILITATOR_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); + GHO_TOKEN.grantRole(GHO_TOKEN.BUCKET_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); + GHO_TOKEN.addFacilitator(address(TOKEN_POOL), 'CCIP TokenPool', CCIP_BUCKET_CAPACITY); + + TOKEN_ADMIN_REGISTRY.acceptAdminRole(address(GHO_TOKEN)); + TOKEN_POOL.acceptOwnership(); + + _setupRemoteTokenPools(); + + TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN), address(TOKEN_POOL)); + } + + function _deployAndInitializeGhoToken() internal returns (IGhoToken) { + TransparentUpgradeableProxy tokenProxy = new TransparentUpgradeableProxy( + GHO_TOKEN_IMPL, + MiscBase.PROXY_ADMIN, + abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) + ); + return IGhoToken(address(tokenProxy)); + } + + function _setupRemoteTokenPools() internal { + IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ + isEnabled: false, + capacity: 0, + rate: 0 + }); + + IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] + memory chains = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](2); + + { + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_ETH); + chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + remoteChainSelector: ETH_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(MiscEthereum.GHO_TOKEN), + outboundRateLimiterConfig: emptyRateLimiterConfig, + inboundRateLimiterConfig: emptyRateLimiterConfig + }); + } + + { + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_ARB); + chains[1] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + remoteChainSelector: ARB_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING), + outboundRateLimiterConfig: emptyRateLimiterConfig, + inboundRateLimiterConfig: emptyRateLimiterConfig + }); + } + + TOKEN_POOL.applyChainUpdates({ + remoteChainSelectorsToRemove: new uint64[](0), + chainsToAdd: chains + }); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol new file mode 100644 index 000000000..1b143e9c1 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; + +/** + * @dev Test for AaveV3Base_GHOBaseLaunch_20241223 + * command: FOUNDRY_PROFILE=base forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol -vv + */ +contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { + AaveV3Base_GHOBaseLaunch_20241223 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('base'), 24072751); + proposal = new AaveV3Base_GHOBaseLaunch_20241223( + address(0), + address(0), + address(0), + address(0), + address(0) + ); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest('AaveV3Base_GHOBaseLaunch_20241223', AaveV3Base.POOL, address(proposal)); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol new file mode 100644 index 000000000..e0c293f66 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -0,0 +1,609 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Test.sol'; + +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.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 {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; + +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {MiscBase} from 'aave-address-book/MiscBase.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; +import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; + +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; +import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; +import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; +import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; + +import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; +import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; + +/** + * @dev Test for AaveV3Base_GHOBaseLaunch_20241223 + * command: FOUNDRY_PROFILE=base forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol -vv + */ +contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { + struct Common { + IRouter router; + IGhoToken token; + IEVM2EVMOnRamp arbOnRamp; + IEVM2EVMOnRamp baseOnRamp; + IEVM2EVMOnRamp ethOnRamp; + IEVM2EVMOffRamp_1_5 arbOffRamp; + IEVM2EVMOffRamp_1_5 baseOffRamp; + IEVM2EVMOffRamp_1_5 ethOffRamp; + ITokenAdminRegistry tokenAdminRegistry; + uint64 chainSelector; + uint256 forkId; + } + + struct CCIPSendParams { + Common src; + Common dst; + uint256 amount; + address sender; + } + + struct ARB { + AaveV3Arbitrum_GHOBaseLaunch_20241223 proposal; + IUpgradeableBurnMintTokenPool_1_5_1 tokenPool; + Common c; + } + struct BASE { + AaveV3Base_GHOBaseLaunch_20241223 proposal; + IUpgradeableBurnMintTokenPool_1_5_1 tokenPool; + Common c; + } + struct ETH { + AaveV3Ethereum_GHOBaseLaunch_20241223 proposal; + IUpgradeableLockReleaseTokenPool_1_5_1 tokenPool; + Common c; + } + + ARB internal arb; + BASE internal base; + ETH internal eth; + + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; + address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; + + 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 { + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 287752362); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24072751); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21463360); + + arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); + eth.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + eth.c.token = IGhoToken(MiscEthereum.GHO_TOKEN); + (address newTokenPoolEth, address newTokenPoolArb) = _upgradeEthArbTo1_5_1(); + + arb.c.chainSelector = 4949039107694359620; + base.c.chainSelector = 15971525489660198786; + eth.c.chainSelector = 5009297550715157269; + + vm.selectFork(base.c.forkId); + address ghoTokenImplBase = _deployGhoTokenImpl(); + address ghoTokenBase = _computeCreateAddress(GovernanceV3Base.EXECUTOR_LVL_1); + address newTokenPoolBase = _deployNewBurnMintTokenPool( + ghoTokenBase, + RMN_PROXY_BASE, + ROUTER_BASE, + GovernanceV3Base.EXECUTOR_LVL_1, // owner + MiscBase.PROXY_ADMIN + ); + address ghoCcipStewardBase = _deployNewGhoCcipSteward( + newTokenPoolBase, + ghoTokenBase, + GovernanceV3Base.EXECUTOR_LVL_1, // riskCouncil, using executor for convenience + false // bridgeLimitEnabled, *not present* in remote (burnMint) pools + ); + + vm.selectFork(arb.c.forkId); + arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223( + newTokenPoolArb, + newTokenPoolBase, + ghoTokenBase + ); + arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); + arb.c.router = IRouter(arb.tokenPool.getRouter()); + arb.c.baseOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(base.c.chainSelector)); + arb.c.ethOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(eth.c.chainSelector)); + arb.c.baseOffRamp = IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); + arb.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); + + vm.selectFork(base.c.forkId); + base.proposal = new AaveV3Base_GHOBaseLaunch_20241223( + newTokenPoolBase, + ghoTokenImplBase, + ghoCcipStewardBase, + newTokenPoolEth, + newTokenPoolArb + ); + base.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolBase); + base.c.tokenAdminRegistry = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); + base.c.token = IGhoToken(ghoTokenBase); + base.c.router = IRouter(base.tokenPool.getRouter()); + base.c.arbOnRamp = IEVM2EVMOnRamp(base.c.router.getOnRamp(arb.c.chainSelector)); + base.c.ethOnRamp = IEVM2EVMOnRamp(base.c.router.getOnRamp(eth.c.chainSelector)); + base.c.arbOffRamp = IEVM2EVMOffRamp_1_5(0x7D38c6363d5E4DFD500a691Bc34878b383F58d93); + base.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0xCA04169671A81E4fB8768cfaD46c347ae65371F1); + + vm.selectFork(eth.c.forkId); + eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223( + newTokenPoolEth, + newTokenPoolBase, + ghoTokenBase + ); + eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); + eth.c.router = IRouter(eth.tokenPool.getRouter()); + eth.c.arbOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(arb.c.chainSelector)); + eth.c.baseOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(base.c.chainSelector)); + eth.c.arbOffRamp = IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); + eth.c.baseOffRamp = IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); + + _performCLLPreReq(base.c, GovernanceV3Base.EXECUTOR_LVL_1); + + _validateConstants({executed: false}); + } + + function _upgradeEthArbTo1_5_1() internal returns (address, address) { + // deploy new token pools and ghoCcipStewards + vm.selectFork(eth.c.forkId); + IUpgradeableLockReleaseTokenPool_1_4 existingPoolEth = IUpgradeableLockReleaseTokenPool_1_4( + MiscEthereum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolEth = _deployNewLockReleaseTokenPool( + MiscEthereum.GHO_TOKEN, + existingPoolEth.getArmProxy(), + existingPoolEth.getRouter(), + existingPoolEth.getBridgeLimit(), + GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner + MiscEthereum.PROXY_ADMIN + ); + address newGhoCcipStewardEth = _deployNewGhoCcipSteward( + newTokenPoolEth, + MiscEthereum.GHO_TOKEN, + GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience + true // bridgeLimitEnabled + ); + + vm.selectFork(arb.c.forkId); + IUpgradeableBurnMintTokenPool_1_4 existingPoolArb = IUpgradeableBurnMintTokenPool_1_4( + MiscArbitrum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolArb = _deployNewBurnMintTokenPool( + AaveV3ArbitrumAssets.GHO_UNDERLYING, + existingPoolArb.getArmProxy(), + existingPoolArb.getRouter(), + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner + MiscArbitrum.PROXY_ADMIN + ); + address newGhoCcipStewardArb = _deployNewGhoCcipSteward( + newTokenPoolArb, + AaveV3ArbitrumAssets.GHO_UNDERLYING, + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience + false // bridgeLimitEnabled + ); + + // execute CLL pre-requisites for the proposal + _performCLLPreReq(eth.c, GovernanceV3Ethereum.EXECUTOR_LVL_1); + _performCLLPreReq(arb.c, GovernanceV3Arbitrum.EXECUTOR_LVL_1); + + // execute proposal + { + vm.selectFork(eth.c.forkId); + executePayload( + vm, + address( + new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( + newTokenPoolEth, + newTokenPoolArb, + newGhoCcipStewardEth + ) + ) + ); + + vm.selectFork(arb.c.forkId); + executePayload( + vm, + address( + new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( + newTokenPoolArb, + newTokenPoolEth, + newGhoCcipStewardArb + ) + ) + ); + } + + return (newTokenPoolEth, newTokenPoolArb); + } + + function _deployGhoTokenImpl() internal returns (address) { + return address(new UpgradeableGhoToken()); + } + + function _computeCreateAddress(address deployer) internal view returns (address) { + return vm.computeCreateAddress(deployer, vm.getNonce(deployer)); + } + + function _deployNewBurnMintTokenPool( + address ghoToken, + address rmnProxy, + address router, + address owner, + address proxyAdmin + ) private returns (address) { + address newTokenPoolImpl = address( + new UpgradeableBurnMintTokenPool( + ghoToken, + 18, // optimistic token deployment for base, hence hardcoding 18 decimals for ghoToken + rmnProxy, + false // allowListEnabled + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + address(proxyAdmin), + abi.encodeCall( + IUpgradeableBurnMintTokenPool_1_5_1.initialize, + ( + owner, + new address[](0), // allowList + router + ) + ) + ) + ); + } + + function _deployNewLockReleaseTokenPool( + address ghoToken, + address rmnProxy, + address router, + uint256 bridgeLimit, + address owner, + address proxyAdmin + ) private returns (address) { + address newTokenPoolImpl = address( + new UpgradeableLockReleaseTokenPool( + ghoToken, + 18, // optimistic token deployment for base, hence hardcoding 18 decimals for ghoToken + rmnProxy, + false, // allowListEnabled + true // acceptLiquidity + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + address(proxyAdmin), + abi.encodeCall( + IUpgradeableLockReleaseTokenPool_1_5_1.initialize, + ( + owner, + new address[](0), // allowList + router, + bridgeLimit + ) + ) + ) + ); + } + + function _performCLLPreReq(Common memory c, address newAdmin) internal { + vm.selectFork(c.forkId); + + vm.prank(c.tokenAdminRegistry.owner()); + if (c.forkId == base.c.forkId) { + c.tokenAdminRegistry.proposeAdministrator(address(c.token), newAdmin); + } else { + c.tokenAdminRegistry.transferAdminRole(address(c.token), newAdmin); + } + } + + function _deployNewGhoCcipSteward( + address newTokenPool, + address ghoToken, + address riskCouncil, + bool bridgeLimitEnabled + ) internal returns (address) { + return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); + } + + 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.src.token), + amount: params.amount + }); + + uint256 feeAmount = params.src.router.getFee(params.dst.chainSelector, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: params.src.router, + sourceChainSelector: params.src.chainSelector, + destChainSelector: params.dst.chainSelector, + feeTokenAmount: feeAmount, + originalSender: params.sender, + sourceToken: address(params.src.token), + destinationToken: address(params.dst.token) + }) + ); + + return (message, eventArg); + } + + // todo: expand + function _validateConstants(bool executed) internal { + if (executed) { + vm.selectFork(base.c.forkId); + assertEq(base.proposal.REMOTE_TOKEN_POOL_ETH(), address(eth.tokenPool)); + assertEq(base.proposal.REMOTE_TOKEN_POOL_ARB(), address(arb.tokenPool)); + assertTrue( + base.tokenPool.isRemotePool(eth.c.chainSelector, abi.encode(address(eth.tokenPool))) + ); + assertTrue( + base.tokenPool.isRemotePool(arb.c.chainSelector, abi.encode(address(arb.tokenPool))) + ); + } + } +} + +contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLaunch_20241223_Base { + function setUp() public override { + super.setUp(); + + vm.selectFork(arb.c.forkId); + executePayload(vm, address(arb.proposal)); + + vm.selectFork(eth.c.forkId); + executePayload(vm, address(eth.proposal)); + + vm.selectFork(base.c.forkId); + executePayload(vm, address(base.proposal)); + + _validateConstants({executed: true}); + } + + function test_E2E_Eth_Base(uint256 amount) public { + { + vm.selectFork(eth.c.forkId); + uint256 bridgeableAmount = eth.tokenPool.getBridgeLimit() - + eth.tokenPool.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); + + vm.prank(alice); + eth.c.token.approve(address(eth.c.router), amount); + deal(address(eth.c.token), alice, amount); + + uint256 tokenPoolBalance = eth.c.token.balanceOf(address(eth.tokenPool)); + uint256 aliceBalance = eth.c.token.balanceOf(alice); + uint256 bridgedAmount = eth.tokenPool.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({src: eth.c, dst: base.c, sender: alice, amount: amount}) + ); + + vm.expectEmit(address(eth.tokenPool)); + emit Locked(address(eth.c.baseOnRamp), amount); + vm.expectEmit(address(eth.c.baseOnRamp)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + eth.c.router.ccipSend{value: eventArg.feeTokenAmount}(base.c.chainSelector, message); + + assertEq(eth.c.token.balanceOf(address(eth.tokenPool)), tokenPoolBalance + amount); + assertEq(eth.c.token.balanceOf(alice), aliceBalance - amount); + assertEq(eth.tokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + + // base execute message + vm.selectFork(base.c.forkId); + + assertEq(base.c.token.balanceOf(alice), 0); + assertEq(base.c.token.totalSupply(), 0); // first bridge + assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, 0); // first bridge + + vm.expectEmit(address(base.tokenPool)); + emit Minted(address(base.c.ethOffRamp), alice, amount); + + vm.prank(address(base.c.ethOffRamp)); + base.c.ethOffRamp.executeSingleMessage({ + message: eventArg, + offchainTokenData: new bytes[](message.tokenAmounts.length), + tokenGasOverrides: new uint32[](0) + }); + + assertEq(base.c.token.balanceOf(alice), amount); + assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, amount); + } + + // send amount back to eth + { + // send base from base + vm.selectFork(base.c.forkId); + vm.prank(alice); + base.c.token.approve(address(base.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({src: base.c, dst: eth.c, sender: alice, amount: amount}) + ); + + vm.expectEmit(address(base.tokenPool)); + emit Burned(address(base.c.ethOnRamp), amount); + vm.expectEmit(address(base.c.ethOnRamp)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + base.c.router.ccipSend{value: eventArg.feeTokenAmount}(eth.c.chainSelector, message); + + assertEq(base.c.token.balanceOf(alice), 0); + assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, 0); + + // eth execute message + vm.selectFork(eth.c.forkId); + + uint256 bridgedAmount = eth.tokenPool.getCurrentBridgedAmount(); + + vm.expectEmit(address(eth.tokenPool)); + emit Released(address(eth.c.baseOffRamp), alice, amount); + vm.prank(address(eth.c.baseOffRamp)); + eth.c.baseOffRamp.executeSingleMessage({ + message: eventArg, + offchainTokenData: new bytes[](message.tokenAmounts.length), + tokenGasOverrides: new uint32[](0) + }); + + assertEq(eth.c.token.balanceOf(alice), amount); + assertEq(eth.tokenPool.getCurrentBridgedAmount(), bridgedAmount - amount); + } + } + + function test_E2E_Arb_Base(uint256 amount) public { + { + vm.selectFork(arb.c.forkId); + uint256 bridgeableAmount = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); + + vm.prank(alice); + arb.c.token.approve(address(arb.c.router), amount); + deal(address(arb.c.token), alice, amount); + + uint256 aliceBalance = arb.c.token.balanceOf(alice); + uint256 facilitatorLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({src: arb.c, dst: base.c, sender: alice, amount: amount}) + ); + + vm.expectEmit(address(arb.tokenPool)); + emit Burned(address(arb.c.baseOnRamp), amount); + vm.expectEmit(address(arb.c.baseOnRamp)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + arb.c.router.ccipSend{value: eventArg.feeTokenAmount}(base.c.chainSelector, message); + + assertEq(arb.c.token.balanceOf(alice), aliceBalance - amount); + assertEq( + arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel, + facilitatorLevel - amount + ); + + // base execute message + vm.selectFork(base.c.forkId); + + assertEq(base.c.token.balanceOf(alice), 0); + assertEq(base.c.token.totalSupply(), 0); // first bridge + assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, 0); // first bridge + + vm.expectEmit(address(base.tokenPool)); + emit Minted(address(base.c.arbOffRamp), alice, amount); + + vm.prank(address(base.c.arbOffRamp)); + base.c.arbOffRamp.executeSingleMessage({ + message: eventArg, + offchainTokenData: new bytes[](message.tokenAmounts.length), + tokenGasOverrides: new uint32[](0) + }); + + assertEq(base.c.token.balanceOf(alice), amount); + assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, amount); + } + + // send amount back to arb + { + // send base from base + vm.selectFork(base.c.forkId); + vm.prank(alice); + base.c.token.approve(address(base.c.router), amount); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({src: base.c, dst: arb.c, sender: alice, amount: amount}) + ); + + vm.expectEmit(address(base.tokenPool)); + emit Burned(address(base.c.arbOnRamp), amount); + vm.expectEmit(address(base.c.arbOnRamp)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + base.c.router.ccipSend{value: eventArg.feeTokenAmount}(arb.c.chainSelector, message); + + assertEq(base.c.token.balanceOf(alice), 0); + assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, 0); + + // arb execute message + vm.selectFork(arb.c.forkId); + + uint256 facilitatorLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; + + vm.expectEmit(address(arb.tokenPool)); + emit Minted(address(arb.c.baseOffRamp), alice, amount); + vm.prank(address(arb.c.baseOffRamp)); + arb.c.baseOffRamp.executeSingleMessage({ + message: eventArg, + offchainTokenData: new bytes[](message.tokenAmounts.length), + tokenGasOverrides: new uint32[](0) + }); + + assertEq(arb.c.token.balanceOf(alice), amount); + assertEq( + arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel, + facilitatorLevel + amount + ); + } + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol new file mode 100644 index 000000000..a14e90f8c --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; +import {IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; + +/** + * @title GHO Base Launch + * @author Aave Labs + * - Snapshot: TODO + * - Discussion: TODO + */ +contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { + uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; + + IUpgradeableLockReleaseTokenPool_1_5_1 public immutable TOKEN_POOL; // replace with MiscEthereum.GHO_CCIP_TOKEN_POOL once address-book is updated + + address public immutable REMOTE_TOKEN_POOL_BASE; + address public immutable REMOTE_GHO_TOKEN_BASE; // new deployment, not present in address-book + + constructor(address tokenPoolEth, address tokenPoolBase, address ghoTokenBase) { + TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(tokenPoolEth); + REMOTE_TOKEN_POOL_BASE = tokenPoolBase; + REMOTE_GHO_TOKEN_BASE = ghoTokenBase; + } + + function execute() external { + IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ + isEnabled: false, + capacity: 0, + rate: 0 + }); + + IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[] + memory chains = new IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[](1); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_BASE); + + chains[0] = IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate({ + remoteChainSelector: BASE_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(REMOTE_GHO_TOKEN_BASE), + outboundRateLimiterConfig: emptyRateLimiterConfig, + inboundRateLimiterConfig: emptyRateLimiterConfig + }); + + TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol new file mode 100644 index 000000000..0b9175cd1 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; + +/** + * @dev Test for AaveV3Ethereum_GHOBaseLaunch_20241223 + * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol -vv + */ +contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { + AaveV3Ethereum_GHOBaseLaunch_20241223 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 21463360); + proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(address(0), address(0), address(0)); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest('AaveV3Ethereum_GHOBaseLaunch_20241223', AaveV3Ethereum.POOL, address(proposal)); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md new file mode 100644 index 000000000..dac8d1d39 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md @@ -0,0 +1,22 @@ +--- +title: "GHO Base Launch" +author: "Aave Labs" +discussions: "" +--- + +## Simple Summary + +## Motivation + +## Specification + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol), [AaveV3Base](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol), [AaveV3Base](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.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/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol new file mode 100644 index 000000000..dc4a2baaf --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol @@ -0,0 +1,115 @@ +// 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, BaseScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol'; +import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; +import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; +import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol:DeployEthereum chain=mainnet + * verify-command: FOUNDRY_PROFILE=mainnet npx catapulta-verify -b broadcast/GHOBaseLaunch_20241223.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_GHOBaseLaunch_20241223).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/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol:DeployArbitrum chain=arbitrum + * verify-command: FOUNDRY_PROFILE=arbitrum npx catapulta-verify -b broadcast/GHOBaseLaunch_20241223.s.sol/42161/run-latest.json + */ +contract DeployArbitrum is ArbitrumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Arbitrum_GHOBaseLaunch_20241223).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 Base + * deploy-command: make deploy-ledger contract=src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol:DeployBase chain=base + * verify-command: FOUNDRY_PROFILE=base npx catapulta-verify -b broadcast/GHOBaseLaunch_20241223.s.sol/8453/run-latest.json + */ +contract DeployBase is BaseScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Base_GHOBaseLaunch_20241223).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/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol:CreateProposal chain=mainnet + */ +contract CreateProposal is EthereumScript { + function run() external { + // create payloads + PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](3); + + // compose actions for validation + IPayloadsControllerCore.ExecutionAction[] + memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsEthereum[0] = GovV3Helpers.buildAction( + type(AaveV3Ethereum_GHOBaseLaunch_20241223).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + IPayloadsControllerCore.ExecutionAction[] + memory actionsArbitrum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsArbitrum[0] = GovV3Helpers.buildAction( + type(AaveV3Arbitrum_GHOBaseLaunch_20241223).creationCode + ); + payloads[1] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum); + + IPayloadsControllerCore.ExecutionAction[] + memory actionsBase = new IPayloadsControllerCore.ExecutionAction[](1); + actionsBase[0] = GovV3Helpers.buildAction(type(AaveV3Base_GHOBaseLaunch_20241223).creationCode); + payloads[2] = GovV3Helpers.buildBasePayload(vm, actionsBase); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovernanceV3Ethereum.VOTING_PORTAL_ETH_POL, + GovV3Helpers.ipfsHashFile(vm, 'src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md') + ); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts new file mode 100644 index 000000000..bd8b7e9c3 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -0,0 +1,18 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum', 'AaveV3Arbitrum', 'AaveV3Base'], + title: 'GHO Base Launch', + shortName: 'GHOBaseLaunch', + date: '20241223', + author: 'Aave Labs', + discussion: '', + snapshot: '', + votingNetwork: 'POLYGON', + }, + poolOptions: { + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21463360}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 287752362}}, + AaveV3Base: {configs: {OTHERS: {}}, cache: {blockNumber: 24072751}}, + }, +}; diff --git a/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol b/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol new file mode 100644 index 000000000..7a8e93d46 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +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; + uint64 destChainSelector; + uint256 feeTokenAmount; + address originalSender; + address sourceToken; + address destinationToken; + } + + 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) { + IEVM2EVMOnRamp onRamp = IEVM2EVMOnRamp(params.router.getOnRamp(params.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: '' + }); + + for (uint256 i; i < params.message.tokenAmounts.length; ++i) { + messageEvent.sourceTokenData[i] = abi.encode( + SourceTokenData({ + sourcePoolAddress: abi.encode( + onRamp.getPoolBySourceToken( + params.destChainSelector, + params.message.tokenAmounts[i].token + ) + ), + destTokenAddress: abi.encode(params.destinationToken), + extraData: abi.encode(getTokenDecimals(params.sourceToken)), + destGasAmount: getDestGasAmount(onRamp, params.message.tokenAmounts[i].token) + }) + ); + } + + messageEvent.messageId = hash( + messageEvent, + generateMetadataHash(params.sourceChainSelector, params.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)) + ) + ); + } + + 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; + } + + function getTokenDecimals(address token) internal view returns (uint8) { + (bool success, bytes memory data) = token.staticcall(abi.encodeWithSignature('decimals()')); + require(success, 'CCIPUtils: failed to get token decimals'); + return abi.decode(data, (uint8)); + } +} diff --git a/src/interfaces/IGhoToken.sol b/src/interfaces/IGhoToken.sol index 96fc71c24..d1b212853 100644 --- a/src/interfaces/IGhoToken.sol +++ b/src/interfaces/IGhoToken.sol @@ -70,6 +70,12 @@ interface IGhoToken is IERC20 { */ function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256); + /** + * @notice Returns the identifier of the Facilitator Manager Role + * @return The bytes32 id hash of the FacilitatorManager role + */ + function FACILITATOR_MANAGER_ROLE() external pure returns (bytes32); + /** * @notice Returns the identifier of the Bucket Manager Role * @return The bytes32 id hash of the BucketManager role From f02b9d168477c7140b517e797ebd5827ab02df70 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 01:43:41 +0530 Subject: [PATCH 029/123] chore: upd ccip lib --- lib/ccip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ccip b/lib/ccip index a2e92d0e7..a3ff6f570 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit a2e92d0e7fdae6f62f94ce90e1fac613fa04371d +Subproject commit a3ff6f570de333ce7d3a1234ec1c9a1b448bcdc6 From 3f5dc31bfdd3ac09355d8511c2abfe5a4dc729c3 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:24:20 +0530 Subject: [PATCH 030/123] test: cleanup & fuzzify --- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 65c3bab80..bb43397d7 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -247,10 +247,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base { - function setUp() public override { - super.setUp(); - } - function test_defaultProposalExecution() public { defaultTest( 'AaveV3Arbitrum_GHOCCIP151Upgrade_20241209', @@ -356,8 +352,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is executePayload(vm, address(proposal)); } - function test_sendMessageSucceedsAndRoutesViaNewPool() public { - uint256 amount = 100_000e18; + function test_sendMessageSucceedsAndRoutesViaNewPool(uint256 amount) public { + uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); deal(address(GHO), alice, amount); vm.prank(alice); @@ -406,8 +403,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // on-ramp via new pool - function test_lockOrBurnSucceedsOnNewPool() public { - uint256 amount = 100_000e18; + function test_lockOrBurnSucceedsOnNewPool(uint256 amount) public { + uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(NEW_TOKEN_POOL), amount); @@ -448,10 +446,13 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from new eth token pool (v1.5.1) - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth(uint256 amount) public { + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(NEW_TOKEN_POOL) + ); + uint256 mintAbleAmount = bucketCapacity - bucketLevel; + amount = bound(amount, 1, mintAbleAmount); - uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; uint256 aliceBalance = GHO.balanceOf(alice); vm.expectEmit(address(NEW_TOKEN_POOL)); @@ -476,10 +477,15 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth( + uint256 amount + ) public { + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(NEW_TOKEN_POOL) + ); + uint256 mintAbleAmount = bucketCapacity - bucketLevel; + amount = bound(amount, 1, mintAbleAmount); - uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; uint256 aliceBalance = GHO.balanceOf(alice); vm.expectEmit(address(NEW_TOKEN_POOL)); From bb88ac1f2772356f56c32a0ae2fe10677fabca10 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:30:03 +0530 Subject: [PATCH 031/123] test: cleanup & fuzzify --- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 81ab6cfcf..5b66ffbf0 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -262,10 +262,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base { - function setUp() public override { - super.setUp(); - } - /** * @dev executes the generic test suite including e2e and config snapshots */ @@ -374,8 +370,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is executePayload(vm, address(proposal)); } - function test_sendMessageSucceedsAndRoutesViaNewPool() public { - uint256 amount = 100_000e18; + function test_sendMessageSucceedsAndRoutesViaNewPool(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - + NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); deal(address(GHO), alice, amount); vm.prank(alice); @@ -425,8 +423,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // on-ramp via new pool - function test_lockOrBurnSucceedsOnNewPool() public { - uint256 amount = 100_000e18; + function test_lockOrBurnSucceedsOnNewPool(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - + NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); // router pulls tokens from the user & sends to the token pool during onRamps // we don't override NEW_TOKEN_POOL balance here & instead transfer because we want @@ -475,8 +475,9 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from new eth token pool (v1.5.1) - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); uint256 aliceBalance = GHO.balanceOf(alice); uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); @@ -505,8 +506,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth( + uint256 amount + ) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); uint256 aliceBalance = GHO.balanceOf(alice); uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); From fe0368a40fc2aaa746606d56ee7f0000726065d2 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:14:22 +0530 Subject: [PATCH 032/123] chore: use latest deployment of existing remote pool upgrade --- lib/ccip | 2 +- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 6 +----- src/20241209_Multi_GHOCCIP151Upgrade/config.ts | 2 +- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/ccip b/lib/ccip index a3ff6f570..ca12f6398 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit a3ff6f570de333ce7d3a1234ec1c9a1b448bcdc6 +Subproject commit ca12f6398157d7a0526bc3f153d69566884d9dd0 diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index d03a8df00..8625ddd07 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -36,9 +36,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH address public immutable NEW_REMOTE_POOL_ETH; - // https://arbiscan.io/address/0x360d8aa8F6b09B7BC57aF34db2Eb84dD87bf4d12 + // https://arbiscan.io/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = - 0x360d8aa8F6b09B7BC57aF34db2Eb84dD87bf4d12; // from https://github.com/aave/ccip/pull/21 (commit f684d950178fbdc95f543382fac472cf47434d55) + 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index bb43397d7..719c5442c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -74,7 +74,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 287752362); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 288070365); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index b428a7f46..a2329290e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -87,7 +87,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function setUp() public virtual { l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21366260); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 287752362); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); vm.selectFork(l1.c.forkId); address newTokenPoolEth = _deployNewTokenPoolEth(); @@ -521,10 +521,6 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_PostUpgrade is contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is AaveV3E2E_GHOCCIP151Upgrade_20241209_Base { - function setUp() public override { - super.setUp(); - } - function test_E2E_InFlightMsg_FromEth() public { vm.selectFork(l1.c.forkId); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index 833e1934b..e2cb8b937 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -12,6 +12,6 @@ export const config: ConfigFile = { }, poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21366260}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 287752362}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, }, }; From 8c8ce066150548b16305b03479e33d2a04a60c5a Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:20:10 +0530 Subject: [PATCH 033/123] doc: snapshot -> direct-to-aip --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 1 - .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 1 - src/20241209_Multi_GHOCCIP151Upgrade/config.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 8625ddd07..9a93c3a7e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -15,7 +15,6 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs - * - Snapshot: TODO * - Discussion: TODO */ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 6372a59c1..545cef1ea 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -11,7 +11,6 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs - * - Snapshot: TODO * - Discussion: TODO */ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index e2cb8b937..15ad2de6e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -7,7 +7,7 @@ export const config: ConfigFile = { date: '20241209', author: 'Aave Labs', discussion: '', - snapshot: '', + snapshot: 'Direct-to-AIP', votingNetwork: 'POLYGON', }, poolOptions: { From 37d1eb6b4a4b205f95362833ddb30fb11fd4eb8c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:24:01 +0530 Subject: [PATCH 034/123] chore: import gho from EthereumAssets instead of MiscEthereum --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 9 ++++++--- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 7 ++++--- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 5 +++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 11 ++++++----- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 9a93c3a7e..46444fe41 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -8,8 +8,8 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** @@ -92,7 +92,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: ETH_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, - remoteTokenAddress: abi.encode(MiscEthereum.GHO_TOKEN), + remoteTokenAddress: abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING), outboundRateLimiterConfig: emptyRateLimiterConfig, inboundRateLimiterConfig: emptyRateLimiterConfig }); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 719c5442c..661ee947a 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -18,9 +18,9 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; @@ -183,7 +183,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { feeTokenAmount: feeAmount, originalSender: params.sender, sourceToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, - destinationToken: MiscEthereum.GHO_TOKEN, + destinationToken: AaveV3EthereumAssets.GHO_UNDERLYING, poolVersion: params.poolVersion }) ); @@ -321,7 +321,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 2); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(ETH_PROXY_POOL))); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ETH))); - assertEq(NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), abi.encode(MiscEthereum.GHO_TOKEN)); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), + abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING) + ); assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 1); assertTrue(NEW_TOKEN_POOL.isSupportedChain(ETH_CHAIN_SELECTOR)); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index a2329290e..8e58872d6 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -14,6 +14,7 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; @@ -93,7 +94,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address newTokenPoolEth = _deployNewTokenPoolEth(); address newGhoCcipStewardEth = _deployNewGhoCcipSteward( newTokenPoolEth, - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience true // bridgeLimitEnabled ); @@ -178,7 +179,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _validateConfig(bool upgraded) internal { vm.selectFork(l1.c.forkId); assertEq(l1.c.chainSelector, 5009297550715157269); - assertEq(address(l1.c.token), MiscEthereum.GHO_TOKEN); + assertEq(address(l1.c.token), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(l1.c.router.typeAndVersion(), 'Router 1.2.0'); assertEq(l1.c.EVM2EVMOnRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(l1.c.EVM2EVMOffRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); @@ -265,7 +266,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { vm.selectFork(l1.c.forkId); vm.prank(l1.c.tokenAdminRegistry.owner()); l1.c.tokenAdminRegistry.transferAdminRole( - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1 ); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 545cef1ea..82219c3a4 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -6,6 +6,7 @@ import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGen import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** @@ -46,7 +47,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // pre-req - chainlink transfers gho token pool ownership on token admin registry function _acceptOwnership() internal { NEW_TOKEN_POOL.acceptOwnership(); - TOKEN_ADMIN_REGISTRY.acceptAdminRole(MiscEthereum.GHO_TOKEN); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(AaveV3EthereumAssets.GHO_UNDERLYING); } function _migrateLiquidity() internal { @@ -89,6 +90,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { NEW_TOKEN_POOL.setBridgeLimitAdmin(NEW_GHO_CCIP_STEWARD); // register new pool - TOKEN_ADMIN_REGISTRY.setPool(MiscEthereum.GHO_TOKEN, address(NEW_TOKEN_POOL)); + TOKEN_ADMIN_REGISTRY.setPool(AaveV3EthereumAssets.GHO_UNDERLYING, address(NEW_TOKEN_POOL)); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 5b66ffbf0..c941cffda 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -21,6 +21,7 @@ import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; @@ -44,7 +45,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; - IGhoToken internal constant GHO = IGhoToken(MiscEthereum.GHO_TOKEN); + IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); address internal constant ARB_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; @@ -88,7 +89,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { // pre-req - chainlink transfers gho token pool ownership on token admin registry vm.prank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.transferAdminRole( - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1 ); @@ -166,7 +167,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); - assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *present* on eth token pool } @@ -176,7 +177,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { IClient.EVM2AnyMessage memory message = CCIPUtils.generateMessage(params.sender, 1); message.tokenAmounts[0] = IClient.EVMTokenAmount({ - token: MiscEthereum.GHO_TOKEN, + token: AaveV3EthereumAssets.GHO_UNDERLYING, amount: params.amount }); @@ -190,7 +191,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { sourceChainSelector: ETH_CHAIN_SELECTOR, feeTokenAmount: feeAmount, originalSender: params.sender, - sourceToken: MiscEthereum.GHO_TOKEN, + sourceToken: AaveV3EthereumAssets.GHO_UNDERLYING, destinationToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, poolVersion: params.poolVersion }) From 141e49db35858189de5e75a014f5aa028d5c556f Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:35:13 +0530 Subject: [PATCH 035/123] chore: cleanup rm ProxyAdmin reference --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 46444fe41..d4befc56c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -39,7 +39,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb - ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); constructor(address newTokenPoolArb, address newTokenPoolEth, address newGhoCcipSteward) { @@ -109,7 +108,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { } function _upgradeExistingTokenPool() internal { - PROXY_ADMIN.upgrade( + ProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), EXISTING_TOKEN_POOL_UPGRADE_IMPL ); From 62b189bc32e7f99dc41a10196ecccc0fb8117a7e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:37:07 +0530 Subject: [PATCH 036/123] chore: rename facilitator --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 2 +- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index d4befc56c..a813d56a8 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -65,7 +65,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address(EXISTING_TOKEN_POOL) ); - GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); + GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP TokenPool v1.5.1 ', uint128(bucketCapacity)); NEW_TOKEN_POOL.directMint(address(EXISTING_TOKEN_POOL), bucketLevel); // increase facilitator level _upgradeExistingTokenPool(); // introduce `directBurn` method diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 661ee947a..dd0422342 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -292,7 +292,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is newFacilitator = GHO.getFacilitator(address(NEW_TOKEN_POOL)); - assertEq(newFacilitator.label, 'CCIP v1.5.1 TokenPool'); + assertEq(newFacilitator.label, 'CCIP TokenPool v1.5.1 '); assertEq(newFacilitator.bucketCapacity, existingFacilitator.bucketCapacity); assertEq(newFacilitator.bucketLevel, existingFacilitator.bucketLevel); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 8e58872d6..2ef55c4fd 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -247,7 +247,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { if (upgraded) { assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), address(l2.newTokenPool)); assertEq(bytes(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label).length, 0); - assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP v1.5.1 TokenPool'); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP TokenPool v1.5.1 '); } else { assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), l2.c.proxyPool); assertEq(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label, 'CCIP TokenPool'); From b8e50a6a754c912c18fcf0920d69ffa0b30e4663 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:43:56 +0530 Subject: [PATCH 037/123] chore: rm duplicate check --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 7 +------ .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index dd0422342..6d9879dee 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -204,12 +204,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _getDynamicParams(address tokenPool) internal view returns (bytes memory) { IUpgradeableBurnMintTokenPool_1_4 ghoTokenPool = IUpgradeableBurnMintTokenPool_1_4(tokenPool); - return - abi.encode( - ghoTokenPool.owner(), - ghoTokenPool.getSupportedChains(), - ghoTokenPool.getAllowListEnabled() - ); + return abi.encode(ghoTokenPool.owner(), ghoTokenPool.getSupportedChains()); } function _tokenBucketToConfig( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index c941cffda..37bf4635b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -222,7 +222,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { abi.encode( ghoTokenPool.owner(), ghoTokenPool.getSupportedChains(), - ghoTokenPool.getAllowListEnabled(), ghoTokenPool.getRebalancer(), ghoTokenPool.getBridgeLimit() ); From 7c0b73df0151deeb8862ea175312af64119ca789 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 25 Dec 2024 17:07:52 +0530 Subject: [PATCH 038/123] fix: updates based on upstream changes from https://github.com/bgd-labs/aave-proposals-v3/pull/527 --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md | 10 ---------- ...eV3Ethereum_GHOCCIP151Upgrade_20241209_after.md | 14 -------------- remappings.txt | 9 ++++++++- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 8 ++++---- ...AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 6 ++++-- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 11 +++++++---- ...AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 6 ++++-- 7 files changed, 27 insertions(+), 37 deletions(-) diff --git a/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md b/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md index 4d686addb..c15d3e2bc 100644 --- a/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md +++ b/diffs/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_before_AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_after.md @@ -1,13 +1,3 @@ -## Emodes changed - -### EMode: Stablecoins(id: 1) - - - -### EMode: ETH correlated(id: 2) - - - ## Raw diff ```json diff --git a/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md b/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md index 95861275d..c15d3e2bc 100644 --- a/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md +++ b/diffs/AaveV3Ethereum_GHOCCIP151Upgrade_20241209_before_AaveV3Ethereum_GHOCCIP151Upgrade_20241209_after.md @@ -1,17 +1,3 @@ -## Emodes changed - -### EMode: ETH correlated(id: 1) - - - -### EMode: sUSDe Stablecoins(id: 2) - - - -### EMode: rsETH LST main(id: 3) - - - ## Raw diff ```json diff --git a/remappings.txt b/remappings.txt index 1cd25c526..9c8cea061 100644 --- a/remappings.txt +++ b/remappings.txt @@ -2,6 +2,13 @@ aave-address-book/=lib/aave-helpers/lib/aave-address-book/src/ 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 +solidity-utils/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/src/ +@openzeppelin/contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/ +@openzeppelin/contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ +aave-v3-origin-tests/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/tests/ +ds-test/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/ +erc4626-tests/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ +openzeppelin-contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/ +openzeppelin-contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/ aave-ccip/=lib/ccip/contracts/src/v0.8/ccip gho-core/=lib/gho-core/src/contracts diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index a813d56a8..0b23d6ee1 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT 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 {ITransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {ILegacyProxyAdmin} from 'src/interfaces/ILegacyProxyAdmin.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; @@ -108,8 +108,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { } function _upgradeExistingTokenPool() internal { - ProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( - TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), + ILegacyProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( + ITransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), EXISTING_TOKEN_POOL_UPGRADE_IMPL ); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 6d9879dee..d8d1d485f 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -21,9 +21,11 @@ import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; @@ -92,7 +94,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _deployNewTokenPoolArb() private returns (address) { IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( - MiscArbitrum.GHO_CCIP_TOKEN_POOL + GhoArbitrum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolImpl = address( new UpgradeableBurnMintTokenPool( @@ -106,7 +108,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - address(MiscArbitrum.PROXY_ADMIN), + ProxyAdmin(MiscArbitrum.PROXY_ADMIN), abi.encodeCall( IUpgradeableBurnMintTokenPool_1_5_1.initialize, ( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 2ef55c4fd..070df68c6 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -16,12 +16,15 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; @@ -280,7 +283,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _deployNewTokenPoolEth() private returns (address) { IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( - MiscEthereum.GHO_CCIP_TOKEN_POOL + GhoEthereum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolImpl = address( new UpgradeableLockReleaseTokenPool( @@ -296,7 +299,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - MiscEthereum.PROXY_ADMIN, + ProxyAdmin(MiscEthereum.PROXY_ADMIN), abi.encodeCall( IUpgradeableLockReleaseTokenPool_1_5_1.initialize, ( @@ -312,7 +315,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _deployNewTokenPoolArb() private returns (address) { IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( - MiscArbitrum.GHO_CCIP_TOKEN_POOL + GhoArbitrum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolImpl = address( new UpgradeableBurnMintTokenPool( @@ -326,7 +329,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - address(MiscArbitrum.PROXY_ADMIN), + ProxyAdmin(MiscArbitrum.PROXY_ADMIN), abi.encodeCall( IUpgradeableBurnMintTokenPool_1_5_1.initialize, ( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 37bf4635b..e9c4241ce 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -18,6 +18,7 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -25,6 +26,7 @@ import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; @@ -98,7 +100,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _deployNewTokenPoolEth() private returns (address) { IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( - MiscEthereum.GHO_CCIP_TOKEN_POOL + GhoEthereum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolImpl = address( new UpgradeableLockReleaseTokenPool( @@ -114,7 +116,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - MiscEthereum.PROXY_ADMIN, + ProxyAdmin(MiscEthereum.PROXY_ADMIN), abi.encodeCall( IUpgradeableLockReleaseTokenPool_1_5_1.initialize, ( From bcd843ab73a2e49594a1f4fd0e31db3b51abfcb9 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 25 Dec 2024 17:20:07 +0530 Subject: [PATCH 039/123] chore: fix&add comment, use chain selector from helper lib --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index d8d1d485f..d633097fe 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -43,8 +43,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { CCIPUtils.PoolVersion poolVersion; } - uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; - uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; IGhoToken internal constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index e9c4241ce..d4d1b687c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -44,8 +44,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { CCIPUtils.PoolVersion poolVersion; } - uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; - uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = @@ -414,6 +414,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); + // since we disable the bridge by resetting the bridge limit to 0 vm.expectRevert(abi.encodeWithSelector(BridgeLimitExceeded.selector, 0)); EXISTING_TOKEN_POOL.lockOrBurn( alice, @@ -432,7 +433,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is // router pulls tokens from the user & sends to the token pool during onRamps // we don't override NEW_TOKEN_POOL balance here & instead transfer because we want - // to check the invariant GHO.balanceOf(tokenPool) == tokenPool.currentBridgedAmount() + // to check the invariant GHO.balanceOf(tokenPool) >= tokenPool.currentBridgedAmount() deal(address(GHO), address(alice), amount); vm.prank(alice); GHO.transfer(address(NEW_TOKEN_POOL), amount); From be4396aa6d149de12080afa7cd7f4d801018f96e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 01:43:41 +0530 Subject: [PATCH 040/123] chore: upd ccip lib --- lib/ccip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ccip b/lib/ccip index a2e92d0e7..a3ff6f570 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit a2e92d0e7fdae6f62f94ce90e1fac613fa04371d +Subproject commit a3ff6f570de333ce7d3a1234ec1c9a1b448bcdc6 From ac516af642c985114d49b32e2307cd8438cf68c3 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:50:00 +0530 Subject: [PATCH 041/123] feat: expand _validateConfig in e2e test --- lib/ccip | 2 +- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 2 - .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 217 +++++++++++++++++- src/interfaces/ccip/IEVM2EVMOffRamp.sol | 32 +++ src/interfaces/ccip/IEVM2EVMOnRamp.sol | 17 ++ 5 files changed, 256 insertions(+), 14 deletions(-) diff --git a/lib/ccip b/lib/ccip index a3ff6f570..a2e92d0e7 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit a3ff6f570de333ce7d3a1234ec1c9a1b448bcdc6 +Subproject commit a2e92d0e7fdae6f62f94ce90e1fac613fa04371d diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 79c538865..6b3a0f1de 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT 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 {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index e0c293f66..9871a5ce1 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -5,13 +5,15 @@ import 'forge-std/Test.sol'; import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; -import {IClient} from 'src/interfaces/ccip/IClient.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; +import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; @@ -173,7 +175,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { _performCLLPreReq(base.c, GovernanceV3Base.EXECUTOR_LVL_1); - _validateConstants({executed: false}); + _validateConfig({executed: false}); } function _upgradeEthArbTo1_5_1() internal returns (address, address) { @@ -374,20 +376,213 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { return (message, eventArg); } - // todo: expand - function _validateConstants(bool executed) internal { + function _validateConfig(bool executed) internal { + vm.selectFork(arb.c.forkId); + assertEq(arb.c.chainSelector, 4949039107694359620); + assertEq(address(arb.c.token), AaveV3ArbitrumAssets.GHO_UNDERLYING); + assertEq(arb.c.router.typeAndVersion(), 'Router 1.2.0'); + _assertOnRamp(arb.c.baseOnRamp, arb.c.chainSelector, base.c.chainSelector, arb.c.router); + _assertOnRamp(arb.c.ethOnRamp, arb.c.chainSelector, eth.c.chainSelector, arb.c.router); + _assertOffRamp(arb.c.baseOffRamp, base.c.chainSelector, arb.c.chainSelector, arb.c.router); + _assertOffRamp(arb.c.ethOffRamp, eth.c.chainSelector, arb.c.chainSelector, arb.c.router); + + // proposal constants + assertEq(arb.proposal.BASE_CHAIN_SELECTOR(), base.c.chainSelector); + assertEq(address(arb.proposal.TOKEN_POOL()), address(arb.tokenPool)); + assertEq(arb.proposal.REMOTE_TOKEN_POOL_BASE(), address(base.tokenPool)); + assertEq(arb.proposal.REMOTE_GHO_TOKEN_BASE(), address(base.c.token)); + + vm.selectFork(base.c.forkId); + assertEq(base.c.chainSelector, 15971525489660198786); + assertEq(base.c.router.typeAndVersion(), 'Router 1.2.0'); + _assertOnRamp(base.c.arbOnRamp, base.c.chainSelector, arb.c.chainSelector, base.c.router); + _assertOnRamp(base.c.ethOnRamp, base.c.chainSelector, eth.c.chainSelector, base.c.router); + _assertOffRamp(base.c.arbOffRamp, arb.c.chainSelector, base.c.chainSelector, base.c.router); + _assertOffRamp(base.c.ethOffRamp, eth.c.chainSelector, base.c.chainSelector, base.c.router); + + // proposal constants + assertEq(base.proposal.ETH_CHAIN_SELECTOR(), eth.c.chainSelector); + assertEq(base.proposal.ARB_CHAIN_SELECTOR(), arb.c.chainSelector); + assertEq(base.proposal.CCIP_BUCKET_CAPACITY(), 25_000_000e18); + assertEq(address(base.proposal.TOKEN_ADMIN_REGISTRY()), address(base.c.tokenAdminRegistry)); + assertEq(address(base.proposal.TOKEN_POOL()), address(base.tokenPool)); + IGhoCcipSteward ghoCcipSteward = IGhoCcipSteward(base.proposal.GHO_CCIP_STEWARD()); + assertEq(ghoCcipSteward.GHO_TOKEN_POOL(), address(base.tokenPool)); + assertEq(ghoCcipSteward.GHO_TOKEN(), address(base.c.token)); + assertEq(base.proposal.REMOTE_TOKEN_POOL_ETH(), address(eth.tokenPool)); + assertEq(base.proposal.REMOTE_TOKEN_POOL_ARB(), address(arb.tokenPool)); + + vm.selectFork(eth.c.forkId); + assertEq(eth.c.chainSelector, 5009297550715157269); + assertEq(address(eth.c.token), MiscEthereum.GHO_TOKEN); + assertEq(eth.c.router.typeAndVersion(), 'Router 1.2.0'); + _assertOnRamp(eth.c.arbOnRamp, eth.c.chainSelector, arb.c.chainSelector, eth.c.router); + _assertOnRamp(eth.c.baseOnRamp, eth.c.chainSelector, base.c.chainSelector, eth.c.router); + _assertOffRamp(eth.c.arbOffRamp, arb.c.chainSelector, eth.c.chainSelector, eth.c.router); + _assertOffRamp(eth.c.baseOffRamp, base.c.chainSelector, eth.c.chainSelector, eth.c.router); + + // proposal constants + assertEq(eth.proposal.BASE_CHAIN_SELECTOR(), base.c.chainSelector); + assertEq(address(eth.proposal.TOKEN_POOL()), address(eth.tokenPool)); + assertEq(eth.proposal.REMOTE_TOKEN_POOL_BASE(), address(base.tokenPool)); + assertEq(eth.proposal.REMOTE_GHO_TOKEN_BASE(), address(base.c.token)); + if (executed) { + vm.selectFork(arb.c.forkId); + assertEq(arb.c.tokenAdminRegistry.getPool(address(arb.c.token)), address(arb.tokenPool)); + assertEq(arb.tokenPool.getSupportedChains()[0], eth.c.chainSelector); + assertEq(arb.tokenPool.getSupportedChains()[1], base.c.chainSelector); + assertEq(arb.tokenPool.getRemoteToken(eth.c.chainSelector), abi.encode(address(eth.c.token))); + assertEq( + arb.tokenPool.getRemoteToken(base.c.chainSelector), + abi.encode(address(base.c.token)) + ); + assertEq(arb.tokenPool.getRemotePools(base.c.chainSelector).length, 1); + assertEq( + arb.tokenPool.getRemotePools(base.c.chainSelector)[0], + abi.encode(address(base.tokenPool)) + ); + assertEq(arb.tokenPool.getRemotePools(eth.c.chainSelector).length, 2); + assertEq( + arb.tokenPool.getRemotePools(eth.c.chainSelector)[1], // 0th is the 1.4 token pool + abi.encode(address(eth.tokenPool)) + ); + _assertDisabledRateLimit(arb.c, address(arb.tokenPool)); + vm.selectFork(base.c.forkId); - assertEq(base.proposal.REMOTE_TOKEN_POOL_ETH(), address(eth.tokenPool)); - assertEq(base.proposal.REMOTE_TOKEN_POOL_ARB(), address(arb.tokenPool)); - assertTrue( - base.tokenPool.isRemotePool(eth.c.chainSelector, abi.encode(address(eth.tokenPool))) + assertEq(base.proposal.GHO_TOKEN_IMPL(), _getImplementation(address(base.c.token))); + assertEq(base.c.tokenAdminRegistry.getPool(address(base.c.token)), address(base.tokenPool)); + assertEq(base.tokenPool.getSupportedChains()[0], eth.c.chainSelector); + assertEq(base.tokenPool.getSupportedChains()[1], arb.c.chainSelector); + assertEq( + base.tokenPool.getRemoteToken(arb.c.chainSelector), + abi.encode(address(arb.c.token)) + ); + assertEq( + base.tokenPool.getRemoteToken(eth.c.chainSelector), + abi.encode(address(eth.c.token)) + ); + assertEq(base.tokenPool.getRemotePools(arb.c.chainSelector).length, 1); + assertEq( + base.tokenPool.getRemotePools(arb.c.chainSelector)[0], + abi.encode(address(arb.tokenPool)) + ); + assertEq(base.tokenPool.getRemotePools(eth.c.chainSelector).length, 1); + assertEq( + base.tokenPool.getRemotePools(eth.c.chainSelector)[0], + abi.encode(address(eth.tokenPool)) + ); + _assertDisabledRateLimit(base.c, address(base.tokenPool)); + + vm.selectFork(eth.c.forkId); + assertEq(eth.c.tokenAdminRegistry.getPool(address(eth.c.token)), address(eth.tokenPool)); + assertEq(eth.tokenPool.getSupportedChains()[0], arb.c.chainSelector); + assertEq(eth.tokenPool.getSupportedChains()[1], base.c.chainSelector); + assertEq(eth.tokenPool.getRemoteToken(arb.c.chainSelector), abi.encode(address(arb.c.token))); + assertEq( + eth.tokenPool.getRemoteToken(base.c.chainSelector), + abi.encode(address(base.c.token)) + ); + assertEq(eth.tokenPool.getRemotePools(arb.c.chainSelector).length, 2); + assertEq( + eth.tokenPool.getRemotePools(arb.c.chainSelector)[1], // 0th is the 1.4 token pool + abi.encode(address(arb.tokenPool)) ); - assertTrue( - base.tokenPool.isRemotePool(arb.c.chainSelector, abi.encode(address(arb.tokenPool))) + assertEq(eth.tokenPool.getRemotePools(base.c.chainSelector).length, 1); + assertEq( + eth.tokenPool.getRemotePools(base.c.chainSelector)[0], + abi.encode(address(base.tokenPool)) ); + _assertDisabledRateLimit(eth.c, address(eth.tokenPool)); } } + + function _assertOnRamp( + IEVM2EVMOnRamp onRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(onRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(onRamp.getStaticConfig().chainSelector, srcSelector); + assertEq(onRamp.getStaticConfig().destChainSelector, dstSelector); + assertEq(onRamp.getDynamicConfig().router, address(router)); + assertEq(router.getOnRamp(dstSelector), address(onRamp)); + } + + function _assertOffRamp( + IEVM2EVMOffRamp_1_5 offRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(offRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + assertEq(offRamp.getStaticConfig().sourceChainSelector, srcSelector); + assertEq(offRamp.getStaticConfig().chainSelector, dstSelector); + assertEq(offRamp.getDynamicConfig().router, address(router)); + assertTrue(router.isOffRamp(srcSelector, address(offRamp))); + } + + function _assertDisabledRateLimit(Common memory src, address tokenPool) internal view { + (Common memory dst1, Common memory dst2) = _getDestination(src); + IUpgradeableLockReleaseTokenPool_1_5_1 _tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( + tokenPool + ); + assertEq( + _tokenPool.getCurrentInboundRateLimiterState(dst1.chainSelector), + _getDisabledConfig() + ); + assertEq( + _tokenPool.getCurrentOutboundRateLimiterState(dst1.chainSelector), + _getDisabledConfig() + ); + + assertEq( + _tokenPool.getCurrentInboundRateLimiterState(dst2.chainSelector), + _getDisabledConfig() + ); + assertEq( + _tokenPool.getCurrentOutboundRateLimiterState(dst2.chainSelector), + _getDisabledConfig() + ); + } + + function _getDestination(Common memory src) internal view returns (Common memory, Common memory) { + if (src.forkId == arb.c.forkId) return (base.c, eth.c); + else if (src.forkId == base.c.forkId) return (arb.c, eth.c); + else return (arb.c, base.c); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() internal pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + } } contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLaunch_20241223_Base { @@ -403,7 +598,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa vm.selectFork(base.c.forkId); executePayload(vm, address(base.proposal)); - _validateConstants({executed: true}); + _validateConfig({executed: true}); } function test_E2E_Eth_Base(uint256 amount) public { diff --git a/src/interfaces/ccip/IEVM2EVMOffRamp.sol b/src/interfaces/ccip/IEVM2EVMOffRamp.sol index d9d132f5f..34f565594 100644 --- a/src/interfaces/ccip/IEVM2EVMOffRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOffRamp.sol @@ -20,6 +20,38 @@ interface IEVM2EVMOffRamp_1_2 is ITypeAndVersion { } interface IEVM2EVMOffRamp_1_5 is ITypeAndVersion { + /// @notice Static offRamp config + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + //solhint-disable gas-struct-packing + struct StaticConfig { + address commitStore; // ────────╮ CommitStore address on the destination chain + uint64 chainSelector; // ───────╯ Destination chainSelector + uint64 sourceChainSelector; // ─╮ Source chainSelector + address onRamp; // ─────────────╯ OnRamp address on the source chain + address prevOffRamp; // Address of previous-version OffRamp + address rmnProxy; // RMN proxy address + address tokenAdminRegistry; // Token admin registry address + } + + /// @notice Dynamic offRamp config + /// @dev since OffRampConfig is part of OffRampConfigChanged event, if changing it, we should update the ABI on Atlas + struct DynamicConfig { + uint32 permissionLessExecutionThresholdSeconds; // ─╮ Waiting time before manual execution is enabled + uint32 maxDataBytes; // │ Maximum payload data size in bytes + uint16 maxNumberOfTokensPerMsg; // │ Maximum number of ERC20 token transfers that can be included per message + address router; // ─────────────────────────────────╯ Router address + address priceRegistry; // Price registry address + } + + /// @notice Returns the static config. + /// @dev This function will always return the same struct as the contents is static and can never change. + /// RMN depends on this function, if changing, please notify the RMN maintainers. + function getStaticConfig() external view returns (StaticConfig memory); + + /// @notice Returns the current dynamic config. + /// @return The current config. + function getDynamicConfig() external view returns (DynamicConfig memory); + /// @notice Execute a single message. /// @param message The message that will be executed. /// @param offchainTokenData Token transfer data to be passed to TokenPool. diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol index 13affbc6e..396945144 100644 --- a/src/interfaces/ccip/IEVM2EVMOnRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -17,6 +17,17 @@ interface IEVM2EVMOnRamp is ITypeAndVersion { bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees } + struct StaticConfig { + address linkToken; // ────────╮ Link token address + uint64 chainSelector; // ─────╯ Source chainSelector + uint64 destChainSelector; // ─╮ Destination chainSelector + uint64 defaultTxGasLimit; // │ Default gas limit for a tx + uint96 maxNopFeesJuels; // ───╯ Max nop fee balance onramp can have + address prevOnRamp; // Address of previous-version OnRamp + address rmnProxy; // Address of RMN proxy + address tokenAdminRegistry; // Address of the token admin registry + } + struct DynamicConfig { address router; // ──────────────────────────╮ Router address uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message @@ -69,4 +80,10 @@ interface IEVM2EVMOnRamp is ITypeAndVersion { /// @notice Returns the dynamic onRamp config. /// @return dynamicConfig the configuration. function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig); + + /// @notice Returns the static onRamp config. + /// @dev RMN depends on this function, if changing, please notify the RMN maintainers. + /// @return the configuration. + + function getStaticConfig() external view returns (StaticConfig memory); } From c7b11bdc97faad897aaf09b4336ea2aba0da4c4e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:06:01 +0530 Subject: [PATCH 042/123] feat: eth & arb tests --- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 475 +++++++++++++++++- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 6 +- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 438 +++++++++++++++- 3 files changed, 902 insertions(+), 17 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 4dcb21a81..fd68414a5 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -1,10 +1,34 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import 'forge-std/Test.sol'; + +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; +import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; -import 'forge-std/Test.sol'; -import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; + +import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; /** @@ -12,17 +36,452 @@ import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLau * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol -vv */ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { + struct CCIPSendParams { + address sender; + uint256 amount; + uint64 destChainSelector; + } + + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + uint64 internal constant BASE_CHAIN_SELECTOR = 15971525489660198786; + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + + IGhoToken internal constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + IEVM2EVMOnRamp internal constant ETH_ON_RAMP = + IEVM2EVMOnRamp(0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3); + IEVM2EVMOnRamp internal constant BASE_ON_RAMP = + IEVM2EVMOnRamp(0xc1b6287A3292d6469F2D8545877E40A2f75CA9a6); + + IEVM2EVMOffRamp_1_5 internal constant ETH_OFF_RAMP = + IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); + IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = + IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); + + IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); + + IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + + IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; + AaveV3Arbitrum_GHOBaseLaunch_20241223 internal proposal; + address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); + address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: LockReleaseTokenPool 1.5.1'); + address internal NEW_REMOTE_TOKEN_BASE = makeAddr('BASE: GhoToken'); + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + 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); + error InvalidSourcePoolAddress(bytes); + function setUp() public { vm.createSelectFork(vm.rpcUrl('arbitrum'), 287752362); - proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(address(0), address(0), address(0)); + NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); + NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); + _upgradeArbTo1_5_1(); + proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_BASE, + NEW_REMOTE_TOKEN_BASE + ); + + _validateConstants(); + + // execute proposal + executePayload(vm, address(proposal)); + } + + function _upgradeArbTo1_5_1() internal { + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + + executePayload( + vm, + address( + new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ETH, + address(NEW_GHO_CCIP_STEWARD) + ) + ) + ); } - /** - * @dev executes the generic test suite including e2e and config snapshots - */ - function test_defaultProposalExecution() public { - defaultTest('AaveV3Arbitrum_GHOBaseLaunch_20241223', AaveV3Arbitrum.POOL, address(proposal)); + function _deployNewTokenPoolArb() private returns (address) { + IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( + MiscArbitrum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolImpl = address( + new UpgradeableBurnMintTokenPool( + existingTokenPool.getToken(), + IGhoToken(existingTokenPool.getToken()).decimals(), + existingTokenPool.getArmProxy(), + existingTokenPool.getAllowListEnabled() + ) + ); + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + address(MiscArbitrum.PROXY_ADMIN), + abi.encodeCall( + IUpgradeableBurnMintTokenPool_1_5_1.initialize, + ( + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner + existingTokenPool.getAllowList(), + existingTokenPool.getRouter() + ) + ) + ) + ); + } + + function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { + return + address( + new GhoCcipSteward( + address(GHO), + newTokenPool, + GovernanceV3Arbitrum.EXECUTOR_LVL_1, // riskAdmin, using executor for convenience + false // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool + ) + ); + } + + function _validateConstants() private view { + assertEq(proposal.BASE_CHAIN_SELECTOR(), BASE_CHAIN_SELECTOR); + assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(proposal.REMOTE_TOKEN_POOL_BASE(), NEW_REMOTE_POOL_BASE); + assertEq(proposal.REMOTE_GHO_TOKEN_BASE(), NEW_REMOTE_TOKEN_BASE); + + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); + assertEq(ROUTER.typeAndVersion(), 'Router 1.2.0'); + + _assertOnRamp(ETH_ON_RAMP, ARB_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); + _assertOnRamp(BASE_ON_RAMP, ARB_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); + _assertOffRamp(ETH_OFF_RAMP, ETH_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); + _assertOffRamp(BASE_OFF_RAMP, BASE_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); + + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); + assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); + } + + function _assertOnRamp( + IEVM2EVMOnRamp onRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(onRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(onRamp.getStaticConfig().chainSelector, srcSelector); + assertEq(onRamp.getStaticConfig().destChainSelector, dstSelector); + assertEq(onRamp.getDynamicConfig().router, address(router)); + assertEq(router.getOnRamp(dstSelector), address(onRamp)); + } + + function _assertOffRamp( + IEVM2EVMOffRamp_1_5 offRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(offRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + assertEq(offRamp.getStaticConfig().sourceChainSelector, srcSelector); + assertEq(offRamp.getStaticConfig().chainSelector, dstSelector); + assertEq(offRamp.getDynamicConfig().router, address(router)); + assertTrue(router.isOffRamp(srcSelector, address(offRamp))); + } + + 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(GHO), amount: params.amount}); + + uint256 feeAmount = ROUTER.getFee(params.destChainSelector, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: ROUTER, + sourceChainSelector: ARB_CHAIN_SELECTOR, + destChainSelector: params.destChainSelector, + feeTokenAmount: feeAmount, + originalSender: params.sender, + sourceToken: address(GHO), + destinationToken: address( + params.destChainSelector == BASE_CHAIN_SELECTOR + ? NEW_REMOTE_TOKEN_BASE + : MiscEthereum.GHO_TOKEN + ) + }) + ); + + return (message, eventArg); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() internal pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + } + + function test_BasePoolConfig() public view { + assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); + assertEq(NEW_TOKEN_POOL.getSupportedChains()[0], ETH_CHAIN_SELECTOR); + assertEq(NEW_TOKEN_POOL.getSupportedChains()[1], BASE_CHAIN_SELECTOR); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), + abi.encode(address(MiscEthereum.GHO_TOKEN)) + ); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(BASE_CHAIN_SELECTOR), + abi.encode(address(NEW_REMOTE_TOKEN_BASE)) + ); + assertEq(NEW_TOKEN_POOL.getRemotePools(BASE_CHAIN_SELECTOR).length, 1); + assertEq( + NEW_TOKEN_POOL.getRemotePools(BASE_CHAIN_SELECTOR)[0], + abi.encode(address(NEW_REMOTE_POOL_BASE)) + ); + assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 2); + assertEq( + NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR)[1], // 0th is the 1.4 token pool + abi.encode(address(NEW_REMOTE_POOL_ETH)) + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(BASE_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(BASE_CHAIN_SELECTOR), + _getDisabledConfig() + ); + } + + function test_sendMessageToBaseSucceeds(uint256 amount) public { + uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, destChainSelector: BASE_CHAIN_SELECTOR}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Burned(address(BASE_ON_RAMP), amount); + vm.expectEmit(address(BASE_ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(BASE_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bridgeableAmount - amount); + } + + function test_sendMessageToEthSucceeds(uint256 amount) public { + uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, destChainSelector: ETH_CHAIN_SELECTOR}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Burned(address(ETH_ON_RAMP), amount); + vm.expectEmit(address(ETH_ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bridgeableAmount - amount); + } + + function test_offRampViaBaseSucceeds(uint256 amount) public { + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(NEW_TOKEN_POOL) + ); + uint256 mintAbleAmount = bucketCapacity - bucketLevel; + amount = bound(amount, 1, mintAbleAmount); + + uint256 aliceBalance = GHO.balanceOf(alice); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Minted(address(BASE_OFF_RAMP), alice, amount); + + vm.prank(address(BASE_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: BASE_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_BASE)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel + amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + } + + function test_offRampViaEthSucceeds(uint256 amount) public { + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(NEW_TOKEN_POOL) + ); + uint256 mintAbleAmount = bucketCapacity - bucketLevel; + amount = bound(amount, 1, mintAbleAmount); + + uint256 aliceBalance = GHO.balanceOf(alice); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Minted(address(ETH_OFF_RAMP), alice, amount); + + vm.prank(address(ETH_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ETH)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel + amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + } + + function test_cannotUseBaseOffRampForEthMessages() public { + uint256 amount = 100e18; + + vm.expectRevert( + abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, address(BASE_OFF_RAMP)) + ); + vm.prank(address(BASE_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ETH)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + } + + function test_cannotOffRampOtherChainMessages() public { + uint256 amount = 100e18; + + vm.expectRevert( + abi.encodeWithSelector( + InvalidSourcePoolAddress.selector, + abi.encode(address(NEW_REMOTE_POOL_ETH)) + ) + ); + vm.prank(address(BASE_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: BASE_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ETH)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + vm.expectRevert( + abi.encodeWithSelector( + InvalidSourcePoolAddress.selector, + abi.encode(address(NEW_REMOTE_POOL_BASE)) + ) + ); + vm.prank(address(ETH_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_BASE)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 1b143e9c1..13bc95038 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -25,10 +25,14 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ); } + function test_temp() public pure { + assertTrue(1 == 1); + } + /** * @dev executes the generic test suite including e2e and config snapshots */ - function test_defaultProposalExecution() public { + function skip_test_defaultProposalExecution() public { defaultTest('AaveV3Base_GHOBaseLaunch_20241223', AaveV3Base.POOL, address(proposal)); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 0b9175cd1..a9d773c10 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -1,10 +1,34 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import 'forge-std/Test.sol'; + +import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; +import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; -import 'forge-std/Test.sol'; -import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; + +import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; /** @@ -12,17 +36,415 @@ import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLau * command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol -vv */ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { + struct CCIPSendParams { + address sender; + uint256 amount; + uint64 destChainSelector; + } + + uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; + uint64 internal constant BASE_CHAIN_SELECTOR = 15971525489660198786; + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + + IGhoToken internal constant GHO = IGhoToken(MiscEthereum.GHO_TOKEN); + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + IEVM2EVMOnRamp internal constant ARB_ON_RAMP = + IEVM2EVMOnRamp(0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284); + IEVM2EVMOnRamp internal constant BASE_ON_RAMP = + IEVM2EVMOnRamp(0xb8a882f3B88bd52D1Ff56A873bfDB84b70431937); + IEVM2EVMOffRamp_1_5 internal constant ARB_OFF_RAMP = + IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); + IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = + IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); + + IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); + + IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + + IUpgradeableLockReleaseTokenPool_1_5_1 internal NEW_TOKEN_POOL; + AaveV3Ethereum_GHOBaseLaunch_20241223 internal proposal; + address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); + address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: BurnMintTokenPool 1.5.1'); + address internal NEW_REMOTE_TOKEN_BASE = makeAddr('BASE: GhoToken'); + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + 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); + error InvalidSourcePoolAddress(bytes); + function setUp() public { vm.createSelectFork(vm.rpcUrl('mainnet'), 21463360); - proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(address(0), address(0), address(0)); + NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(_deployNewTokenPoolEth()); + NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); + _upgradeEthTo1_5_1(); + proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_BASE, + NEW_REMOTE_TOKEN_BASE + ); + + _validateConstants(); + + // execute proposal + executePayload(vm, address(proposal)); + } + + function _upgradeEthTo1_5_1() internal { + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1); + + executePayload( + vm, + address( + new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ARB, + address(NEW_GHO_CCIP_STEWARD) + ) + ) + ); + } + + function _deployNewTokenPoolEth() private returns (address) { + IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( + MiscEthereum.GHO_CCIP_TOKEN_POOL + ); + address newTokenPoolImpl = address( + new UpgradeableLockReleaseTokenPool( + existingTokenPool.getToken(), + IGhoToken(existingTokenPool.getToken()).decimals(), + existingTokenPool.getArmProxy(), + existingTokenPool.getAllowListEnabled(), + existingTokenPool.canAcceptLiquidity() + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + MiscEthereum.PROXY_ADMIN, + abi.encodeCall( + IUpgradeableLockReleaseTokenPool_1_5_1.initialize, + ( + GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner + existingTokenPool.getAllowList(), + existingTokenPool.getRouter(), + existingTokenPool.getBridgeLimit() + ) + ) + ) + ); + } + + function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { + return + address( + new GhoCcipSteward( + address(GHO), + newTokenPool, + GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, using executor for convenience + true // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool + ) + ); + } + + function _validateConstants() private view { + assertEq(proposal.BASE_CHAIN_SELECTOR(), BASE_CHAIN_SELECTOR); + assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(proposal.REMOTE_TOKEN_POOL_BASE(), NEW_REMOTE_POOL_BASE); + assertEq(proposal.REMOTE_GHO_TOKEN_BASE(), NEW_REMOTE_TOKEN_BASE); + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'LockReleaseTokenPool 1.5.1'); + assertEq(ROUTER.typeAndVersion(), 'Router 1.2.0'); + _assertOnRamp(ARB_ON_RAMP, ETH_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); + _assertOnRamp(BASE_ON_RAMP, ETH_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); + _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); + _assertOffRamp(BASE_OFF_RAMP, BASE_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); + assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); + } + + function _assertOnRamp( + IEVM2EVMOnRamp onRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(onRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(onRamp.getStaticConfig().chainSelector, srcSelector); + assertEq(onRamp.getStaticConfig().destChainSelector, dstSelector); + assertEq(onRamp.getDynamicConfig().router, address(router)); + assertEq(router.getOnRamp(dstSelector), address(onRamp)); + } + + function _assertOffRamp( + IEVM2EVMOffRamp_1_5 offRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(offRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + assertEq(offRamp.getStaticConfig().sourceChainSelector, srcSelector); + assertEq(offRamp.getStaticConfig().chainSelector, dstSelector); + assertEq(offRamp.getDynamicConfig().router, address(router)); + assertTrue(router.isOffRamp(srcSelector, address(offRamp))); + } + + 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(GHO), amount: params.amount}); + + uint256 feeAmount = ROUTER.getFee(params.destChainSelector, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: ROUTER, + sourceChainSelector: ETH_CHAIN_SELECTOR, + destChainSelector: params.destChainSelector, + feeTokenAmount: feeAmount, + originalSender: params.sender, + sourceToken: address(GHO), + destinationToken: address( + params.destChainSelector == BASE_CHAIN_SELECTOR + ? NEW_REMOTE_TOKEN_BASE + : AaveV3ArbitrumAssets.GHO_UNDERLYING + ) + }) + ); + + return (message, eventArg); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() internal 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)); + } + + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function test_sendMessageToBaseSucceeds(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - + NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 currentBridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, destChainSelector: BASE_CHAIN_SELECTOR}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Locked(address(BASE_ON_RAMP), amount); + vm.expectEmit(address(BASE_ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(BASE_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), currentBridgedAmount + amount); + } + + function test_sendMessageToArbSucceeds(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - + NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 currentBridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, destChainSelector: ARB_CHAIN_SELECTOR}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Locked(address(ARB_ON_RAMP), amount); + vm.expectEmit(address(ARB_ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), currentBridgedAmount + amount); + } + + function test_offRampViaBaseSucceeds(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 poolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Released(address(BASE_OFF_RAMP), alice, amount); + + vm.prank(address(BASE_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: BASE_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_BASE)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), poolBalance - amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgeableAmount - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), GHO.balanceOf(address(NEW_TOKEN_POOL))); + } + + function test_offRampViaArbSucceeds(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 poolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Released(address(ARB_OFF_RAMP), alice, amount); + + vm.prank(address(ARB_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ARB)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), poolBalance - amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgeableAmount - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), GHO.balanceOf(address(NEW_TOKEN_POOL))); } - /** - * @dev executes the generic test suite including e2e and config snapshots - */ - function test_defaultProposalExecution() public { - defaultTest('AaveV3Ethereum_GHOBaseLaunch_20241223', AaveV3Ethereum.POOL, address(proposal)); + function test_cannotUseBaseOffRampForArbMessages() public { + uint256 amount = 100e18; + + vm.expectRevert( + abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, address(BASE_OFF_RAMP)) + ); + vm.prank(address(BASE_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ARB)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + } + + function test_cannotOffRampOtherChainMessages() public { + uint256 amount = 100e18; + + vm.expectRevert( + abi.encodeWithSelector( + InvalidSourcePoolAddress.selector, + abi.encode(address(NEW_REMOTE_POOL_ARB)) + ) + ); + vm.prank(address(BASE_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: BASE_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ARB)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + vm.expectRevert( + abi.encodeWithSelector( + InvalidSourcePoolAddress.selector, + abi.encode(address(NEW_REMOTE_POOL_BASE)) + ) + ); + vm.prank(address(ARB_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_BASE)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); } } From c3ea819e350f0e26e0c7f0fb03e3d2a752272988 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:27:13 +0530 Subject: [PATCH 043/123] chore: import gho from EthereumAssets instead of MiscEthereum --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 6 +++--- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 4 ++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 9 +++++---- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 6 +++--- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index fd68414a5..53ab49fcd 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -18,8 +18,8 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; @@ -223,7 +223,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { destinationToken: address( params.destChainSelector == BASE_CHAIN_SELECTOR ? NEW_REMOTE_TOKEN_BASE - : MiscEthereum.GHO_TOKEN + : AaveV3EthereumAssets.GHO_UNDERLYING ) }) ); @@ -268,7 +268,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(NEW_TOKEN_POOL.getSupportedChains()[1], BASE_CHAIN_SELECTOR); assertEq( NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), - abi.encode(address(MiscEthereum.GHO_TOKEN)) + abi.encode(address(AaveV3EthereumAssets.GHO_UNDERLYING)) ); assertEq( NEW_TOKEN_POOL.getRemoteToken(BASE_CHAIN_SELECTOR), diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 6b3a0f1de..1b0c502ab 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -11,8 +11,8 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; /** * @title GHO Base Launch @@ -91,7 +91,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: ETH_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, - remoteTokenAddress: abi.encode(MiscEthereum.GHO_TOKEN), + remoteTokenAddress: abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING), outboundRateLimiterConfig: emptyRateLimiterConfig, inboundRateLimiterConfig: emptyRateLimiterConfig }); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 9871a5ce1..7425b2f15 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -16,6 +16,7 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; @@ -106,7 +107,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); eth.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); - eth.c.token = IGhoToken(MiscEthereum.GHO_TOKEN); + eth.c.token = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); (address newTokenPoolEth, address newTokenPoolArb) = _upgradeEthArbTo1_5_1(); arb.c.chainSelector = 4949039107694359620; @@ -185,7 +186,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { MiscEthereum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolEth = _deployNewLockReleaseTokenPool( - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, existingPoolEth.getArmProxy(), existingPoolEth.getRouter(), existingPoolEth.getBridgeLimit(), @@ -194,7 +195,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ); address newGhoCcipStewardEth = _deployNewGhoCcipSteward( newTokenPoolEth, - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience true // bridgeLimitEnabled ); @@ -414,7 +415,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(eth.c.forkId); assertEq(eth.c.chainSelector, 5009297550715157269); - assertEq(address(eth.c.token), MiscEthereum.GHO_TOKEN); + assertEq(address(eth.c.token), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(eth.c.router.typeAndVersion(), 'Router 1.2.0'); _assertOnRamp(eth.c.arbOnRamp, eth.c.chainSelector, arb.c.chainSelector, eth.c.router); _assertOnRamp(eth.c.baseOnRamp, eth.c.chainSelector, base.c.chainSelector, eth.c.router); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index a9d773c10..536382c32 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -16,10 +16,10 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; @@ -46,7 +46,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { uint64 internal constant BASE_CHAIN_SELECTOR = 15971525489660198786; uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; - IGhoToken internal constant GHO = IGhoToken(MiscEthereum.GHO_TOKEN); + IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); IEVM2EVMOnRamp internal constant ARB_ON_RAMP = @@ -170,7 +170,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); _assertOffRamp(BASE_OFF_RAMP, BASE_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), GovernanceV3Ethereum.EXECUTOR_LVL_1); - assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); } From dd136559fec3f0cbbe2b4c1a47b164064f299898 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:32:03 +0530 Subject: [PATCH 044/123] chore: use latest deployment of existing remote pool upgrade --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 2 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 53ab49fcd..96734216b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -82,7 +82,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 287752362); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 288070365); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); _upgradeArbTo1_5_1(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 7425b2f15..90e7ce8b8 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -100,7 +100,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 287752362); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24072751); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21463360); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index bd8b7e9c3..788f85192 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -12,7 +12,7 @@ export const config: ConfigFile = { }, poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21463360}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 287752362}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, AaveV3Base: {configs: {OTHERS: {}}, cache: {blockNumber: 24072751}}, }, }; From 9994623ea9b91a1a96ddc85cf3c791b1a3655a26 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:33:52 +0530 Subject: [PATCH 045/123] doc: snapshot & discussion --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 3 +-- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 3 +-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 3 +-- src/20241223_Multi_GHOBaseLaunch/config.ts | 5 +++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index dfb20feeb..7f8cde05e 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -8,8 +8,7 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; /** * @title GHO Base Launch * @author Aave Labs - * - Snapshot: TODO - * - Discussion: TODO + * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 */ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 1b0c502ab..379988e9a 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -17,8 +17,7 @@ import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; /** * @title GHO Base Launch * @author Aave Labs - * - Snapshot: TODO - * - Discussion: TODO + * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 */ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index a14e90f8c..632f5ddff 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -8,8 +8,7 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; /** * @title GHO Base Launch * @author Aave Labs - * - Snapshot: TODO - * - Discussion: TODO + * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 */ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 788f85192..448df8089 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -6,8 +6,9 @@ export const config: ConfigFile = { shortName: 'GHOBaseLaunch', date: '20241223', author: 'Aave Labs', - discussion: '', - snapshot: '', + discussion: + 'https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338', + snapshot: 'Direct-to-AIP', votingNetwork: 'POLYGON', }, poolOptions: { From 2ddc8130860ef0a9478bd6ffeae3d5919a8d1915 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:37:24 +0530 Subject: [PATCH 046/123] chore: rename facilitator --- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 379988e9a..75c957599 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -55,7 +55,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { GHO_TOKEN.grantRole(GHO_TOKEN.FACILITATOR_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); GHO_TOKEN.grantRole(GHO_TOKEN.BUCKET_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); - GHO_TOKEN.addFacilitator(address(TOKEN_POOL), 'CCIP TokenPool', CCIP_BUCKET_CAPACITY); + GHO_TOKEN.addFacilitator(address(TOKEN_POOL), 'CCIP TokenPool v1.5.1', CCIP_BUCKET_CAPACITY); TOKEN_ADMIN_REGISTRY.acceptAdminRole(address(GHO_TOKEN)); TOKEN_POOL.acceptOwnership(); From 8b43b846c64b645988a08bc331959233a9333206 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:24:20 +0530 Subject: [PATCH 047/123] test: cleanup & fuzzify --- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 65c3bab80..bb43397d7 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -247,10 +247,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base { - function setUp() public override { - super.setUp(); - } - function test_defaultProposalExecution() public { defaultTest( 'AaveV3Arbitrum_GHOCCIP151Upgrade_20241209', @@ -356,8 +352,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is executePayload(vm, address(proposal)); } - function test_sendMessageSucceedsAndRoutesViaNewPool() public { - uint256 amount = 100_000e18; + function test_sendMessageSucceedsAndRoutesViaNewPool(uint256 amount) public { + uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); deal(address(GHO), alice, amount); vm.prank(alice); @@ -406,8 +403,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // on-ramp via new pool - function test_lockOrBurnSucceedsOnNewPool() public { - uint256 amount = 100_000e18; + function test_lockOrBurnSucceedsOnNewPool(uint256 amount) public { + uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + amount = bound(amount, 1, bridgeableAmount); // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(NEW_TOKEN_POOL), amount); @@ -448,10 +446,13 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from new eth token pool (v1.5.1) - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth(uint256 amount) public { + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(NEW_TOKEN_POOL) + ); + uint256 mintAbleAmount = bucketCapacity - bucketLevel; + amount = bound(amount, 1, mintAbleAmount); - uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; uint256 aliceBalance = GHO.balanceOf(alice); vm.expectEmit(address(NEW_TOKEN_POOL)); @@ -476,10 +477,15 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth( + uint256 amount + ) public { + (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( + address(NEW_TOKEN_POOL) + ); + uint256 mintAbleAmount = bucketCapacity - bucketLevel; + amount = bound(amount, 1, mintAbleAmount); - uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; uint256 aliceBalance = GHO.balanceOf(alice); vm.expectEmit(address(NEW_TOKEN_POOL)); From f022cd62bea75b6105c895c32303d9763873aec4 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:30:03 +0530 Subject: [PATCH 048/123] test: cleanup & fuzzify --- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 81ab6cfcf..5b66ffbf0 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -262,10 +262,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base { - function setUp() public override { - super.setUp(); - } - /** * @dev executes the generic test suite including e2e and config snapshots */ @@ -374,8 +370,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is executePayload(vm, address(proposal)); } - function test_sendMessageSucceedsAndRoutesViaNewPool() public { - uint256 amount = 100_000e18; + function test_sendMessageSucceedsAndRoutesViaNewPool(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - + NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); deal(address(GHO), alice, amount); vm.prank(alice); @@ -425,8 +423,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // on-ramp via new pool - function test_lockOrBurnSucceedsOnNewPool() public { - uint256 amount = 100_000e18; + function test_lockOrBurnSucceedsOnNewPool(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - + NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); // router pulls tokens from the user & sends to the token pool during onRamps // we don't override NEW_TOKEN_POOL balance here & instead transfer because we want @@ -475,8 +475,9 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from new eth token pool (v1.5.1) - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth(uint256 amount) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); uint256 aliceBalance = GHO.balanceOf(alice); uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); @@ -505,8 +506,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth() public { - uint256 amount = 100_000e18; + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth( + uint256 amount + ) public { + uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); uint256 aliceBalance = GHO.balanceOf(alice); uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); From 1e06e0d2c9702ba8458b4f2d6ce0b732ddbab4f2 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:14:22 +0530 Subject: [PATCH 049/123] chore: use latest deployment of existing remote pool upgrade --- lib/aave-helpers | 2 +- lib/ccip | 2 +- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 6 +----- src/20241209_Multi_GHOCCIP151Upgrade/config.ts | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/aave-helpers b/lib/aave-helpers index 19d8ece8a..1821d62cc 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit 19d8ece8a12d3d789ccb96fd184fef0a646b201c +Subproject commit 1821d62ccddb4d9d66ad35405cbaaeec795bd1b2 diff --git a/lib/ccip b/lib/ccip index a2e92d0e7..ca12f6398 160000 --- a/lib/ccip +++ b/lib/ccip @@ -1 +1 @@ -Subproject commit a2e92d0e7fdae6f62f94ce90e1fac613fa04371d +Subproject commit ca12f6398157d7a0526bc3f153d69566884d9dd0 diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index d03a8df00..8625ddd07 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -36,9 +36,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH address public immutable NEW_REMOTE_POOL_ETH; - // https://arbiscan.io/address/0x360d8aa8F6b09B7BC57aF34db2Eb84dD87bf4d12 + // https://arbiscan.io/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = - 0x360d8aa8F6b09B7BC57aF34db2Eb84dD87bf4d12; // from https://github.com/aave/ccip/pull/21 (commit f684d950178fbdc95f543382fac472cf47434d55) + 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index bb43397d7..719c5442c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -74,7 +74,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 287752362); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 288070365); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index b428a7f46..a2329290e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -87,7 +87,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function setUp() public virtual { l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21366260); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 287752362); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); vm.selectFork(l1.c.forkId); address newTokenPoolEth = _deployNewTokenPoolEth(); @@ -521,10 +521,6 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_PostUpgrade is contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is AaveV3E2E_GHOCCIP151Upgrade_20241209_Base { - function setUp() public override { - super.setUp(); - } - function test_E2E_InFlightMsg_FromEth() public { vm.selectFork(l1.c.forkId); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index 833e1934b..e2cb8b937 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -12,6 +12,6 @@ export const config: ConfigFile = { }, poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21366260}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 287752362}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, }, }; From 843c94a4407f60dcbd54de18d181d500f667a98c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:20:10 +0530 Subject: [PATCH 050/123] doc: snapshot -> direct-to-aip --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 1 - .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 1 - src/20241209_Multi_GHOCCIP151Upgrade/config.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 8625ddd07..9a93c3a7e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -15,7 +15,6 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs - * - Snapshot: TODO * - Discussion: TODO */ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 6372a59c1..545cef1ea 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -11,7 +11,6 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** * @title GHO CCIP 1.5.1 Upgrade * @author Aave Labs - * - Snapshot: TODO * - Discussion: TODO */ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index e2cb8b937..15ad2de6e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -7,7 +7,7 @@ export const config: ConfigFile = { date: '20241209', author: 'Aave Labs', discussion: '', - snapshot: '', + snapshot: 'Direct-to-AIP', votingNetwork: 'POLYGON', }, poolOptions: { From ad22759de00b40ff1fe6251a9c807b662fa7e551 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:24:01 +0530 Subject: [PATCH 051/123] chore: import gho from EthereumAssets instead of MiscEthereum --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 9 ++++++--- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 7 ++++--- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 5 +++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 11 ++++++----- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 9a93c3a7e..46444fe41 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -8,8 +8,8 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** @@ -92,7 +92,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: ETH_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, - remoteTokenAddress: abi.encode(MiscEthereum.GHO_TOKEN), + remoteTokenAddress: abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING), outboundRateLimiterConfig: emptyRateLimiterConfig, inboundRateLimiterConfig: emptyRateLimiterConfig }); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 719c5442c..661ee947a 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -18,9 +18,9 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; @@ -183,7 +183,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { feeTokenAmount: feeAmount, originalSender: params.sender, sourceToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, - destinationToken: MiscEthereum.GHO_TOKEN, + destinationToken: AaveV3EthereumAssets.GHO_UNDERLYING, poolVersion: params.poolVersion }) ); @@ -321,7 +321,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 2); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(ETH_PROXY_POOL))); assertTrue(NEW_TOKEN_POOL.isRemotePool(ETH_CHAIN_SELECTOR, abi.encode(NEW_REMOTE_POOL_ETH))); - assertEq(NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), abi.encode(MiscEthereum.GHO_TOKEN)); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), + abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING) + ); assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 1); assertTrue(NEW_TOKEN_POOL.isSupportedChain(ETH_CHAIN_SELECTOR)); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index a2329290e..8e58872d6 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -14,6 +14,7 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; @@ -93,7 +94,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address newTokenPoolEth = _deployNewTokenPoolEth(); address newGhoCcipStewardEth = _deployNewGhoCcipSteward( newTokenPoolEth, - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience true // bridgeLimitEnabled ); @@ -178,7 +179,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _validateConfig(bool upgraded) internal { vm.selectFork(l1.c.forkId); assertEq(l1.c.chainSelector, 5009297550715157269); - assertEq(address(l1.c.token), MiscEthereum.GHO_TOKEN); + assertEq(address(l1.c.token), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(l1.c.router.typeAndVersion(), 'Router 1.2.0'); assertEq(l1.c.EVM2EVMOnRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(l1.c.EVM2EVMOffRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); @@ -265,7 +266,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { vm.selectFork(l1.c.forkId); vm.prank(l1.c.tokenAdminRegistry.owner()); l1.c.tokenAdminRegistry.transferAdminRole( - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1 ); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 545cef1ea..82219c3a4 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -6,6 +6,7 @@ import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGen import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** @@ -46,7 +47,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // pre-req - chainlink transfers gho token pool ownership on token admin registry function _acceptOwnership() internal { NEW_TOKEN_POOL.acceptOwnership(); - TOKEN_ADMIN_REGISTRY.acceptAdminRole(MiscEthereum.GHO_TOKEN); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(AaveV3EthereumAssets.GHO_UNDERLYING); } function _migrateLiquidity() internal { @@ -89,6 +90,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { NEW_TOKEN_POOL.setBridgeLimitAdmin(NEW_GHO_CCIP_STEWARD); // register new pool - TOKEN_ADMIN_REGISTRY.setPool(MiscEthereum.GHO_TOKEN, address(NEW_TOKEN_POOL)); + TOKEN_ADMIN_REGISTRY.setPool(AaveV3EthereumAssets.GHO_UNDERLYING, address(NEW_TOKEN_POOL)); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 5b66ffbf0..c941cffda 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -21,6 +21,7 @@ import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; @@ -44,7 +45,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; - IGhoToken internal constant GHO = IGhoToken(MiscEthereum.GHO_TOKEN); + IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); address internal constant ARB_PROXY_POOL = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; @@ -88,7 +89,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { // pre-req - chainlink transfers gho token pool ownership on token admin registry vm.prank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.transferAdminRole( - MiscEthereum.GHO_TOKEN, + AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1 ); @@ -166,7 +167,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); - assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), MiscEthereum.GHO_TOKEN); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *present* on eth token pool } @@ -176,7 +177,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { IClient.EVM2AnyMessage memory message = CCIPUtils.generateMessage(params.sender, 1); message.tokenAmounts[0] = IClient.EVMTokenAmount({ - token: MiscEthereum.GHO_TOKEN, + token: AaveV3EthereumAssets.GHO_UNDERLYING, amount: params.amount }); @@ -190,7 +191,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { sourceChainSelector: ETH_CHAIN_SELECTOR, feeTokenAmount: feeAmount, originalSender: params.sender, - sourceToken: MiscEthereum.GHO_TOKEN, + sourceToken: AaveV3EthereumAssets.GHO_UNDERLYING, destinationToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, poolVersion: params.poolVersion }) From b9022f6b773888533126c45ac15756172c4d0f3d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:35:13 +0530 Subject: [PATCH 052/123] chore: cleanup rm ProxyAdmin reference --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 46444fe41..d4befc56c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -39,7 +39,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb - ProxyAdmin public constant PROXY_ADMIN = ProxyAdmin(MiscArbitrum.PROXY_ADMIN); IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); constructor(address newTokenPoolArb, address newTokenPoolEth, address newGhoCcipSteward) { @@ -109,7 +108,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { } function _upgradeExistingTokenPool() internal { - PROXY_ADMIN.upgrade( + ProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( TransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), EXISTING_TOKEN_POOL_UPGRADE_IMPL ); From 2754acfc9e1627c86df3dc1ed8d875ee1cb64953 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:37:07 +0530 Subject: [PATCH 053/123] chore: rename facilitator --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 2 +- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index d4befc56c..a813d56a8 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -65,7 +65,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address(EXISTING_TOKEN_POOL) ); - GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP v1.5.1 TokenPool', uint128(bucketCapacity)); + GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP TokenPool v1.5.1 ', uint128(bucketCapacity)); NEW_TOKEN_POOL.directMint(address(EXISTING_TOKEN_POOL), bucketLevel); // increase facilitator level _upgradeExistingTokenPool(); // introduce `directBurn` method diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 661ee947a..dd0422342 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -292,7 +292,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is newFacilitator = GHO.getFacilitator(address(NEW_TOKEN_POOL)); - assertEq(newFacilitator.label, 'CCIP v1.5.1 TokenPool'); + assertEq(newFacilitator.label, 'CCIP TokenPool v1.5.1 '); assertEq(newFacilitator.bucketCapacity, existingFacilitator.bucketCapacity); assertEq(newFacilitator.bucketLevel, existingFacilitator.bucketLevel); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 8e58872d6..2ef55c4fd 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -247,7 +247,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { if (upgraded) { assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), address(l2.newTokenPool)); assertEq(bytes(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label).length, 0); - assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP v1.5.1 TokenPool'); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP TokenPool v1.5.1 '); } else { assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), l2.c.proxyPool); assertEq(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label, 'CCIP TokenPool'); From ff8bd9eadcf324f6afe5d47973819230783f0258 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:43:56 +0530 Subject: [PATCH 054/123] chore: rm duplicate check --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 7 +------ .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index dd0422342..6d9879dee 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -204,12 +204,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _getDynamicParams(address tokenPool) internal view returns (bytes memory) { IUpgradeableBurnMintTokenPool_1_4 ghoTokenPool = IUpgradeableBurnMintTokenPool_1_4(tokenPool); - return - abi.encode( - ghoTokenPool.owner(), - ghoTokenPool.getSupportedChains(), - ghoTokenPool.getAllowListEnabled() - ); + return abi.encode(ghoTokenPool.owner(), ghoTokenPool.getSupportedChains()); } function _tokenBucketToConfig( diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index c941cffda..37bf4635b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -222,7 +222,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { abi.encode( ghoTokenPool.owner(), ghoTokenPool.getSupportedChains(), - ghoTokenPool.getAllowListEnabled(), ghoTokenPool.getRebalancer(), ghoTokenPool.getBridgeLimit() ); From 17ec054bb893cda835615bcf04a027121b4f8ded Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 16:49:35 +0530 Subject: [PATCH 055/123] fix: snapshot, use utils reference for chain selectors --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 1 + .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 6 +++--- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 1 + .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 1 + .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 6 +++--- src/20241223_Multi_GHOBaseLaunch/config.ts | 3 ++- src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol | 3 ++- 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 7f8cde05e..97c7dfb01 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -9,6 +9,7 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; * @title GHO Base Launch * @author Aave Labs * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 + * - Snapshot: https://snapshot.box/#/s:aave.eth/proposal/0x03dc21e0423c60082dc23317af6ebaf997610cbc2cbb0f5a385653bd99a524fe */ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 96734216b..8765d3493 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -42,9 +42,9 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { uint64 destChainSelector; } - uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; - uint64 internal constant BASE_CHAIN_SELECTOR = 15971525489660198786; - uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; + uint64 internal constant BASE_CHAIN_SELECTOR = CCIPUtils.BASE_CHAIN_SELECTOR; + uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; IGhoToken internal constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 75c957599..0e38d7ab5 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -18,6 +18,7 @@ import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; * @title GHO Base Launch * @author Aave Labs * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 + * - Snapshot: https://snapshot.box/#/s:aave.eth/proposal/0x03dc21e0423c60082dc23317af6ebaf997610cbc2cbb0f5a385653bd99a524fe */ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index 632f5ddff..b484270d4 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -9,6 +9,7 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; * @title GHO Base Launch * @author Aave Labs * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 + * - Snapshot: https://snapshot.box/#/s:aave.eth/proposal/0x03dc21e0423c60082dc23317af6ebaf997610cbc2cbb0f5a385653bd99a524fe */ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 536382c32..5e165b5ed 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -42,9 +42,9 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { uint64 destChainSelector; } - uint64 internal constant ARB_CHAIN_SELECTOR = 4949039107694359620; - uint64 internal constant BASE_CHAIN_SELECTOR = 15971525489660198786; - uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; + uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; + uint64 internal constant BASE_CHAIN_SELECTOR = CCIPUtils.BASE_CHAIN_SELECTOR; + uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 448df8089..8fdb40d54 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -8,7 +8,8 @@ export const config: ConfigFile = { author: 'Aave Labs', discussion: 'https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338', - snapshot: 'Direct-to-AIP', + snapshot: + 'https://snapshot.box/#/s:aave.eth/proposal/0x03dc21e0423c60082dc23317af6ebaf997610cbc2cbb0f5a385653bd99a524fe', votingNetwork: 'POLYGON', }, poolOptions: { diff --git a/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol b/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol index 7a8e93d46..c3b489477 100644 --- a/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol +++ b/src/20241223_Multi_GHOBaseLaunch/utils/CCIPUtils.sol @@ -7,8 +7,9 @@ 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; + uint64 internal constant BASE_CHAIN_SELECTOR = 15971525489660198786; + uint64 internal constant ETH_CHAIN_SELECTOR = 5009297550715157269; bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000; From 0471bd8c77afd8f51d37bbc24b57c11db9f3a0b6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 21:20:32 +0530 Subject: [PATCH 056/123] fix: base config test on eth --- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 5e165b5ed..e79ed8e37 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -261,6 +261,46 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + function test_BasePoolConfig() public view { + assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); + assertEq(NEW_TOKEN_POOL.getSupportedChains()[0], ARB_CHAIN_SELECTOR); + assertEq(NEW_TOKEN_POOL.getSupportedChains()[1], BASE_CHAIN_SELECTOR); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ARB_CHAIN_SELECTOR), + abi.encode(address(AaveV3ArbitrumAssets.GHO_UNDERLYING)) + ); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(BASE_CHAIN_SELECTOR), + abi.encode(address(NEW_REMOTE_TOKEN_BASE)) + ); + assertEq(NEW_TOKEN_POOL.getRemotePools(BASE_CHAIN_SELECTOR).length, 1); + assertEq( + NEW_TOKEN_POOL.getRemotePools(BASE_CHAIN_SELECTOR)[0], + abi.encode(address(NEW_REMOTE_POOL_BASE)) + ); + assertEq(NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR).length, 2); + assertEq( + NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR)[1], // 0th is the 1.4 token pool + abi.encode(address(NEW_REMOTE_POOL_ARB)) + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(BASE_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(BASE_CHAIN_SELECTOR), + _getDisabledConfig() + ); + } + function test_sendMessageToBaseSucceeds(uint256 amount) public { uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - NEW_TOKEN_POOL.getCurrentBridgedAmount(); From cddd17581585bf6c679e13f854f62e2000c5176c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 21:21:00 +0530 Subject: [PATCH 057/123] test: eth<>arb e2e test --- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 138 +++++++++++++++++- 1 file changed, 135 insertions(+), 3 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 90e7ce8b8..a6fc0f40d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -3,6 +3,8 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; + import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; @@ -116,7 +118,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(base.c.forkId); address ghoTokenImplBase = _deployGhoTokenImpl(); - address ghoTokenBase = _computeCreateAddress(GovernanceV3Base.EXECUTOR_LVL_1); + address ghoTokenBase = _predictGhoTokenAddressBase(ghoTokenImplBase); address newTokenPoolBase = _deployNewBurnMintTokenPool( ghoTokenBase, RMN_PROXY_BASE, @@ -256,8 +258,35 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { return address(new UpgradeableGhoToken()); } - function _computeCreateAddress(address deployer) internal view returns (address) { - return vm.computeCreateAddress(deployer, vm.getNonce(deployer)); + function _predictGhoTokenAddressBase(address logic) internal pure returns (address) { + return + _predictCreate2Address({ + creator: GovernanceV3Base.EXECUTOR_LVL_1, + salt: keccak256('based-GHO'), + creationCode: type(TransparentUpgradeableProxy).creationCode, + constructorArgs: abi.encode( + logic, + address(MiscBase.PROXY_ADMIN), + abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) + ) + }); + } + + function _predictCreate2Address( + address creator, + bytes32 salt, + bytes memory creationCode, + bytes memory constructorArgs + ) internal pure returns (address) { + bytes32 hash = keccak256( + abi.encodePacked( + bytes1(0xff), + creator, + salt, + keccak256(abi.encodePacked(creationCode, constructorArgs)) + ) + ); + return address(uint160(uint256(hash))); } function _deployNewBurnMintTokenPool( @@ -802,4 +831,107 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa ); } } + + function test_E2E_Eth_Arb(uint256 amount) public { + { + vm.selectFork(eth.c.forkId); + uint256 bridgeableAmount = eth.tokenPool.getBridgeLimit() - + eth.tokenPool.getCurrentBridgedAmount(); + amount = bound(amount, 1, bridgeableAmount); + + vm.prank(alice); + eth.c.token.approve(address(eth.c.router), amount); + deal(address(eth.c.token), alice, amount); + + uint256 tokenPoolBalance = eth.c.token.balanceOf(address(eth.tokenPool)); + uint256 aliceBalance = eth.c.token.balanceOf(alice); + uint256 bridgedAmount = eth.tokenPool.getCurrentBridgedAmount(); + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage(CCIPSendParams({src: eth.c, dst: arb.c, sender: alice, amount: amount})); + + vm.expectEmit(address(eth.tokenPool)); + emit Locked(address(eth.c.arbOnRamp), amount); + vm.expectEmit(address(eth.c.arbOnRamp)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + eth.c.router.ccipSend{value: eventArg.feeTokenAmount}(arb.c.chainSelector, message); + + assertEq(eth.c.token.balanceOf(address(eth.tokenPool)), tokenPoolBalance + amount); + assertEq(eth.c.token.balanceOf(alice), aliceBalance - amount); + assertEq(eth.tokenPool.getCurrentBridgedAmount(), bridgedAmount + amount); + + // arb execute message + vm.selectFork(arb.c.forkId); + + aliceBalance = arb.c.token.balanceOf(alice); + uint256 bucketLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; + + vm.expectEmit(address(arb.tokenPool)); + emit Minted(address(arb.c.ethOffRamp), alice, amount); + + vm.prank(address(arb.c.ethOffRamp)); + arb.c.ethOffRamp.executeSingleMessage({ + message: eventArg, + offchainTokenData: new bytes[](message.tokenAmounts.length), + tokenGasOverrides: new uint32[](0) + }); + + assertEq(arb.c.token.balanceOf(alice), aliceBalance + amount); + assertEq( + arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel, + bucketLevel + amount + ); + } + + // send amount back to eth + { + // send back from arb + vm.selectFork(arb.c.forkId); + vm.prank(alice); + arb.c.token.approve(address(arb.c.router), amount); + + uint256 aliceBalance = arb.c.token.balanceOf(alice); + uint256 bucketLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage(CCIPSendParams({src: arb.c, dst: eth.c, sender: alice, amount: amount})); + + vm.expectEmit(address(arb.tokenPool)); + emit Burned(address(arb.c.ethOnRamp), amount); + vm.expectEmit(address(arb.c.ethOnRamp)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + arb.c.router.ccipSend{value: eventArg.feeTokenAmount}(eth.c.chainSelector, message); + + assertEq(arb.c.token.balanceOf(alice), aliceBalance - amount); + assertEq( + arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel, + bucketLevel - amount + ); + + // eth execute message + vm.selectFork(eth.c.forkId); + + uint256 bridgedAmount = eth.tokenPool.getCurrentBridgedAmount(); + + vm.expectEmit(address(eth.tokenPool)); + emit Released(address(eth.c.arbOffRamp), alice, amount); + vm.prank(address(eth.c.arbOffRamp)); + eth.c.arbOffRamp.executeSingleMessage({ + message: eventArg, + offchainTokenData: new bytes[](message.tokenAmounts.length), + tokenGasOverrides: new uint32[](0) + }); + + assertEq(eth.c.token.balanceOf(alice), amount); + assertEq(eth.tokenPool.getCurrentBridgedAmount(), bridgedAmount - amount); + } + } } From f866baff2520da6a1997caffb0453b79829ee10d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 21:21:40 +0530 Subject: [PATCH 058/123] chore: mock naming accuracy --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 8765d3493..db55dad1b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -68,7 +68,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { AaveV3Arbitrum_GHOBaseLaunch_20241223 internal proposal; address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); - address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: LockReleaseTokenPool 1.5.1'); + address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: BurnMintTokenPool 1.5.1'); address internal NEW_REMOTE_TOKEN_BASE = makeAddr('BASE: GhoToken'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); From c366c915325ed92090c26fbe6f9bc8f459e5605b Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 21:22:41 +0530 Subject: [PATCH 059/123] feat: base token through create2 --- ...AaveV3Base_GHOBaseLaunch_20241223_after.md | 11 + .../AaveV3Base_GHOBaseLaunch_20241223.sol | 16 +- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 189 +++++++++++++++++- 3 files changed, 200 insertions(+), 16 deletions(-) create mode 100644 diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md diff --git a/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md b/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md new file mode 100644 index 000000000..12b5664e5 --- /dev/null +++ b/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md @@ -0,0 +1,11 @@ +## Emodes changed + +### EMode: ETH correlated(id: 1) + + + +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 0e38d7ab5..2eb233c61 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -67,12 +67,16 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { } function _deployAndInitializeGhoToken() internal returns (IGhoToken) { - TransparentUpgradeableProxy tokenProxy = new TransparentUpgradeableProxy( - GHO_TOKEN_IMPL, - MiscBase.PROXY_ADMIN, - abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) - ); - return IGhoToken(address(tokenProxy)); + return + IGhoToken( + address( + new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( + GHO_TOKEN_IMPL, + MiscBase.PROXY_ADMIN, + abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) + ) + ) + ); } function _setupRemoteTokenPools() internal { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 13bc95038..fb9d8b563 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -1,10 +1,37 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import 'forge-std/Test.sol'; + +import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; +import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {MiscBase} from 'aave-address-book/MiscBase.sol'; +import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; +import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; + +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; + +import {CCIPUtils} from './utils/CCIPUtils.sol'; -import 'forge-std/Test.sol'; -import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; /** @@ -12,27 +39,169 @@ import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_2024 * command: FOUNDRY_PROFILE=base forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol -vv */ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { + struct CCIPSendParams { + address sender; + uint256 amount; + uint64 destChainSelector; + } + + uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; + uint64 internal constant BASE_CHAIN_SELECTOR = CCIPUtils.BASE_CHAIN_SELECTOR; + uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); + IEVM2EVMOnRamp internal constant ARB_ON_RAMP = + IEVM2EVMOnRamp(0x9D0ffA76C7F82C34Be313b5bFc6d42A72dA8CA69); + IEVM2EVMOnRamp internal constant ETH_ON_RAMP = + IEVM2EVMOnRamp(0x56b30A0Dcd8dc87Ec08b80FA09502bAB801fa78e); + + IEVM2EVMOffRamp_1_5 internal constant ARB_OFF_RAMP = + IEVM2EVMOffRamp_1_5(0x7D38c6363d5E4DFD500a691Bc34878b383F58d93); + IEVM2EVMOffRamp_1_5 internal constant ETH_OFF_RAMP = + IEVM2EVMOffRamp_1_5(0xCA04169671A81E4fB8768cfaD46c347ae65371F1); + + IRouter internal constant ROUTER = IRouter(0x881e3A65B4d4a04dD529061dd0071cf975F58bCD); + address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; + + IGhoToken internal GHO; + IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Base_GHOBaseLaunch_20241223 internal proposal; + address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); + address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); + address internal alice = makeAddr('alice'); + address internal bob = makeAddr('bob'); + address internal carol = makeAddr('carol'); + + 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); + error InvalidSourcePoolAddress(bytes); + function setUp() public { vm.createSelectFork(vm.rpcUrl('base'), 24072751); + + address ghoTokenImpl = _deployGhoTokenImpl(); + GHO = IGhoToken(_predictGhoTokenAddress(ghoTokenImpl)); + NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( + _deployNewBurnMintTokenPool( + address(GHO), + RMN_PROXY, + address(ROUTER), + GovernanceV3Base.EXECUTOR_LVL_1, // owner + MiscBase.PROXY_ADMIN + ) + ); + NEW_GHO_CCIP_STEWARD = IGhoCcipSteward( + _deployNewGhoCcipSteward( + address(NEW_TOKEN_POOL), + address(GHO), + GovernanceV3Base.EXECUTOR_LVL_1, // riskCouncil, using executor for convenience + false // bridgeLimitEnabled, *not present* in remote (burnMint) pools + ) + ); + proposal = new AaveV3Base_GHOBaseLaunch_20241223( - address(0), - address(0), - address(0), - address(0), - address(0) + address(NEW_TOKEN_POOL), + ghoTokenImpl, + address(NEW_GHO_CCIP_STEWARD), + NEW_REMOTE_POOL_ETH, + NEW_REMOTE_POOL_ARB + ); + + _performCcipPreReq(); + } + + function _performCcipPreReq() internal { + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO), GovernanceV3Base.EXECUTOR_LVL_1); + } + + function _deployGhoTokenImpl() internal returns (address) { + return address(new UpgradeableGhoToken()); + } + + function _predictGhoTokenAddress(address logic) internal view returns (address) { + return + _predictCreate2Address({ + creator: GovernanceV3Base.EXECUTOR_LVL_1, + salt: keccak256('based-GHO'), + creationCode: type(TransparentUpgradeableProxy).creationCode, + constructorArgs: abi.encode( + logic, + address(MiscBase.PROXY_ADMIN), + abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) + ) + }); + } + + function _predictCreate2Address( + address creator, + bytes32 salt, + bytes memory creationCode, + bytes memory constructorArgs + ) internal pure returns (address) { + bytes32 hash = keccak256( + abi.encodePacked( + bytes1(0xff), + creator, + salt, + keccak256(abi.encodePacked(creationCode, constructorArgs)) + ) ); + return address(uint160(uint256(hash))); + } + + function _deployNewBurnMintTokenPool( + address ghoToken, + address rmnProxy, + address router, + address owner, + address proxyAdmin + ) private returns (address) { + address newTokenPoolImpl = address( + new UpgradeableBurnMintTokenPool( + ghoToken, + 18, + rmnProxy, + false // allowListEnabled + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + address(proxyAdmin), + abi.encodeCall( + IUpgradeableBurnMintTokenPool_1_5_1.initialize, + ( + owner, + new address[](0), // allowList + router + ) + ) + ) + ); } - function test_temp() public pure { - assertTrue(1 == 1); + function _deployNewGhoCcipSteward( + address newTokenPool, + address ghoToken, + address riskCouncil, + bool bridgeLimitEnabled + ) internal returns (address) { + return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); } /** * @dev executes the generic test suite including e2e and config snapshots */ - function skip_test_defaultProposalExecution() public { + function test_defaultProposalExecution() public { defaultTest('AaveV3Base_GHOBaseLaunch_20241223', AaveV3Base.POOL, address(proposal)); } } From d6717dada6fd454061625a2eb3ecb5b5ce913a84 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:50:00 +0530 Subject: [PATCH 060/123] feat: expand _validateConfig in e2e test --- lib/aave-helpers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aave-helpers b/lib/aave-helpers index 1821d62cc..19d8ece8a 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit 1821d62ccddb4d9d66ad35405cbaaeec795bd1b2 +Subproject commit 19d8ece8a12d3d789ccb96fd184fef0a646b201c From 88a26e4ead7c5a1d2e039330ad25faddc9dae360 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 25 Dec 2024 17:44:33 +0530 Subject: [PATCH 061/123] feat: use deployed gho token impl on base, fix facilitator bucket to 20M instead of 25M --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 8 +-- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 5 +- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 56 ++++++++++++------- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 43 +------------- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 27 +++------ .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 8 +-- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 6 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 2 +- 8 files changed, 61 insertions(+), 94 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 97c7dfb01..458752397 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -14,15 +14,15 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; - IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; // replace with MiscArbitrum.GHO_CCIP_TOKEN_POOL once address-book is updated + IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; address public immutable REMOTE_TOKEN_POOL_BASE; - address public immutable REMOTE_GHO_TOKEN_BASE; // new deployment, not present in address-book + // https://basescan.org/address/0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910 + address public constant REMOTE_GHO_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted - constructor(address tokenPoolArb, address tokenPoolBase, address ghoTokenBase) { + constructor(address tokenPoolArb, address tokenPoolBase) { TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPoolArb); REMOTE_TOKEN_POOL_BASE = tokenPoolBase; - REMOTE_GHO_TOKEN_BASE = ghoTokenBase; } function execute() external { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index db55dad1b..33c3e9cca 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -60,6 +60,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); + address public constant NEW_REMOTE_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; @@ -69,7 +70,6 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: BurnMintTokenPool 1.5.1'); - address internal NEW_REMOTE_TOKEN_BASE = makeAddr('BASE: GhoToken'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -88,8 +88,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { _upgradeArbTo1_5_1(); proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223( address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_BASE, - NEW_REMOTE_TOKEN_BASE + NEW_REMOTE_POOL_BASE ); _validateConstants(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 2eb233c61..91ca83095 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -24,14 +24,17 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant ETH_CHAIN_SELECTOR = 5009297550715157269; uint64 public constant ARB_CHAIN_SELECTOR = 4949039107694359620; - uint128 public constant CCIP_BUCKET_CAPACITY = 25_000_000e18; // 25M GHO + uint128 public constant CCIP_BUCKET_CAPACITY = 20_000_000e18; // 20M GHO ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; - address public immutable GHO_TOKEN_IMPL; + // https://basescan.org/address/0x26d595dddbad81bf976ef6f24686a12a800b141f + address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + // predicted address, will be deployed in the AIP + IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910); address public immutable GHO_CCIP_STEWARD; address public immutable REMOTE_TOKEN_POOL_ETH; @@ -39,42 +42,53 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { constructor( address tokenPool, - address ghoTokenImpl, address ghoCcipSteward, address tokenPoolEth, address tokenPoolArb ) { TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPool); - GHO_TOKEN_IMPL = ghoTokenImpl; GHO_CCIP_STEWARD = ghoCcipSteward; REMOTE_TOKEN_POOL_ETH = tokenPoolEth; REMOTE_TOKEN_POOL_ARB = tokenPoolArb; } function execute() external { - IGhoToken GHO_TOKEN = _deployAndInitializeGhoToken(); - - GHO_TOKEN.grantRole(GHO_TOKEN.FACILITATOR_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); - GHO_TOKEN.grantRole(GHO_TOKEN.BUCKET_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); - GHO_TOKEN.addFacilitator(address(TOKEN_POOL), 'CCIP TokenPool v1.5.1', CCIP_BUCKET_CAPACITY); - - TOKEN_ADMIN_REGISTRY.acceptAdminRole(address(GHO_TOKEN)); - TOKEN_POOL.acceptOwnership(); + _acceptOwnership(); + if (_deployAndInitializeGhoToken() != address(GHO_TOKEN_PROXY)) revert(); + + GHO_TOKEN_PROXY.grantRole( + GHO_TOKEN_PROXY.FACILITATOR_MANAGER_ROLE(), + GovernanceV3Base.EXECUTOR_LVL_1 + ); + GHO_TOKEN_PROXY.grantRole( + GHO_TOKEN_PROXY.BUCKET_MANAGER_ROLE(), + GovernanceV3Base.EXECUTOR_LVL_1 + ); + GHO_TOKEN_PROXY.addFacilitator( + address(TOKEN_POOL), + 'CCIP TokenPool v1.5.1', + CCIP_BUCKET_CAPACITY + ); + + TOKEN_POOL.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); _setupRemoteTokenPools(); - TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN), address(TOKEN_POOL)); + TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN_PROXY), address(TOKEN_POOL)); + } + + function _acceptOwnership() internal { + TOKEN_ADMIN_REGISTRY.acceptAdminRole(address(GHO_TOKEN_PROXY)); + TOKEN_POOL.acceptOwnership(); } - function _deployAndInitializeGhoToken() internal returns (IGhoToken) { + function _deployAndInitializeGhoToken() internal returns (address) { return - IGhoToken( - address( - new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( - GHO_TOKEN_IMPL, - MiscBase.PROXY_ADMIN, - abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) - ) + address( + new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( + GHO_TOKEN_IMPL, + MiscBase.PROXY_ADMIN, + abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) ) ); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index fb9d8b563..bd6b879ad 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -64,7 +64,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IRouter internal constant ROUTER = IRouter(0x881e3A65B4d4a04dD529061dd0071cf975F58bCD); address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; - IGhoToken internal GHO; + address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + IGhoToken public constant GHO = IGhoToken(0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910); // predicted address, will be deployed in the AIP IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Base_GHOBaseLaunch_20241223 internal proposal; @@ -83,10 +84,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('base'), 24072751); + vm.createSelectFork(vm.rpcUrl('base'), 24139320); - address ghoTokenImpl = _deployGhoTokenImpl(); - GHO = IGhoToken(_predictGhoTokenAddress(ghoTokenImpl)); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( _deployNewBurnMintTokenPool( address(GHO), @@ -107,7 +106,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { proposal = new AaveV3Base_GHOBaseLaunch_20241223( address(NEW_TOKEN_POOL), - ghoTokenImpl, address(NEW_GHO_CCIP_STEWARD), NEW_REMOTE_POOL_ETH, NEW_REMOTE_POOL_ARB @@ -121,41 +119,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO), GovernanceV3Base.EXECUTOR_LVL_1); } - function _deployGhoTokenImpl() internal returns (address) { - return address(new UpgradeableGhoToken()); - } - - function _predictGhoTokenAddress(address logic) internal view returns (address) { - return - _predictCreate2Address({ - creator: GovernanceV3Base.EXECUTOR_LVL_1, - salt: keccak256('based-GHO'), - creationCode: type(TransparentUpgradeableProxy).creationCode, - constructorArgs: abi.encode( - logic, - address(MiscBase.PROXY_ADMIN), - abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) - ) - }); - } - - function _predictCreate2Address( - address creator, - bytes32 salt, - bytes memory creationCode, - bytes memory constructorArgs - ) internal pure returns (address) { - bytes32 hash = keccak256( - abi.encodePacked( - bytes1(0xff), - creator, - salt, - keccak256(abi.encodePacked(creationCode, constructorArgs)) - ) - ); - return address(uint160(uint256(hash))); - } - function _deployNewBurnMintTokenPool( address ghoToken, address rmnProxy, diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index a6fc0f40d..7e1654734 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -94,6 +94,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; + address public constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + IGhoToken public constant GHO_TOKEN_BASE = IGhoToken(0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910); // predicted address, will be deployed in the AIP event CCIPSendRequested(IInternal.EVM2EVMMessage message); event Locked(address indexed sender, uint256 amount); @@ -103,7 +105,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { function setUp() public virtual { arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24072751); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24139320); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21463360); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); @@ -117,10 +119,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { eth.c.chainSelector = 5009297550715157269; vm.selectFork(base.c.forkId); - address ghoTokenImplBase = _deployGhoTokenImpl(); - address ghoTokenBase = _predictGhoTokenAddressBase(ghoTokenImplBase); address newTokenPoolBase = _deployNewBurnMintTokenPool( - ghoTokenBase, + address(GHO_TOKEN_BASE), RMN_PROXY_BASE, ROUTER_BASE, GovernanceV3Base.EXECUTOR_LVL_1, // owner @@ -128,17 +128,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ); address ghoCcipStewardBase = _deployNewGhoCcipSteward( newTokenPoolBase, - ghoTokenBase, + address(GHO_TOKEN_BASE), GovernanceV3Base.EXECUTOR_LVL_1, // riskCouncil, using executor for convenience false // bridgeLimitEnabled, *not present* in remote (burnMint) pools ); vm.selectFork(arb.c.forkId); - arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223( - newTokenPoolArb, - newTokenPoolBase, - ghoTokenBase - ); + arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(newTokenPoolArb, newTokenPoolBase); arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); arb.c.router = IRouter(arb.tokenPool.getRouter()); arb.c.baseOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(base.c.chainSelector)); @@ -149,14 +145,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(base.c.forkId); base.proposal = new AaveV3Base_GHOBaseLaunch_20241223( newTokenPoolBase, - ghoTokenImplBase, ghoCcipStewardBase, newTokenPoolEth, newTokenPoolArb ); base.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolBase); base.c.tokenAdminRegistry = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); - base.c.token = IGhoToken(ghoTokenBase); + base.c.token = GHO_TOKEN_BASE; base.c.router = IRouter(base.tokenPool.getRouter()); base.c.arbOnRamp = IEVM2EVMOnRamp(base.c.router.getOnRamp(arb.c.chainSelector)); base.c.ethOnRamp = IEVM2EVMOnRamp(base.c.router.getOnRamp(eth.c.chainSelector)); @@ -164,11 +159,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { base.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0xCA04169671A81E4fB8768cfaD46c347ae65371F1); vm.selectFork(eth.c.forkId); - eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223( - newTokenPoolEth, - newTokenPoolBase, - ghoTokenBase - ); + eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(newTokenPoolEth, newTokenPoolBase); eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); eth.c.router = IRouter(eth.tokenPool.getRouter()); eth.c.arbOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(arb.c.chainSelector)); @@ -433,7 +424,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { // proposal constants assertEq(base.proposal.ETH_CHAIN_SELECTOR(), eth.c.chainSelector); assertEq(base.proposal.ARB_CHAIN_SELECTOR(), arb.c.chainSelector); - assertEq(base.proposal.CCIP_BUCKET_CAPACITY(), 25_000_000e18); + assertEq(base.proposal.CCIP_BUCKET_CAPACITY(), 20_000_000e18); assertEq(address(base.proposal.TOKEN_ADMIN_REGISTRY()), address(base.c.tokenAdminRegistry)); assertEq(address(base.proposal.TOKEN_POOL()), address(base.tokenPool)); IGhoCcipSteward ghoCcipSteward = IGhoCcipSteward(base.proposal.GHO_CCIP_STEWARD()); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index b484270d4..104eac366 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -14,15 +14,15 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; - IUpgradeableLockReleaseTokenPool_1_5_1 public immutable TOKEN_POOL; // replace with MiscEthereum.GHO_CCIP_TOKEN_POOL once address-book is updated + IUpgradeableLockReleaseTokenPool_1_5_1 public immutable TOKEN_POOL; address public immutable REMOTE_TOKEN_POOL_BASE; - address public immutable REMOTE_GHO_TOKEN_BASE; // new deployment, not present in address-book + // https://basescan.org/address/0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910 + address public constant REMOTE_GHO_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted - constructor(address tokenPoolEth, address tokenPoolBase, address ghoTokenBase) { + constructor(address tokenPoolEth, address tokenPoolBase) { TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(tokenPoolEth); REMOTE_TOKEN_POOL_BASE = tokenPoolBase; - REMOTE_GHO_TOKEN_BASE = ghoTokenBase; } function execute() external { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index e79ed8e37..ba5546e3b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -59,6 +59,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); + address public constant NEW_REMOTE_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; @@ -68,7 +69,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: BurnMintTokenPool 1.5.1'); - address internal NEW_REMOTE_TOKEN_BASE = makeAddr('BASE: GhoToken'); + address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -87,8 +88,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { _upgradeEthTo1_5_1(); proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223( address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_BASE, - NEW_REMOTE_TOKEN_BASE + NEW_REMOTE_POOL_BASE ); _validateConstants(); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 8fdb40d54..6ae5ea3f6 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -15,6 +15,6 @@ export const config: ConfigFile = { poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21463360}}, AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, - AaveV3Base: {configs: {OTHERS: {}}, cache: {blockNumber: 24072751}}, + AaveV3Base: {configs: {OTHERS: {}}, cache: {blockNumber: 24139320}}, }, }; From 0f19b524c0d9c810c85b381b16257563645241a0 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 25 Dec 2024 18:03:24 +0530 Subject: [PATCH 062/123] fix: merge latest upstream --- ...efore_AaveV3Base_GHOBaseLaunch_20241223_after.md | 6 ------ lib/aave-helpers | 2 +- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 4 ++-- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 8 +++++--- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 5 +++-- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 5 +++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 13 ++++++++----- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 4 ++-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 8 +++++--- 9 files changed, 29 insertions(+), 26 deletions(-) diff --git a/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md b/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md index 12b5664e5..c15d3e2bc 100644 --- a/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md +++ b/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md @@ -1,9 +1,3 @@ -## Emodes changed - -### EMode: ETH correlated(id: 1) - - - ## Raw diff ```json diff --git a/lib/aave-helpers b/lib/aave-helpers index 19d8ece8a..1821d62cc 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit 19d8ece8a12d3d789ccb96fd184fef0a646b201c +Subproject commit 1821d62ccddb4d9d66ad35405cbaaeec795bd1b2 diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 458752397..f01dd5e49 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -17,8 +17,8 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; address public immutable REMOTE_TOKEN_POOL_BASE; - // https://basescan.org/address/0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910 - address public constant REMOTE_GHO_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted + // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D + address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted constructor(address tokenPoolArb, address tokenPoolBase) { TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPoolArb); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 33c3e9cca..228c1c99d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -20,9 +20,11 @@ import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; @@ -60,7 +62,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); - address public constant NEW_REMOTE_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted + address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; @@ -115,7 +117,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { function _deployNewTokenPoolArb() private returns (address) { IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( - MiscArbitrum.GHO_CCIP_TOKEN_POOL + GhoArbitrum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolImpl = address( new UpgradeableBurnMintTokenPool( @@ -129,7 +131,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - address(MiscArbitrum.PROXY_ADMIN), + ProxyAdmin(MiscArbitrum.PROXY_ADMIN), abi.encodeCall( IUpgradeableBurnMintTokenPool_1_5_1.initialize, ( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 91ca83095..f1ad87071 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -2,6 +2,7 @@ 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 {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; @@ -34,7 +35,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://basescan.org/address/0x26d595dddbad81bf976ef6f24686a12a800b141f address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; // predicted address, will be deployed in the AIP - IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910); + IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); address public immutable GHO_CCIP_STEWARD; address public immutable REMOTE_TOKEN_POOL_ETH; @@ -87,7 +88,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { address( new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( GHO_TOKEN_IMPL, - MiscBase.PROXY_ADMIN, + ProxyAdmin(MiscBase.PROXY_ADMIN), abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) ) ); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index bd6b879ad..1a85f0fd6 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -26,6 +26,7 @@ import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; @@ -65,7 +66,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - IGhoToken public constant GHO = IGhoToken(0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910); // predicted address, will be deployed in the AIP + IGhoToken public constant GHO = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Base_GHOBaseLaunch_20241223 internal proposal; @@ -139,7 +140,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - address(proxyAdmin), + ProxyAdmin(proxyAdmin), abi.encodeCall( IUpgradeableBurnMintTokenPool_1_5_1.initialize, ( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 7e1654734..ee3ff49d6 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -22,11 +22,14 @@ import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol'; @@ -95,7 +98,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; address public constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - IGhoToken public constant GHO_TOKEN_BASE = IGhoToken(0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910); // predicted address, will be deployed in the AIP + IGhoToken public constant GHO_TOKEN_BASE = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP event CCIPSendRequested(IInternal.EVM2EVMMessage message); event Locked(address indexed sender, uint256 amount); @@ -176,7 +179,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { // deploy new token pools and ghoCcipStewards vm.selectFork(eth.c.forkId); IUpgradeableLockReleaseTokenPool_1_4 existingPoolEth = IUpgradeableLockReleaseTokenPool_1_4( - MiscEthereum.GHO_CCIP_TOKEN_POOL + GhoEthereum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolEth = _deployNewLockReleaseTokenPool( AaveV3EthereumAssets.GHO_UNDERLYING, @@ -195,7 +198,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(arb.c.forkId); IUpgradeableBurnMintTokenPool_1_4 existingPoolArb = IUpgradeableBurnMintTokenPool_1_4( - MiscArbitrum.GHO_CCIP_TOKEN_POOL + GhoArbitrum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolArb = _deployNewBurnMintTokenPool( AaveV3ArbitrumAssets.GHO_UNDERLYING, @@ -300,7 +303,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - address(proxyAdmin), + ProxyAdmin(proxyAdmin), abi.encodeCall( IUpgradeableBurnMintTokenPool_1_5_1.initialize, ( @@ -335,7 +338,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - address(proxyAdmin), + ProxyAdmin(proxyAdmin), abi.encodeCall( IUpgradeableLockReleaseTokenPool_1_5_1.initialize, ( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index 104eac366..d6503e80d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -17,8 +17,8 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { IUpgradeableLockReleaseTokenPool_1_5_1 public immutable TOKEN_POOL; address public immutable REMOTE_TOKEN_POOL_BASE; - // https://basescan.org/address/0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910 - address public constant REMOTE_GHO_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted + // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D + address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted constructor(address tokenPoolEth, address tokenPoolBase) { TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(tokenPoolEth); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index ba5546e3b..52bff3e33 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -17,12 +17,14 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; @@ -59,7 +61,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); - address public constant NEW_REMOTE_TOKEN_BASE = 0x888053142E093BcB4D8c3c1B79ce92DBa9C2E910; // predicted + address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; @@ -115,7 +117,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { function _deployNewTokenPoolEth() private returns (address) { IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( - MiscEthereum.GHO_CCIP_TOKEN_POOL + GhoEthereum.GHO_CCIP_TOKEN_POOL ); address newTokenPoolImpl = address( new UpgradeableLockReleaseTokenPool( @@ -131,7 +133,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address( new TransparentUpgradeableProxy( newTokenPoolImpl, - MiscEthereum.PROXY_ADMIN, + ProxyAdmin(MiscEthereum.PROXY_ADMIN), abi.encodeCall( IUpgradeableLockReleaseTokenPool_1_5_1.initialize, ( From 459ec753fb1964b6d8606a11c8d1e38102865c2d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 25 Dec 2024 18:25:34 +0530 Subject: [PATCH 063/123] chore: fix chain selector lib typo --- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index d4d1b687c..84d95018b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -45,7 +45,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { } uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; - uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = From 514bde6fd66862913986b2e04f0bca73d3d8606e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 26 Dec 2024 16:15:49 +0530 Subject: [PATCH 064/123] fix: tmp fix remappings such that gho-core OZ and aave-v3 OZ do not collide --- remappings.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/remappings.txt b/remappings.txt index 9c8cea061..a542e09d3 100644 --- a/remappings.txt +++ b/remappings.txt @@ -4,11 +4,15 @@ 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/ @openzeppelin/contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/ -@openzeppelin/contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ aave-v3-origin-tests/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/tests/ ds-test/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/ erc4626-tests/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ openzeppelin-contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/ openzeppelin-contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/ +@aave/core-v3/=lib/gho-core/lib/aave-v3-core/ +@openzeppelin/contracts/access/=lib/gho-core/lib/openzeppelin-contracts/contracts/access/ +@openzeppelin/contracts/utils/=lib/gho-core/lib/openzeppelin-contracts/contracts/utils/ +@openzeppelin/contracts/token/=lib/gho-core/lib/openzeppelin-contracts/contracts/token/ +@openzeppelin/contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ aave-ccip/=lib/ccip/contracts/src/v0.8/ccip gho-core/=lib/gho-core/src/contracts From 59e1dd25e61659099e00ce1b27b9c0866d9ea386 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 26 Dec 2024 16:16:32 +0530 Subject: [PATCH 065/123] feat: stewards, base tests --- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 75 +++- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 397 ++++++++++++++++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 109 +++-- src/interfaces/IOwnable.sol | 8 + 4 files changed, 507 insertions(+), 82 deletions(-) create mode 100644 src/interfaces/IOwnable.sol diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index f1ad87071..b94b7c816 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -8,8 +8,10 @@ import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGen import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -36,6 +38,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; // predicted address, will be deployed in the AIP IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); + + address public immutable GHO_AAVE_STEWARD; + address public immutable GHO_BUCKET_STEWARD; address public immutable GHO_CCIP_STEWARD; address public immutable REMOTE_TOKEN_POOL_ETH; @@ -43,37 +48,28 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { constructor( address tokenPool, - address ghoCcipSteward, address tokenPoolEth, - address tokenPoolArb + address tokenPoolArb, + address ghoAaveSteward, + address ghoBucketSteward, + address ghoCcipSteward ) { TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPool); - GHO_CCIP_STEWARD = ghoCcipSteward; REMOTE_TOKEN_POOL_ETH = tokenPoolEth; REMOTE_TOKEN_POOL_ARB = tokenPoolArb; + GHO_AAVE_STEWARD = ghoAaveSteward; + GHO_BUCKET_STEWARD = ghoBucketSteward; + GHO_CCIP_STEWARD = ghoCcipSteward; } function execute() external { _acceptOwnership(); - if (_deployAndInitializeGhoToken() != address(GHO_TOKEN_PROXY)) revert(); - GHO_TOKEN_PROXY.grantRole( - GHO_TOKEN_PROXY.FACILITATOR_MANAGER_ROLE(), - GovernanceV3Base.EXECUTOR_LVL_1 - ); - GHO_TOKEN_PROXY.grantRole( - GHO_TOKEN_PROXY.BUCKET_MANAGER_ROLE(), - GovernanceV3Base.EXECUTOR_LVL_1 - ); - GHO_TOKEN_PROXY.addFacilitator( - address(TOKEN_POOL), - 'CCIP TokenPool v1.5.1', - CCIP_BUCKET_CAPACITY - ); + if (_deployAndInitializeGhoToken() != address(GHO_TOKEN_PROXY)) revert(); - TOKEN_POOL.setRateLimitAdmin(address(GHO_CCIP_STEWARD)); + _setupStewardsAndTokenPoolOnGho(); - _setupRemoteTokenPools(); + _setupRemoteTokenPools(); // eth & arb TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN_PROXY), address(TOKEN_POOL)); } @@ -94,6 +90,39 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { ); } + function _setupStewardsAndTokenPoolOnGho() internal { + GHO_TOKEN_PROXY.grantRole( + GHO_TOKEN_PROXY.FACILITATOR_MANAGER_ROLE(), + GovernanceV3Base.EXECUTOR_LVL_1 + ); + GHO_TOKEN_PROXY.grantRole( + GHO_TOKEN_PROXY.BUCKET_MANAGER_ROLE(), + GovernanceV3Base.EXECUTOR_LVL_1 + ); + + // Token Pool as facilitator with 20M GHO capacity + GHO_TOKEN_PROXY.addFacilitator( + address(TOKEN_POOL), + 'CCIP TokenPool v1.5.1', + CCIP_BUCKET_CAPACITY + ); + + // Gho Aave Steward + AaveV3Base.ACL_MANAGER.grantRole(AaveV3Base.ACL_MANAGER.RISK_ADMIN_ROLE(), GHO_AAVE_STEWARD); + + // Gho Bucket Steward + GHO_TOKEN_PROXY.grantRole(GHO_TOKEN_PROXY.BUCKET_MANAGER_ROLE(), GHO_BUCKET_STEWARD); + address[] memory facilitatorList = new address[](1); + facilitatorList[0] = address(TOKEN_POOL); + IGhoBucketSteward(GHO_BUCKET_STEWARD).setControlledFacilitator({ + facilitatorList: facilitatorList, + approve: true + }); + + // Gho CCIP Steward + TOKEN_POOL.setRateLimitAdmin(GHO_CCIP_STEWARD); + } + function _setupRemoteTokenPools() internal { IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ isEnabled: false, @@ -102,12 +131,12 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { }); IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] - memory chains = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](2); + memory chainsToAdd = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](2); { bytes[] memory remotePoolAddresses = new bytes[](1); remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_ETH); - chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + chainsToAdd[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: ETH_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING), @@ -119,7 +148,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { { bytes[] memory remotePoolAddresses = new bytes[](1); remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_ARB); - chains[1] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + chainsToAdd[1] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: ARB_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING), @@ -130,7 +159,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { TOKEN_POOL.applyChainUpdates({ remoteChainSelectorsToRemove: new uint64[](0), - chainsToAdd: chains + chainsToAdd: chainsToAdd }); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 1a85f0fd6..d4120eb85 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; @@ -12,23 +12,25 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IOwnable} from 'src/interfaces/IOwnable.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; +import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; +import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; -import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol'; +import {GhoAaveSteward} from 'gho-core/misc/GhoAaveSteward.sol'; +import {GhoBucketSteward} from 'gho-core/misc/GhoBucketSteward.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; @@ -39,7 +41,7 @@ import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_2024 * @dev Test for AaveV3Base_GHOBaseLaunch_20241223 * command: FOUNDRY_PROFILE=base forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol -vv */ -contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { +contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { struct CCIPSendParams { address sender; uint256 amount; @@ -67,12 +69,17 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; IGhoToken public constant GHO = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + + IGhoAaveSteward internal NEW_GHO_AAVE_STEWARD; + IGhoBucketSteward internal NEW_GHO_BUCKET_STEWARD; IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Base_GHOBaseLaunch_20241223 internal proposal; address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); + address internal RISK_COUNCIL = makeAddr('riskCouncil'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -84,7 +91,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error CallerIsNotARampOnRouter(address); error InvalidSourcePoolAddress(bytes); - function setUp() public { + function setUp() public virtual { vm.createSelectFork(vm.rpcUrl('base'), 24139320); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( @@ -96,20 +103,15 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { MiscBase.PROXY_ADMIN ) ); - NEW_GHO_CCIP_STEWARD = IGhoCcipSteward( - _deployNewGhoCcipSteward( - address(NEW_TOKEN_POOL), - address(GHO), - GovernanceV3Base.EXECUTOR_LVL_1, // riskCouncil, using executor for convenience - false // bridgeLimitEnabled, *not present* in remote (burnMint) pools - ) - ); + (NEW_GHO_AAVE_STEWARD, NEW_GHO_BUCKET_STEWARD, NEW_GHO_CCIP_STEWARD) = _deployStewards(); proposal = new AaveV3Base_GHOBaseLaunch_20241223( address(NEW_TOKEN_POOL), - address(NEW_GHO_CCIP_STEWARD), NEW_REMOTE_POOL_ETH, - NEW_REMOTE_POOL_ARB + NEW_REMOTE_POOL_ARB, + address(NEW_GHO_AAVE_STEWARD), + address(NEW_GHO_BUCKET_STEWARD), + address(NEW_GHO_CCIP_STEWARD) ); _performCcipPreReq(); @@ -153,19 +155,366 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ); } - function _deployNewGhoCcipSteward( - address newTokenPool, - address ghoToken, - address riskCouncil, - bool bridgeLimitEnabled - ) internal returns (address) { - return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); + function _deployStewards() + internal + returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) + { + address aaveSteward = address( + new GhoAaveSteward({ + owner: GovernanceV3Base.EXECUTOR_LVL_1, + addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), + poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), + ghoToken: address(GHO), + riskCouncil: RISK_COUNCIL, + borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ + optimalUsageRatioMaxChange: 0, + baseVariableBorrowRateMaxChange: 0, + variableRateSlope1MaxChange: 0, + variableRateSlope2MaxChange: 0 + }) + }) + ); + address bucketSteward = address( + new GhoBucketSteward({ + owner: GovernanceV3Base.EXECUTOR_LVL_1, + ghoToken: address(GHO), + riskCouncil: RISK_COUNCIL + }) + ); + address ccipSteward = address( + new GhoCcipSteward({ + ghoToken: address(GHO), + ghoTokenPool: address(NEW_TOKEN_POOL), + riskCouncil: RISK_COUNCIL, + bridgeLimitEnabled: false + }) + ); + return ( + IGhoAaveSteward(aaveSteward), + IGhoBucketSteward(bucketSteward), + IGhoCcipSteward(ccipSteward) + ); } + 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(GHO), amount: params.amount}); + + uint256 feeAmount = ROUTER.getFee(params.destChainSelector, message); + deal(params.sender, feeAmount); + + IInternal.EVM2EVMMessage memory eventArg = CCIPUtils.messageToEvent( + CCIPUtils.MessageToEventParams({ + message: message, + router: ROUTER, + sourceChainSelector: BASE_CHAIN_SELECTOR, + destChainSelector: params.destChainSelector, + feeTokenAmount: feeAmount, + originalSender: params.sender, + sourceToken: address(GHO), + destinationToken: address( + params.destChainSelector == ARB_CHAIN_SELECTOR + ? AaveV3ArbitrumAssets.GHO_UNDERLYING + : AaveV3EthereumAssets.GHO_UNDERLYING + ) + }) + ); + + return (message, eventArg); + } + + function _tokenBucketToConfig( + IRateLimiter.TokenBucket memory bucket + ) internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: bucket.isEnabled, + capacity: bucket.capacity, + rate: bucket.rate + }); + } + + function _getDisabledConfig() internal pure returns (IRateLimiter.Config memory) { + return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + } + + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + } +} + +contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLaunch_20241223_Base { /** * @dev executes the generic test suite including e2e and config snapshots */ function test_defaultProposalExecution() public { defaultTest('AaveV3Base_GHOBaseLaunch_20241223', AaveV3Base.POOL, address(proposal)); } + + function test_stewardRolesAndConfig() public { + // gho token is deployed in the AIP, does not existing before + + assertFalse( + AaveV3Base.ACL_MANAGER.hasRole( + AaveV3Base.ACL_MANAGER.RISK_ADMIN_ROLE(), + address(NEW_GHO_AAVE_STEWARD) + ) + ); + assertEq(NEW_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 0); + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(0)); + + executePayload(vm, address(proposal)); + + assertTrue(GHO.hasRole(GHO.FACILITATOR_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1)); + assertTrue(GHO.hasRole(GHO.BUCKET_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1)); + + IGhoToken.Facilitator memory facilitator = GHO.getFacilitator(address(NEW_TOKEN_POOL)); + assertEq(facilitator.label, 'CCIP TokenPool v1.5.1'); + assertEq(facilitator.bucketLevel, 0); + assertEq(facilitator.bucketCapacity, proposal.CCIP_BUCKET_CAPACITY()); + + assertTrue( + AaveV3Base.ACL_MANAGER.hasRole( + AaveV3Base.ACL_MANAGER.RISK_ADMIN_ROLE(), + address(NEW_GHO_AAVE_STEWARD) + ) + ); + + assertTrue(GHO.hasRole(GHO.BUCKET_MANAGER_ROLE(), address(NEW_GHO_BUCKET_STEWARD))); + + address[] memory facilitatorList = NEW_GHO_BUCKET_STEWARD.getControlledFacilitators(); + assertEq(facilitatorList.length, 1); + assertEq(facilitatorList[0], address(NEW_TOKEN_POOL)); + assertTrue(NEW_GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); + } + + function test_newTokenPoolInitialization() public { + vm.expectRevert('Initializable: contract is already initialized'); + NEW_TOKEN_POOL.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); + assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); + + address IMPL = _getImplementation(address(NEW_TOKEN_POOL)); + vm.expectRevert('Initializable: contract is already initialized'); + IUpgradeableBurnMintTokenPool_1_5_1(IMPL).initialize( + makeAddr('owner'), + new address[](0), + makeAddr('router') + ); + assertEq(_readInitialized(IMPL), 255); + } + + function test_stewardsConfig() public view { + assertEq(IOwnable(address(NEW_GHO_AAVE_STEWARD)).owner(), GovernanceV3Base.EXECUTOR_LVL_1); + assertEq( + NEW_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER(), + address(AaveV3Base.POOL_ADDRESSES_PROVIDER) + ); + assertEq(NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), address(AaveV3Base.UI_POOL_DATA_PROVIDER)); + assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); + IGhoAaveSteward.BorrowRateConfig memory config = NEW_GHO_AAVE_STEWARD.getBorrowRateConfig(); + assertEq(config.optimalUsageRatioMaxChange, 0); + assertEq(config.baseVariableBorrowRateMaxChange, 0); + assertEq(config.variableRateSlope1MaxChange, 0); + assertEq(config.variableRateSlope2MaxChange, 0); + + assertEq(IOwnable(address(NEW_GHO_BUCKET_STEWARD)).owner(), GovernanceV3Base.EXECUTOR_LVL_1); + assertEq(NEW_GHO_BUCKET_STEWARD.GHO_TOKEN(), address(GHO)); + assertEq(NEW_GHO_BUCKET_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); + assertEq(NEW_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 0); // before AIP, no controlled facilitators are set + + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), address(GHO)); + assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); + assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); + uint256 ccipDebounceValue = uint256(vm.load(address(NEW_GHO_CCIP_STEWARD), bytes32(0))); + IGhoCcipSteward.CcipDebounce memory ccipDebounce = IGhoCcipSteward.CcipDebounce({ + bridgeLimitLastUpdate: uint40(ccipDebounceValue >> 216), + rateLimitLastUpdate: uint40(ccipDebounceValue >> 176) + }); + assertEq(ccipDebounce.bridgeLimitLastUpdate, 0); + assertEq(ccipDebounce.rateLimitLastUpdate, 0); + } +} + +contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLaunch_20241223_Base { + function setUp() public override { + super.setUp(); + + executePayload(vm, address(proposal)); + } + + function test_sendMessageToArbSucceeds(uint256 amount) public { + amount = bound(amount, 1, 5_000_000e18); + // mock previously bridged amount + vm.prank(address(NEW_TOKEN_POOL)); + GHO.mint(alice, amount); // increase bucket level + + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, destChainSelector: ARB_CHAIN_SELECTOR}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Burned(address(ARB_ON_RAMP), amount); + vm.expectEmit(address(ARB_ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ARB_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel - amount); + } + + function test_sendMessageToEthSucceeds(uint256 amount) public { + amount = bound(amount, 1, 5_000_000e18); + // mock previously bridged amount + vm.prank(address(NEW_TOKEN_POOL)); + GHO.mint(alice, amount); // increase bucket level + + deal(address(GHO), alice, amount); + vm.prank(alice); + GHO.approve(address(ROUTER), amount); + + uint256 aliceBalance = GHO.balanceOf(alice); + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + + ( + IClient.EVM2AnyMessage memory message, + IInternal.EVM2EVMMessage memory eventArg + ) = _getTokenMessage( + CCIPSendParams({amount: amount, sender: alice, destChainSelector: ETH_CHAIN_SELECTOR}) + ); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Burned(address(ETH_ON_RAMP), amount); + vm.expectEmit(address(ETH_ON_RAMP)); + emit CCIPSendRequested(eventArg); + + vm.prank(alice); + ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); + + assertEq(GHO.balanceOf(alice), aliceBalance - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel - amount); + } + + function test_offRampViaArbSucceeds(uint256 amount) public { + amount = bound(amount, 1, GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity); // initially, bucketLevel == 0 + + uint256 aliceBalance = GHO.balanceOf(alice); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Minted(address(ARB_OFF_RAMP), alice, amount); + + vm.prank(address(ARB_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ARB)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + } + + function test_offRampViaEthSucceeds(uint256 amount) public { + amount = bound(amount, 1, GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity); // initially, bucketLevel == 0 + + uint256 aliceBalance = GHO.balanceOf(alice); + + vm.expectEmit(address(NEW_TOKEN_POOL)); + emit Minted(address(ETH_OFF_RAMP), alice, amount); + + vm.prank(address(ETH_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ETH)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, amount); + assertEq(GHO.balanceOf(alice), aliceBalance + amount); + } + + function test_cannotOffRampOtherChainMessages() public { + uint256 amount = 100e18; + + vm.expectRevert( + abi.encodeWithSelector( + InvalidSourcePoolAddress.selector, + abi.encode(address(NEW_REMOTE_POOL_ETH)) + ) + ); + vm.prank(address(ARB_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ARB_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ETH)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + + vm.expectRevert( + abi.encodeWithSelector( + InvalidSourcePoolAddress.selector, + abi.encode(address(NEW_REMOTE_POOL_ARB)) + ) + ); + vm.prank(address(ETH_OFF_RAMP)); + NEW_TOKEN_POOL.releaseOrMint( + IPool_CCIP.ReleaseOrMintInV1({ + originalSender: abi.encode(alice), + remoteChainSelector: ETH_CHAIN_SELECTOR, + receiver: alice, + amount: amount, + localToken: address(GHO), + sourcePoolAddress: abi.encode(address(NEW_REMOTE_POOL_ARB)), + sourcePoolData: new bytes(0), + offchainTokenData: new bytes(0) + }) + ); + } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index ee3ff49d6..3bec75b7e 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -15,10 +15,13 @@ import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; +import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; +import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; @@ -32,7 +35,8 @@ import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent- import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {UpgradeableLockReleaseTokenPool} from 'aave-ccip/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol'; +import {GhoAaveSteward} from 'gho-core/misc/GhoAaveSteward.sol'; +import {GhoBucketSteward} from 'gho-core/misc/GhoBucketSteward.sol'; import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -87,6 +91,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { Common c; } + address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; + address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; + address internal RISK_COUNCIL_BASE = makeAddr('BASE: riskCouncil'); + address internal constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + IGhoToken internal constant GHO_TOKEN_BASE = + IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + ARB internal arb; BASE internal base; ETH internal eth; @@ -95,10 +106,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); - address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; - address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; - address public constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - IGhoToken public constant GHO_TOKEN_BASE = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + IGhoAaveSteward internal GHO_AAVE_STEWARD_BASE; + IGhoBucketSteward internal GHO_BUCKET_STEWARD_BASE; + IGhoCcipSteward internal GHO_CCIP_STEWARD_BASE; event CCIPSendRequested(IInternal.EVM2EVMMessage message); event Locked(address indexed sender, uint256 amount); @@ -129,11 +139,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { GovernanceV3Base.EXECUTOR_LVL_1, // owner MiscBase.PROXY_ADMIN ); - address ghoCcipStewardBase = _deployNewGhoCcipSteward( - newTokenPoolBase, - address(GHO_TOKEN_BASE), - GovernanceV3Base.EXECUTOR_LVL_1, // riskCouncil, using executor for convenience - false // bridgeLimitEnabled, *not present* in remote (burnMint) pools + (GHO_AAVE_STEWARD_BASE, GHO_BUCKET_STEWARD_BASE, GHO_CCIP_STEWARD_BASE) = _deployStewardsBase( + newTokenPoolBase ); vm.selectFork(arb.c.forkId); @@ -148,9 +155,11 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(base.c.forkId); base.proposal = new AaveV3Base_GHOBaseLaunch_20241223( newTokenPoolBase, - ghoCcipStewardBase, newTokenPoolEth, - newTokenPoolArb + newTokenPoolArb, + address(GHO_AAVE_STEWARD_BASE), + address(GHO_BUCKET_STEWARD_BASE), + address(GHO_CCIP_STEWARD_BASE) ); base.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolBase); base.c.tokenAdminRegistry = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); @@ -189,11 +198,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner MiscEthereum.PROXY_ADMIN ); - address newGhoCcipStewardEth = _deployNewGhoCcipSteward( - newTokenPoolEth, - AaveV3EthereumAssets.GHO_UNDERLYING, - GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience - true // bridgeLimitEnabled + address newGhoCcipStewardEth = address( + new GhoCcipSteward({ + ghoTokenPool: newTokenPoolEth, + ghoToken: AaveV3EthereumAssets.GHO_UNDERLYING, + riskCouncil: makeAddr('ETH: riskAdmin'), + bridgeLimitEnabled: true + }) ); vm.selectFork(arb.c.forkId); @@ -207,11 +218,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner MiscArbitrum.PROXY_ADMIN ); - address newGhoCcipStewardArb = _deployNewGhoCcipSteward( - newTokenPoolArb, - AaveV3ArbitrumAssets.GHO_UNDERLYING, - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience - false // bridgeLimitEnabled + address newGhoCcipStewardArb = address( + new GhoCcipSteward({ + ghoTokenPool: newTokenPoolArb, + ghoToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, + riskCouncil: makeAddr('ARB: riskAdmin'), + bridgeLimitEnabled: false + }) ); // execute CLL pre-requisites for the proposal @@ -248,10 +261,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { return (newTokenPoolEth, newTokenPoolArb); } - function _deployGhoTokenImpl() internal returns (address) { - return address(new UpgradeableGhoToken()); - } - function _predictGhoTokenAddressBase(address logic) internal pure returns (address) { return _predictCreate2Address({ @@ -363,15 +372,45 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { } } - function _deployNewGhoCcipSteward( - address newTokenPool, - address ghoToken, - address riskCouncil, - bool bridgeLimitEnabled - ) internal returns (address) { - return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); + function _deployStewardsBase( + address ghoTokenPool + ) internal returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) { + address aaveSteward = address( + new GhoAaveSteward({ + owner: GovernanceV3Base.EXECUTOR_LVL_1, + addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), + poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), + ghoToken: address(GHO_TOKEN_BASE), + riskCouncil: RISK_COUNCIL_BASE, + borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ + optimalUsageRatioMaxChange: 0, + baseVariableBorrowRateMaxChange: 0, + variableRateSlope1MaxChange: 0, + variableRateSlope2MaxChange: 0 + }) + }) + ); + address bucketSteward = address( + new GhoBucketSteward({ + owner: GovernanceV3Base.EXECUTOR_LVL_1, + ghoToken: address(GHO_TOKEN_BASE), + riskCouncil: RISK_COUNCIL_BASE + }) + ); + address ccipSteward = address( + new GhoCcipSteward({ + ghoToken: address(GHO_TOKEN_BASE), + ghoTokenPool: ghoTokenPool, + riskCouncil: RISK_COUNCIL_BASE, + bridgeLimitEnabled: false + }) + ); + return ( + IGhoAaveSteward(aaveSteward), + IGhoBucketSteward(bucketSteward), + IGhoCcipSteward(ccipSteward) + ); } - function _getTokenMessage( CCIPSendParams memory params ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { diff --git a/src/interfaces/IOwnable.sol b/src/interfaces/IOwnable.sol new file mode 100644 index 000000000..a02af3dd1 --- /dev/null +++ b/src/interfaces/IOwnable.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IOwnable { + /// @notice Returns the owner of the contract. + /// @dev This method is named to match with the OpenZeppelin Ownable contract. + function owner() external view returns (address); +} From 676ee32c80e978266f34e1b7d39010fba7803a0d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 26 Dec 2024 17:52:05 +0530 Subject: [PATCH 066/123] fix: use 500 maxChange borrowRateConfig --- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 16 ++++++++-------- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index d4120eb85..5a105d3f4 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -167,10 +167,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ghoToken: address(GHO), riskCouncil: RISK_COUNCIL, borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ - optimalUsageRatioMaxChange: 0, - baseVariableBorrowRateMaxChange: 0, - variableRateSlope1MaxChange: 0, - variableRateSlope2MaxChange: 0 + optimalUsageRatioMaxChange: 500, + baseVariableBorrowRateMaxChange: 500, + variableRateSlope1MaxChange: 500, + variableRateSlope2MaxChange: 500 }) }) ); @@ -328,10 +328,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq(NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), address(AaveV3Base.UI_POOL_DATA_PROVIDER)); assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); IGhoAaveSteward.BorrowRateConfig memory config = NEW_GHO_AAVE_STEWARD.getBorrowRateConfig(); - assertEq(config.optimalUsageRatioMaxChange, 0); - assertEq(config.baseVariableBorrowRateMaxChange, 0); - assertEq(config.variableRateSlope1MaxChange, 0); - assertEq(config.variableRateSlope2MaxChange, 0); + assertEq(config.optimalUsageRatioMaxChange, 500); + assertEq(config.baseVariableBorrowRateMaxChange, 500); + assertEq(config.variableRateSlope1MaxChange, 500); + assertEq(config.variableRateSlope2MaxChange, 500); assertEq(IOwnable(address(NEW_GHO_BUCKET_STEWARD)).owner(), GovernanceV3Base.EXECUTOR_LVL_1); assertEq(NEW_GHO_BUCKET_STEWARD.GHO_TOKEN(), address(GHO)); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 3bec75b7e..df06080fd 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -383,10 +383,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ghoToken: address(GHO_TOKEN_BASE), riskCouncil: RISK_COUNCIL_BASE, borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ - optimalUsageRatioMaxChange: 0, - baseVariableBorrowRateMaxChange: 0, - variableRateSlope1MaxChange: 0, - variableRateSlope2MaxChange: 0 + optimalUsageRatioMaxChange: 500, + baseVariableBorrowRateMaxChange: 500, + variableRateSlope1MaxChange: 500, + variableRateSlope2MaxChange: 500 }) }) ); From 372e11f3707090ae432238d013e9dc38d291c3a5 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 26 Dec 2024 17:57:58 +0530 Subject: [PATCH 067/123] feat: validate base proposal constants --- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 5a105d3f4..658bcb434 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -115,6 +115,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ); _performCcipPreReq(); + _validateConstants(); } function _performCcipPreReq() internal { @@ -196,6 +197,56 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ); } + function _validateConstants() private view { + assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); + assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); + assertEq(proposal.CCIP_BUCKET_CAPACITY(), 20_000_000e18); + assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); + assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(proposal.GHO_TOKEN_IMPL(), GHO_TOKEN_IMPL); + assertEq(address(proposal.GHO_TOKEN_PROXY()), address(GHO)); + assertEq(proposal.GHO_AAVE_STEWARD(), address(NEW_GHO_AAVE_STEWARD)); + assertEq(proposal.GHO_BUCKET_STEWARD(), address(NEW_GHO_BUCKET_STEWARD)); + assertEq(proposal.GHO_CCIP_STEWARD(), address(NEW_GHO_CCIP_STEWARD)); + assertEq(proposal.REMOTE_TOKEN_POOL_ARB(), NEW_REMOTE_POOL_ARB); + assertEq(proposal.REMOTE_TOKEN_POOL_ETH(), NEW_REMOTE_POOL_ETH); + + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); + assertEq(ROUTER.typeAndVersion(), 'Router 1.2.0'); + + _assertOnRamp(ARB_ON_RAMP, BASE_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); + _assertOnRamp(ETH_ON_RAMP, BASE_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); + _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); + _assertOffRamp(ETH_OFF_RAMP, ETH_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); + } + + function _assertOnRamp( + IEVM2EVMOnRamp onRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(onRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); + assertEq(onRamp.getStaticConfig().chainSelector, srcSelector); + assertEq(onRamp.getStaticConfig().destChainSelector, dstSelector); + assertEq(onRamp.getDynamicConfig().router, address(router)); + assertEq(router.getOnRamp(dstSelector), address(onRamp)); + } + + function _assertOffRamp( + IEVM2EVMOffRamp_1_5 offRamp, + uint64 srcSelector, + uint64 dstSelector, + IRouter router + ) internal view { + assertEq(offRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); + assertEq(offRamp.getStaticConfig().sourceChainSelector, srcSelector); + assertEq(offRamp.getStaticConfig().chainSelector, dstSelector); + assertEq(offRamp.getDynamicConfig().router, address(router)); + assertTrue(router.isOffRamp(srcSelector, address(offRamp))); + } + function _getTokenMessage( CCIPSendParams memory params ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { From 8e97f9fa18d55877935670568910ddeb5ea1be87 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 26 Dec 2024 18:06:47 +0530 Subject: [PATCH 068/123] chore: add partial explorer links for immutables --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 2 ++ .../AaveV3Base_GHOBaseLaunch_20241223.sol | 10 ++++++++-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index f01dd5e49..3f9b1eb85 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -14,8 +14,10 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; + // https://arbiscan.io/address/ IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; + // https://basescan.org/address/ address public immutable REMOTE_TOKEN_POOL_BASE; // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index b94b7c816..57936b979 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -29,21 +29,27 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint128 public constant CCIP_BUCKET_CAPACITY = 20_000_000e18; // 20M GHO + // https://basescan.org/address/0x6f6C373d09C07425BaAE72317863d7F6bb731e37 ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); - + // https://basescan.org/address/ IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; // https://basescan.org/address/0x26d595dddbad81bf976ef6f24686a12a800b141f address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - // predicted address, will be deployed in the AIP + // predicted address, will be deployed in the AIP, https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); + // https://basescan.org/address/ address public immutable GHO_AAVE_STEWARD; + // https://basescan.org/address/ address public immutable GHO_BUCKET_STEWARD; + // https://basescan.org/address/ address public immutable GHO_CCIP_STEWARD; + // https://etherscan.io/address/ address public immutable REMOTE_TOKEN_POOL_ETH; + // https://arbiscan.io/address/ address public immutable REMOTE_TOKEN_POOL_ARB; constructor( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index d6503e80d..262d5cd35 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -14,8 +14,10 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; + // https://etherscan.io/address/ IUpgradeableLockReleaseTokenPool_1_5_1 public immutable TOKEN_POOL; + // https://basescan.org/address/ address public immutable REMOTE_TOKEN_POOL_BASE; // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted From 343e8d4a71f5399c16defaf5460d02af5e4fd142 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 27 Dec 2024 15:51:51 +0530 Subject: [PATCH 069/123] test: tokenPoolConfig --- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 2 +- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 82 +++++++++++++++---- src/interfaces/IGhoToken.sol | 2 + 3 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 57936b979..fe351823a 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -91,7 +91,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( GHO_TOKEN_IMPL, ProxyAdmin(MiscBase.PROXY_ADMIN), - abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) + abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) ) ); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 658bcb434..3b183a7b5 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -316,7 +316,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau defaultTest('AaveV3Base_GHOBaseLaunch_20241223', AaveV3Base.POOL, address(proposal)); } - function test_stewardRolesAndConfig() public { + function test_stewardRoles() public { // gho token is deployed in the AIP, does not existing before assertFalse( @@ -355,21 +355,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); } - function test_newTokenPoolInitialization() public { - vm.expectRevert('Initializable: contract is already initialized'); - NEW_TOKEN_POOL.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); - assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); - - address IMPL = _getImplementation(address(NEW_TOKEN_POOL)); - vm.expectRevert('Initializable: contract is already initialized'); - IUpgradeableBurnMintTokenPool_1_5_1(IMPL).initialize( - makeAddr('owner'), - new address[](0), - makeAddr('router') - ); - assertEq(_readInitialized(IMPL), 255); - } - function test_stewardsConfig() public view { assertEq(IOwnable(address(NEW_GHO_AAVE_STEWARD)).owner(), GovernanceV3Base.EXECUTOR_LVL_1); assertEq( @@ -401,6 +386,71 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq(ccipDebounce.bridgeLimitLastUpdate, 0); assertEq(ccipDebounce.rateLimitLastUpdate, 0); } + + function test_newTokenPoolInitialization() public { + vm.expectRevert('Initializable: contract is already initialized'); + NEW_TOKEN_POOL.initialize(makeAddr('owner'), new address[](0), makeAddr('router')); + assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); + + address IMPL = _getImplementation(address(NEW_TOKEN_POOL)); + vm.expectRevert('Initializable: contract is already initialized'); + IUpgradeableBurnMintTokenPool_1_5_1(IMPL).initialize( + makeAddr('owner'), + new address[](0), + makeAddr('router') + ); + assertEq(_readInitialized(IMPL), 255); + } + + function test_tokenPoolConfig() public { + executePayload(vm, address(proposal)); + + assertEq(NEW_TOKEN_POOL.owner(), GovernanceV3Base.EXECUTOR_LVL_1); + assertEq( + address(uint160(uint256(vm.load(address(NEW_TOKEN_POOL), bytes32(0))) >> 2)), // pending owner + address(0) + ); + console.logBytes32(vm.load(address(NEW_TOKEN_POOL), bytes32(0))); + assertEq(NEW_TOKEN_POOL.getToken(), address(GHO)); + assertEq(NEW_TOKEN_POOL.getTokenDecimals(), GHO.decimals()); + assertEq(NEW_TOKEN_POOL.getRmnProxy(), RMN_PROXY); + assertFalse(NEW_TOKEN_POOL.getAllowListEnabled()); + assertEq(abi.encode(NEW_TOKEN_POOL.getAllowList()), abi.encode(new address[](0))); + assertEq(NEW_TOKEN_POOL.getRouter(), address(ROUTER)); + + assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); + assertEq(NEW_TOKEN_POOL.getSupportedChains()[0], ETH_CHAIN_SELECTOR); + assertEq(NEW_TOKEN_POOL.getSupportedChains()[1], ARB_CHAIN_SELECTOR); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ETH_CHAIN_SELECTOR), + abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING) + ); + assertEq( + NEW_TOKEN_POOL.getRemoteToken(ARB_CHAIN_SELECTOR), + abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING) + ); + assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR).length, 1); + assertEq(NEW_TOKEN_POOL.getRemotePools(ETH_CHAIN_SELECTOR)[0], abi.encode(NEW_REMOTE_POOL_ETH)); + assertEq(NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR).length, 1); + assertEq(NEW_TOKEN_POOL.getRemotePools(ARB_CHAIN_SELECTOR)[0], abi.encode(NEW_REMOTE_POOL_ARB)); + + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + assertEq( + NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), + _getDisabledConfig() + ); + } } contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLaunch_20241223_Base { diff --git a/src/interfaces/IGhoToken.sol b/src/interfaces/IGhoToken.sol index d1b212853..00ea019c4 100644 --- a/src/interfaces/IGhoToken.sol +++ b/src/interfaces/IGhoToken.sol @@ -10,6 +10,8 @@ interface IGhoToken is IERC20 { string label; } + function initialize(address admin) external; + /** * @notice Mints the requested amount of tokens to the account address. * @dev Only facilitators with enough bucket capacity available can mint. From 54e632708f8df44b4e9504ac928ebc77ad9e1f85 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:56:06 +0530 Subject: [PATCH 070/123] feat: accept existing proxy pool ownership as well --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 10 ++++-- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 23 +++++++++++-- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 17 ++++++++-- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 8 ++++- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 32 +++++++++++++------ 5 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 0b23d6ee1..2c519f65f 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -3,12 +3,14 @@ pragma solidity ^0.8.0; import {ITransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {ILegacyProxyAdmin} from 'src/interfaces/ILegacyProxyAdmin.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -24,9 +26,12 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 + IProxyPool public constant EXISTING_PROXY_POOL = + IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); // https://arbiscan.io/address/0xF168B83598516A532a85995b52504a2Fa058C068 IUpgradeableBurnMintTokenPool_1_4 public constant EXISTING_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP + IUpgradeableBurnMintTokenPool_1_4(GhoArbitrum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; address public immutable NEW_GHO_CCIP_STEWARD; @@ -55,6 +60,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // pre-req - chainlink transfers gho token pool ownership on token admin registry function _acceptOwnership() internal { + EXISTING_PROXY_POOL.acceptOwnership(); NEW_TOKEN_POOL.acceptOwnership(); TOKEN_ADMIN_REGISTRY.acceptAdminRole(AaveV3ArbitrumAssets.GHO_UNDERLYING); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index d633097fe..4ddbfc5e9 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -9,6 +9,7 @@ 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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; @@ -60,8 +61,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IProxyPool internal constant EXISTING_PROXY_POOL = + IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP + IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // GhoArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; @@ -86,8 +89,11 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ); // pre-req - chainlink transfers gho token pool ownership on token admin registry - vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + address CLL_OWNER = TOKEN_ADMIN_REGISTRY.owner(); + vm.startPrank(CLL_OWNER); TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + EXISTING_PROXY_POOL.transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); + vm.stopPrank(); _validateConstants(); } @@ -136,11 +142,14 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _validateConstants() private view { assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); + assertEq(address(proposal.EXISTING_PROXY_POOL()), address(EXISTING_PROXY_POOL)); assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); assertEq(address(proposal.EXISTING_REMOTE_POOL_ETH()), ETH_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); assertEq(address(proposal.NEW_REMOTE_POOL_ETH()), NEW_REMOTE_POOL_ETH); + assertEq(address(proposal.EXISTING_PROXY_POOL()), EXISTING_TOKEN_POOL.getProxyPool()); + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); assertEq(EXISTING_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.4.0'); @@ -261,7 +270,11 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is ); assertNotEq(tokenConfig.administrator, GovernanceV3Arbitrum.EXECUTOR_LVL_1); assertEq(tokenConfig.pendingAdministrator, GovernanceV3Arbitrum.EXECUTOR_LVL_1); - assertEq(tokenConfig.tokenPool, EXISTING_TOKEN_POOL.getProxyPool()); + assertEq(tokenConfig.tokenPool, address(EXISTING_PROXY_POOL)); + + assertEq(EXISTING_TOKEN_POOL.owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(EXISTING_PROXY_POOL.owner(), TOKEN_ADMIN_REGISTRY.owner()); + assertEq(NEW_TOKEN_POOL.owner(), address(0)); executePayload(vm, address(proposal)); @@ -269,6 +282,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(tokenConfig.administrator, GovernanceV3Arbitrum.EXECUTOR_LVL_1); assertEq(tokenConfig.pendingAdministrator, address(0)); assertEq(tokenConfig.tokenPool, address(NEW_TOKEN_POOL)); + + assertEq(EXISTING_TOKEN_POOL.owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(EXISTING_PROXY_POOL.owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(NEW_TOKEN_POOL.owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); } function test_tokenPoolLiquidityMigration() public { diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 070df68c6..28f1d16c5 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -11,6 +11,7 @@ import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; @@ -197,12 +198,16 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { // proposal constants assertEq(address(l1.proposal.TOKEN_ADMIN_REGISTRY()), address(l1.c.tokenAdminRegistry)); assertEq(l1.proposal.ARB_CHAIN_SELECTOR(), l2.c.chainSelector); + assertEq(address(l1.proposal.EXISTING_PROXY_POOL()), l1.c.proxyPool); assertEq(address(l1.proposal.EXISTING_TOKEN_POOL()), address(l1.existingTokenPool)); assertEq(address(l1.proposal.EXISTING_REMOTE_POOL_ARB()), l2.c.proxyPool); assertEq(address(l1.proposal.NEW_TOKEN_POOL()), address(l1.newTokenPool)); assertEq(address(l1.proposal.NEW_REMOTE_POOL_ARB()), address(l2.newTokenPool)); if (upgraded) { + assertEq(IProxyPool(l1.c.proxyPool).owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(l1.newTokenPool.owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(l1.c.tokenAdminRegistry.getPool(address(l1.c.token)), address(l1.newTokenPool)); assertEq(l1.c.token.balanceOf(address(l1.existingTokenPool)), 0); @@ -242,12 +247,16 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { // proposal constants assertEq(address(l2.proposal.TOKEN_ADMIN_REGISTRY()), address(l2.c.tokenAdminRegistry)); assertEq(l2.proposal.ETH_CHAIN_SELECTOR(), l1.c.chainSelector); + assertEq(address(l2.proposal.EXISTING_PROXY_POOL()), l2.c.proxyPool); assertEq(address(l2.proposal.EXISTING_TOKEN_POOL()), address(l2.existingTokenPool)); assertEq(address(l2.proposal.EXISTING_REMOTE_POOL_ETH()), l1.c.proxyPool); assertEq(address(l2.proposal.NEW_TOKEN_POOL()), address(l2.newTokenPool)); assertEq(address(l2.proposal.NEW_REMOTE_POOL_ETH()), address(l1.newTokenPool)); if (upgraded) { + assertEq(IProxyPool(l2.c.proxyPool).owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(l2.newTokenPool.owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), address(l2.newTokenPool)); assertEq(bytes(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label).length, 0); assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP TokenPool v1.5.1 '); @@ -267,18 +276,22 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _performPoolTransferCLLPreReq() private { vm.selectFork(l1.c.forkId); - vm.prank(l1.c.tokenAdminRegistry.owner()); + vm.startPrank(l1.c.tokenAdminRegistry.owner()); l1.c.tokenAdminRegistry.transferAdminRole( AaveV3EthereumAssets.GHO_UNDERLYING, GovernanceV3Ethereum.EXECUTOR_LVL_1 ); + IProxyPool(l1.c.proxyPool).transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); + vm.stopPrank(); vm.selectFork(l2.c.forkId); - vm.prank(l2.c.tokenAdminRegistry.owner()); + vm.startPrank(l2.c.tokenAdminRegistry.owner()); l2.c.tokenAdminRegistry.transferAdminRole( AaveV3ArbitrumAssets.GHO_UNDERLYING, GovernanceV3Arbitrum.EXECUTOR_LVL_1 ); + IProxyPool(l2.c.proxyPool).transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); + vm.stopPrank(); } function _deployNewTokenPoolEth() private returns (address) { diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 82219c3a4..d8b21ad46 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -4,8 +4,10 @@ pragma solidity ^0.8.0; import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -21,9 +23,12 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 + IProxyPool public constant EXISTING_PROXY_POOL = + IProxyPool(0x9Ec9F9804733df96D1641666818eFb5198eC50f0); // https://etherscan.io/address/0x5756880B6a1EAba0175227bf02a7E87c1e02B28C IUpgradeableLockReleaseTokenPool_1_4 public constant EXISTING_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP + IUpgradeableLockReleaseTokenPool_1_4(GhoEthereum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; address public immutable NEW_GHO_CCIP_STEWARD; @@ -46,6 +51,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // pre-req - chainlink transfers gho token pool ownership on token admin registry function _acceptOwnership() internal { + EXISTING_PROXY_POOL.acceptOwnership(); NEW_TOKEN_POOL.acceptOwnership(); TOKEN_ADMIN_REGISTRY.acceptAdminRole(AaveV3EthereumAssets.GHO_UNDERLYING); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 84d95018b..bdb1f5fb5 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -9,6 +9,7 @@ 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 {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; @@ -61,8 +62,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IProxyPool internal constant EXISTING_PROXY_POOL = + IProxyPool(0x9Ec9F9804733df96D1641666818eFb5198eC50f0); IUpgradeableLockReleaseTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP + IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // GhoEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; @@ -89,11 +92,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { ); // pre-req - chainlink transfers gho token pool ownership on token admin registry - vm.prank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.transferAdminRole( - AaveV3EthereumAssets.GHO_UNDERLYING, - GovernanceV3Ethereum.EXECUTOR_LVL_1 - ); + address CLL_OWNER = TOKEN_ADMIN_REGISTRY.owner(); + vm.startPrank(CLL_OWNER); + TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1); + EXISTING_PROXY_POOL.transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); + vm.stopPrank(); _validateConstants(); } @@ -145,11 +148,14 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _validateConstants() private view { assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); + assertEq(address(proposal.EXISTING_PROXY_POOL()), address(EXISTING_PROXY_POOL)); assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); assertEq(address(proposal.EXISTING_REMOTE_POOL_ARB()), ARB_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); assertEq(address(proposal.NEW_REMOTE_POOL_ARB()), NEW_REMOTE_POOL_ARB); + assertEq(address(proposal.EXISTING_PROXY_POOL()), EXISTING_TOKEN_POOL.getProxyPool()); + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'LockReleaseTokenPool 1.5.1'); assertEq(EXISTING_TOKEN_POOL.typeAndVersion(), 'LockReleaseTokenPool 1.4.0'); @@ -284,7 +290,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is ); assertNotEq(tokenConfig.administrator, GovernanceV3Ethereum.EXECUTOR_LVL_1); assertEq(tokenConfig.pendingAdministrator, GovernanceV3Ethereum.EXECUTOR_LVL_1); - assertEq(tokenConfig.tokenPool, EXISTING_TOKEN_POOL.getProxyPool()); + assertEq(tokenConfig.tokenPool, address(EXISTING_PROXY_POOL)); + + assertEq(EXISTING_TOKEN_POOL.owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(EXISTING_PROXY_POOL.owner(), TOKEN_ADMIN_REGISTRY.owner()); + assertEq(NEW_TOKEN_POOL.owner(), address(0)); executePayload(vm, address(proposal)); @@ -292,6 +302,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(tokenConfig.administrator, GovernanceV3Ethereum.EXECUTOR_LVL_1); assertEq(tokenConfig.pendingAdministrator, address(0)); assertEq(tokenConfig.tokenPool, address(NEW_TOKEN_POOL)); + + assertEq(EXISTING_TOKEN_POOL.owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(EXISTING_PROXY_POOL.owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(NEW_TOKEN_POOL.owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); } function test_tokenPoolLiquidityMigration() public { @@ -508,8 +522,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount - amount); } - // off-ramp messages sent from existing eth token pool (v1.4) ie ProxyPool - function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolEth( + // off-ramp messages sent from existing arb token pool (v1.4) ie ProxyPool + function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolArb( uint256 amount ) public { uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); From ed83e08340f27ed4a0a7207210836b8c4aed90e8 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 02:52:36 +0530 Subject: [PATCH 071/123] feat: add rate limit --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 20 ++- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 78 ++++++----- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 125 ++++++++++++++---- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 25 ++-- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 100 ++++++++------ src/interfaces/ccip/IEVM2EVMOffRamp.sol | 14 ++ src/interfaces/ccip/IEVM2EVMOnRamp.sol | 15 +++ src/interfaces/ccip/IInternal.sol | 27 ++++ src/interfaces/ccip/IPriceRegistry.sol | 44 ++++++ 9 files changed, 329 insertions(+), 119 deletions(-) create mode 100644 src/interfaces/ccip/IPriceRegistry.sol diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 2c519f65f..e0ea59206 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -44,8 +44,14 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb + // https://arbiscan.io/address/0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33 IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); + // Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; + constructor(address newTokenPoolArb, address newTokenPoolEth, address newGhoCcipSteward) { NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); NEW_REMOTE_POOL_ETH = newTokenPoolEth; @@ -71,7 +77,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address(EXISTING_TOKEN_POOL) ); - GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP TokenPool v1.5.1 ', uint128(bucketCapacity)); + GHO.addFacilitator(address(NEW_TOKEN_POOL), 'CCIP TokenPool v1.5.1', uint128(bucketCapacity)); NEW_TOKEN_POOL.directMint(address(EXISTING_TOKEN_POOL), bucketLevel); // increase facilitator level _upgradeExistingTokenPool(); // introduce `directBurn` method @@ -81,10 +87,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { } function _setupAndRegisterNewPool() internal { - IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ - isEnabled: false, - capacity: 0, - rate: 0 + IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE }); IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] @@ -98,8 +104,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { remoteChainSelector: ETH_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING), - outboundRateLimiterConfig: emptyRateLimiterConfig, - inboundRateLimiterConfig: emptyRateLimiterConfig + outboundRateLimiterConfig: rateLimiterConfig, + inboundRateLimiterConfig: rateLimiterConfig }); // setup new pool diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 4ddbfc5e9..6664cadf3 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -46,6 +46,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; IGhoToken internal constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = @@ -147,6 +149,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(proposal.EXISTING_REMOTE_POOL_ETH()), ETH_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); assertEq(address(proposal.NEW_REMOTE_POOL_ETH()), NEW_REMOTE_POOL_ETH); + assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); assertEq(address(proposal.EXISTING_PROXY_POOL()), EXISTING_TOKEN_POOL.getProxyPool()); @@ -242,6 +246,27 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + 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() + }); + } + + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return amount / CCIP_RATE_LIMIT_REFILL_RATE + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config @@ -306,7 +331,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is newFacilitator = GHO.getFacilitator(address(NEW_TOKEN_POOL)); - assertEq(newFacilitator.label, 'CCIP TokenPool v1.5.1 '); + assertEq(newFacilitator.label, 'CCIP TokenPool v1.5.1'); assertEq(newFacilitator.bucketCapacity, existingFacilitator.bucketCapacity); assertEq(newFacilitator.bucketLevel, existingFacilitator.bucketLevel); @@ -344,11 +369,11 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); } @@ -370,8 +395,12 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is } function test_sendMessageSucceedsAndRoutesViaNewPool(uint256 amount) public { - uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + uint256 bridgeableAmount = _min( + GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill deal(address(GHO), alice, amount); vm.prank(alice); @@ -403,6 +432,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is // existing pool can no longer on ramp function test_lockOrBurnRevertsOnExistingPool() public { uint256 amount = 100_000e18; + skip(_getOutboundRefillTime(amount)); // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); @@ -421,8 +451,12 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is // on-ramp via new pool function test_lockOrBurnSucceedsOnNewPool(uint256 amount) public { - uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + uint256 bridgeableAmount = _min( + GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(NEW_TOKEN_POOL), amount); @@ -450,6 +484,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is // existing pool can no longer off ramp function test_releaseOrMintRevertsOnExistingPool() public { uint256 amount = 100_000e18; + skip(_getInboundRefillTime(amount)); // wait for the rate limiter to refill vm.prank(EXISTING_TOKEN_POOL.getProxyPool()); vm.expectRevert('FACILITATOR_BUCKET_CAPACITY_EXCEEDED'); @@ -467,8 +502,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( address(NEW_TOKEN_POOL) ); - uint256 mintAbleAmount = bucketCapacity - bucketLevel; + uint256 mintAbleAmount = _min(bucketCapacity - bucketLevel, CCIP_RATE_LIMIT_CAPACITY); amount = bound(amount, 1, mintAbleAmount); + skip(_getInboundRefillTime(amount)); // wait for the rate limiter to refill uint256 aliceBalance = GHO.balanceOf(alice); @@ -500,8 +536,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( address(NEW_TOKEN_POOL) ); - uint256 mintAbleAmount = bucketCapacity - bucketLevel; + uint256 mintAbleAmount = _min(bucketCapacity - bucketLevel, CCIP_RATE_LIMIT_CAPACITY); amount = bound(amount, 1, mintAbleAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); @@ -526,19 +563,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(GHO.balanceOf(alice), aliceBalance + amount); } - function test_stewardCanSetAndDisableRateLimit() public { + function test_stewardCanChangeAndDisableRateLimit() public { assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); // sanity - // currently disabled - assertEq( - NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() - ); - assertEq( - NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() - ); - IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ isEnabled: true, capacity: 500_000e18, @@ -550,20 +577,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is rate: 50e18 }); - // since only the DAO can re-enable disabled rate limit, - // first we set the rate limit through an AIP directly on the token pool - vm.prank(GovernanceV3Arbitrum.EXECUTOR_LVL_1); - NEW_TOKEN_POOL.setChainRateLimiterConfig(ETH_CHAIN_SELECTOR, outboundConfig, inboundConfig); - - skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); - - // change capacity - outboundConfig.capacity += 1; - outboundConfig.rate += 1; - inboundConfig.capacity += 1; - inboundConfig.rate += 1; - - // now we assert the steward can change the rate limit + // we assert the steward can change the rate limit vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); NEW_GHO_CCIP_STEWARD.updateRateLimit( ETH_CHAIN_SELECTOR, diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 28f1d16c5..2da12095e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -11,6 +11,7 @@ import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IPriceRegistry} from 'src/interfaces/ccip/IPriceRegistry.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; @@ -58,6 +59,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5 EVM2EVMOffRamp; ITokenAdminRegistry tokenAdminRegistry; IGhoCcipSteward newGhoCcipSteward; + IPriceRegistry priceRegistry; address proxyPool; uint64 chainSelector; uint256 forkId; @@ -84,6 +86,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; + event CCIPSendRequested(IInternal.EVM2EVMMessage message); event Locked(address indexed sender, uint256 amount); event Burned(address indexed sender, uint256 amount); @@ -127,6 +132,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { l1.c.EVM2EVMOnRamp = IEVM2EVMOnRamp(l1.c.router.getOnRamp(l2.c.chainSelector)); l1.c.EVM2EVMOffRamp = IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); // new offramp l1.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); + l1.c.priceRegistry = IPriceRegistry(l1.c.EVM2EVMOnRamp.getDynamicConfig().priceRegistry); l1.c.proxyPool = l1.existingTokenPool.getProxyPool(); vm.selectFork(l2.c.forkId); @@ -145,6 +151,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { l2.c.EVM2EVMOnRamp = IEVM2EVMOnRamp(l2.c.router.getOnRamp(l1.c.chainSelector)); l2.c.EVM2EVMOffRamp = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); // new offramp l2.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); + l2.c.priceRegistry = IPriceRegistry(l2.c.EVM2EVMOnRamp.getDynamicConfig().priceRegistry); l2.c.proxyPool = l2.existingTokenPool.getProxyPool(); _validateConfig({upgraded: false}); @@ -187,11 +194,14 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(l1.c.router.typeAndVersion(), 'Router 1.2.0'); assertEq(l1.c.EVM2EVMOnRamp.typeAndVersion(), 'EVM2EVMOnRamp 1.5.0'); assertEq(l1.c.EVM2EVMOffRamp.typeAndVersion(), 'EVM2EVMOffRamp 1.5.0'); - assertEq(l1.existingTokenPool.typeAndVersion(), 'LockReleaseTokenPool 1.4.0'); assertEq(l1.newTokenPool.typeAndVersion(), 'LockReleaseTokenPool 1.5.1'); - assertEq(l1.c.tokenAdminRegistry.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(l1.c.priceRegistry.typeAndVersion(), 'PriceRegistry 1.2.0'); + assertEq( + l1.c.EVM2EVMOnRamp.getDynamicConfig().priceRegistry, + l1.c.EVM2EVMOffRamp.getDynamicConfig().priceRegistry + ); assertTrue(l1.c.router.isOffRamp(l2.c.chainSelector, address(l1.c.EVM2EVMOffRamp))); assertEq(l1.c.router.getOnRamp(l2.c.chainSelector), address(l1.c.EVM2EVMOnRamp)); @@ -203,6 +213,8 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(l1.proposal.EXISTING_REMOTE_POOL_ARB()), l2.c.proxyPool); assertEq(address(l1.proposal.NEW_TOKEN_POOL()), address(l1.newTokenPool)); assertEq(address(l1.proposal.NEW_REMOTE_POOL_ARB()), address(l2.newTokenPool)); + assertEq(l1.proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(l1.proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); if (upgraded) { assertEq(IProxyPool(l1.c.proxyPool).owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); @@ -240,8 +252,12 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(l2.existingTokenPool.typeAndVersion(), 'BurnMintTokenPool 1.4.0'); assertEq(l2.newTokenPool.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); assertEq(l2.c.tokenAdminRegistry.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); + assertEq(l2.c.priceRegistry.typeAndVersion(), 'PriceRegistry 1.2.0'); + assertEq( + l2.c.EVM2EVMOnRamp.getDynamicConfig().priceRegistry, + l2.c.EVM2EVMOffRamp.getDynamicConfig().priceRegistry + ); assertTrue(l2.c.router.isOffRamp(l1.c.chainSelector, address(l2.c.EVM2EVMOffRamp))); - assertEq(l2.c.router.getOnRamp(l1.c.chainSelector), address(l2.c.EVM2EVMOnRamp)); // proposal constants @@ -252,6 +268,8 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(l2.proposal.EXISTING_REMOTE_POOL_ETH()), l1.c.proxyPool); assertEq(address(l2.proposal.NEW_TOKEN_POOL()), address(l2.newTokenPool)); assertEq(address(l2.proposal.NEW_REMOTE_POOL_ETH()), address(l1.newTokenPool)); + assertEq(l2.proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(l2.proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); if (upgraded) { assertEq(IProxyPool(l2.c.proxyPool).owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); @@ -259,7 +277,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), address(l2.newTokenPool)); assertEq(bytes(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label).length, 0); - assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP TokenPool v1.5.1 '); + assertEq(l2.c.token.getFacilitator(address(l2.newTokenPool)).label, 'CCIP TokenPool v1.5.1'); } else { assertEq(l2.c.tokenAdminRegistry.getPool(address(l2.c.token)), l2.c.proxyPool); assertEq(l2.c.token.getFacilitator(address(l2.existingTokenPool)).label, 'CCIP TokenPool'); @@ -364,10 +382,62 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); } + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + // @dev refresh token prices to the last stored such that price is not stale + // @dev assumed c.forkId is already active + function _refreshGasAndTokenPrices(Common memory c) internal { + uint64 destChainSelector = c.forkId == l1.c.forkId ? l2.c.chainSelector : l1.c.chainSelector; + address bridgeToken = address(c.token); + address feeToken = c.router.getWrappedNative(); // needed as we do tests with wrapped native as fee token + address linkToken = c.EVM2EVMOnRamp.getStaticConfig().linkToken; // needed as feeTokenAmount is converted to linkTokenAmount + IInternal.TokenPriceUpdate[] memory tokenPriceUpdates = new IInternal.TokenPriceUpdate[](3); + IInternal.GasPriceUpdate[] memory gasPriceUpdates = new IInternal.GasPriceUpdate[](1); + + tokenPriceUpdates[0] = IInternal.TokenPriceUpdate({ + sourceToken: bridgeToken, + usdPerToken: c.priceRegistry.getTokenPrice(bridgeToken).value + }); + tokenPriceUpdates[1] = IInternal.TokenPriceUpdate({ + sourceToken: feeToken, + usdPerToken: c.priceRegistry.getTokenPrice(feeToken).value + }); + tokenPriceUpdates[2] = IInternal.TokenPriceUpdate({ + sourceToken: linkToken, + usdPerToken: c.priceRegistry.getTokenPrice(linkToken).value + }); + + gasPriceUpdates[0] = IInternal.GasPriceUpdate({ + destChainSelector: destChainSelector, + usdPerUnitGas: c.priceRegistry.getDestinationChainGasPrice(destChainSelector).value + }); + + vm.prank(c.priceRegistry.owner()); + c.priceRegistry.updatePrices( + IInternal.PriceUpdates({ + tokenPriceUpdates: tokenPriceUpdates, + gasPriceUpdates: gasPriceUpdates + }) + ); + } + // post upgrade function _runEthToArb(address user, uint256 amount) internal { vm.selectFork(l1.c.forkId); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill + _refreshGasAndTokenPrices(l1.c); + vm.prank(user); l1.c.token.approve(address(l1.c.router), amount); @@ -405,6 +475,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { // ARB executeMessage vm.selectFork(l2.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(l2.c); + userBalance = l2.c.token.balanceOf(user); uint256 bucketLevel = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; @@ -425,6 +498,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _runArbToEth(address user, uint256 amount) internal { vm.selectFork(l2.c.forkId); + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(l2.c); + vm.prank(user); l2.c.token.approve(address(l2.c.router), amount); @@ -460,6 +536,9 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { // ETH executeMessage vm.selectFork(l1.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(l1.c); + uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.newTokenPool)); uint256 bridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); userBalance = l1.c.token.balanceOf(user); @@ -492,11 +571,11 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_E2E_FromEth(uint256 amount) public { vm.selectFork(l1.c.forkId); - amount = bound( - amount, - 1, - l1.newTokenPool.getBridgeLimit() - l1.newTokenPool.getCurrentBridgedAmount() + uint256 bridgeableAmount = _min( + l1.newTokenPool.getBridgeLimit() - l1.newTokenPool.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY ); + amount = bound(amount, 1, bridgeableAmount); deal(address(l1.c.token), alice, amount); _runEthToArb(alice, amount); @@ -505,33 +584,17 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_E2E_FromArb(uint256 amount) public { vm.selectFork(l2.c.forkId); - uint256 currentBridgedAmount = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; + uint256 bridgeableAmount = _min( + l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel, + CCIP_RATE_LIMIT_CAPACITY + ); - amount = bound(amount, 1, currentBridgedAmount); + amount = bound(amount, 1, bridgeableAmount); deal(address(l2.c.token), alice, amount); _runArbToEth(alice, amount); _runEthToArb(alice, amount); } - - function test_E2E_Multiple() public { - vm.selectFork(l1.c.forkId); - uint256 currentBridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); - uint256 amount = currentBridgedAmount / 3; - - deal(address(l1.c.token), alice, amount); - deal(address(l1.c.token), bob, amount); - - vm.selectFork(l2.c.forkId); - deal(address(l2.c.token), carol, amount); - - _runEthToArb(alice, amount); - _runEthToArb(bob, amount); - _runArbToEth(alice, amount); - _runArbToEth(carol, amount); - _runEthToArb(carol, amount); - _runArbToEth(bob, amount); - } } // sendMsg => upgrade => executeMsg @@ -543,6 +606,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is uint256 amount = 100_000e18; deal(address(l1.c.token), alice, amount); + skip(_getOutboundRefillTime(amount)); vm.prank(alice); l1.c.token.approve(address(l1.c.router), amount); @@ -586,6 +650,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is // ARB executeMessage vm.selectFork(l2.c.forkId); + skip(_getInboundRefillTime(amount)); aliceBalance = l2.c.token.balanceOf(alice); uint256 bucketLevel = l2.c.token.getFacilitator(address(l2.newTokenPool)).bucketLevel; @@ -610,6 +675,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is uint256 amount = 100_000e18; deal(address(l2.c.token), alice, amount); + skip(_getOutboundRefillTime(amount)); vm.prank(alice); l2.c.token.approve(address(l2.c.router), amount); @@ -654,6 +720,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_InFlightUpgrade is // ETH executeMessage vm.selectFork(l1.c.forkId); + skip(_getInboundRefillTime(amount)); uint256 tokenPoolBalance = l1.c.token.balanceOf(address(l1.newTokenPool)); uint256 bridgedAmount = l1.newTokenPool.getCurrentBridgedAmount(); aliceBalance = l1.c.token.balanceOf(alice); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index d8b21ad46..4c3299f1b 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -6,7 +6,6 @@ import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGen import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -37,6 +36,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb address public immutable NEW_REMOTE_POOL_ARB; + // Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; + constructor(address newTokenPoolEth, address newTokenPoolArb, address newGhoCcipSteward) { NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); NEW_REMOTE_POOL_ARB = newTokenPoolArb; @@ -67,24 +71,25 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { } function _setupAndRegisterNewPool() internal { - bytes[] memory remotePoolAddresses = new bytes[](2); - remotePoolAddresses[0] = abi.encode(EXISTING_REMOTE_POOL_ARB); - remotePoolAddresses[1] = abi.encode(NEW_REMOTE_POOL_ARB); - IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ - isEnabled: false, - capacity: 0, - rate: 0 + IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE }); IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[] memory chains = new IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[](1); + bytes[] memory remotePoolAddresses = new bytes[](2); + remotePoolAddresses[0] = abi.encode(EXISTING_REMOTE_POOL_ARB); + remotePoolAddresses[1] = abi.encode(NEW_REMOTE_POOL_ARB); + chains[0] = IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: ARB_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING), - outboundRateLimiterConfig: emptyRateLimiterConfig, - inboundRateLimiterConfig: emptyRateLimiterConfig + outboundRateLimiterConfig: rateLimiterConfig, + inboundRateLimiterConfig: rateLimiterConfig }); // setup new pool diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index bdb1f5fb5..dcc6b3007 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -47,6 +47,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = @@ -153,6 +155,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(proposal.EXISTING_REMOTE_POOL_ARB()), ARB_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); assertEq(address(proposal.NEW_REMOTE_POOL_ARB()), NEW_REMOTE_POOL_ARB); + assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); assertEq(address(proposal.EXISTING_PROXY_POOL()), EXISTING_TOKEN_POOL.getProxyPool()); @@ -250,6 +254,35 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); } + 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() + }); + } + + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return amount / CCIP_RATE_LIMIT_REFILL_RATE + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return amount / CCIP_RATE_LIMIT_REFILL_RATE + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + function _isDifferenceLowerThanMax( + uint256 from, + uint256 to, + uint256 max + ) internal pure returns (bool) { + return from < to ? to - from <= max : from - to <= max; + } + function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config @@ -361,11 +394,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); } @@ -387,9 +420,12 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is } function test_sendMessageSucceedsAndRoutesViaNewPool(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - - NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getBridgeLimit() - NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill deal(address(GHO), alice, amount); vm.prank(alice); @@ -423,6 +459,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is // existing pool can no longer on ramp function test_lockOrBurnRevertsOnExistingPool() public { uint256 amount = 100_000e18; + skip(_getOutboundRefillTime(amount)); // router pulls tokens from the user & sends to the token pool during onRamps deal(address(GHO), address(EXISTING_TOKEN_POOL), amount); @@ -441,9 +478,12 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is // on-ramp via new pool function test_lockOrBurnSucceedsOnNewPool(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - - NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getBridgeLimit() - NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill // router pulls tokens from the user & sends to the token pool during onRamps // we don't override NEW_TOKEN_POOL balance here & instead transfer because we want @@ -475,6 +515,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is // existing pool can no longer off ramp function test_releaseOrMintRevertsOnExistingPool() public { uint256 amount = 100_000e18; + skip(_getInboundRefillTime(amount)); assertEq(GHO.balanceOf(address(EXISTING_TOKEN_POOL)), 0); @@ -493,8 +534,12 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is // off-ramp messages sent from new eth token pool (v1.5.1) function test_releaseOrMintSucceedsOnNewPoolOffRampedViaNewTokenPoolEth(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); @@ -526,8 +571,12 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is function test_releaseOrMintSucceedsOnNewPoolOffRampedViaExistingTokenPoolArb( uint256 amount ) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); uint256 tokenPoolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); @@ -555,19 +604,9 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount - amount); } - function test_stewardCanSetAndDisableRateLimit() public { + function test_stewardCanChangeAndDisableRateLimit() public { assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); // sanity - // currently disabled - assertEq( - NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() - ); - assertEq( - NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() - ); - IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ isEnabled: true, capacity: 500_000e18, @@ -579,20 +618,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is rate: 50e18 }); - // since only the DAO can re-enable disabled rate limit, - // first we set the rate limit through an AIP directly on the token pool - vm.prank(GovernanceV3Ethereum.EXECUTOR_LVL_1); - NEW_TOKEN_POOL.setChainRateLimiterConfig(ARB_CHAIN_SELECTOR, outboundConfig, inboundConfig); - - skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); - - // change capacity - outboundConfig.capacity += 1; - outboundConfig.rate += 1; - inboundConfig.capacity += 1; - inboundConfig.rate += 1; - - // now we assert the new steward can change the rate limit + // we assert the new steward can change the rate limit vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); NEW_GHO_CCIP_STEWARD.updateRateLimit( ARB_CHAIN_SELECTOR, @@ -634,12 +660,4 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getBridgeLimit(), newBridgeLimit); } - - function _isDifferenceLowerThanMax( - uint256 from, - uint256 to, - uint256 max - ) internal pure returns (bool) { - return from < to ? to - from <= max : from - to <= max; - } } diff --git a/src/interfaces/ccip/IEVM2EVMOffRamp.sol b/src/interfaces/ccip/IEVM2EVMOffRamp.sol index d9d132f5f..3c79cb4ef 100644 --- a/src/interfaces/ccip/IEVM2EVMOffRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOffRamp.sol @@ -32,4 +32,18 @@ interface IEVM2EVMOffRamp_1_5 is ITypeAndVersion { bytes[] calldata offchainTokenData, uint32[] memory tokenGasOverrides ) external; + + /// @notice Dynamic offRamp config + /// @dev since OffRampConfig is part of OffRampConfigChanged event, if changing it, we should update the ABI on Atlas + struct DynamicConfig { + uint32 permissionLessExecutionThresholdSeconds; // ─╮ Waiting time before manual execution is enabled + uint32 maxDataBytes; // │ Maximum payload data size in bytes + uint16 maxNumberOfTokensPerMsg; // │ Maximum number of ERC20 token transfers that can be included per message + address router; // ─────────────────────────────────╯ Router address + address priceRegistry; // Price registry address + } + + /// @notice Returns the current dynamic config. + /// @return The current config. + function getDynamicConfig() external view returns (DynamicConfig memory); } diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol index 13affbc6e..306f1ebf0 100644 --- a/src/interfaces/ccip/IEVM2EVMOnRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -35,6 +35,17 @@ interface IEVM2EVMOnRamp is ITypeAndVersion { bool enforceOutOfOrder; // ──────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. } + struct StaticConfig { + address linkToken; // ────────╮ Link token address + uint64 chainSelector; // ─────╯ Source chainSelector + uint64 destChainSelector; // ─╮ Destination chainSelector + uint64 defaultTxGasLimit; // │ Default gas limit for a tx + uint96 maxNopFeesJuels; // ───╯ Max nop fee balance onramp can have + address prevOnRamp; // Address of previous-version OnRamp + address rmnProxy; // Address of RMN proxy + address tokenAdminRegistry; // Address of the token admin registry + } + /// @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); @@ -69,4 +80,8 @@ interface IEVM2EVMOnRamp is ITypeAndVersion { /// @notice Returns the dynamic onRamp config. /// @return dynamicConfig the configuration. function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig); + + /// @notice Returns the static onRamp config. + /// @return the configuration. + function getStaticConfig() external view returns (StaticConfig memory); } diff --git a/src/interfaces/ccip/IInternal.sol b/src/interfaces/ccip/IInternal.sol index 062ee93da..050e557cd 100644 --- a/src/interfaces/ccip/IInternal.sol +++ b/src/interfaces/ccip/IInternal.sol @@ -5,6 +5,33 @@ pragma solidity ^0.8.0; import {IClient} from 'src/interfaces/ccip/IClient.sol'; interface IInternal { + /// @notice A collection of token price and gas price updates. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct PriceUpdates { + TokenPriceUpdate[] tokenPriceUpdates; + GasPriceUpdate[] gasPriceUpdates; + } + + /// @notice Token price in USD. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct TokenPriceUpdate { + address sourceToken; // Source token + uint224 usdPerToken; // 1e18 USD per 1e18 of the smallest token denomination. + } + + /// @notice Gas price for a given chain in USD, its value may contain tightly packed fields. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct GasPriceUpdate { + uint64 destChainSelector; // Destination chain selector + uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas + } + + /// @notice A timestamped uint224 value that can contain several tightly packed fields. + struct TimestampedPackedUint224 { + uint224 value; // ───────╮ Value in uint224, packed. + uint32 timestamp; // ────╯ Timestamp of the most recent price update. + } + struct PoolUpdate { address token; // The IERC20 token address address pool; // The token pool address diff --git a/src/interfaces/ccip/IPriceRegistry.sol b/src/interfaces/ccip/IPriceRegistry.sol new file mode 100644 index 000000000..664863b2d --- /dev/null +++ b/src/interfaces/ccip/IPriceRegistry.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ITypeAndVersion} from './ITypeAndVersion.sol'; +import {IInternal} from './IInternal.sol'; + +interface IPriceRegistry is ITypeAndVersion { + /// @notice Gets the fee token price and the gas price, both denominated in dollars. + /// @param token The source token to get the price for. + /// @param destChainSelector The destination chain to get the gas price for. + /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. + /// @return gasPrice The price of gas in 1e18 dollars per base unit. + function getTokenAndGasPrices( + address token, + uint64 destChainSelector + ) external view returns (uint224 tokenPrice, uint224 gasPrice); + + /// @notice Update the price for given tokens and gas prices for given chains. + /// @param priceUpdates The price updates to apply. + function updatePrices(IInternal.PriceUpdates memory priceUpdates) external; + + /// @notice Get the `tokenPrice` for a given token. + /// @param token The token to get the price for. + /// @return tokenPrice The tokenPrice for the given token. + function getTokenPrice( + address token + ) external view returns (IInternal.TimestampedPackedUint224 memory); + + /// @notice Get an encoded `gasPrice` for a given destination chain ID. + /// The 224-bit result encodes necessary gas price components. + /// On L1 chains like Ethereum or Avax, the only component is the gas price. + /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. + /// On future chains, there could be more or differing price components. + /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. + /// @param destChainSelector The destination chain to get the price for. + /// @return gasPrice The encoded gasPrice for the given destination chain ID. + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view returns (IInternal.TimestampedPackedUint224 memory); + + /// @notice Gets the owner of the contract. + /// @return The owner of the contract. + function owner() external view returns (address); +} From cd0c17f15910e1c80779abb2ff355c0f9195badc Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 12:02:05 +0530 Subject: [PATCH 072/123] test: fix risk council --- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 23 +++++++++++++++---- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 20 +++++++++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 3b183a7b5..a967157a2 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -67,8 +67,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IRouter internal constant ROUTER = IRouter(0x881e3A65B4d4a04dD529061dd0071cf975F58bCD); address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; - address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - IGhoToken public constant GHO = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + address internal constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; + IGhoToken internal constant GHO = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; IGhoAaveSteward internal NEW_GHO_AAVE_STEWARD; IGhoBucketSteward internal NEW_GHO_BUCKET_STEWARD; @@ -79,7 +80,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); - address internal RISK_COUNCIL = makeAddr('riskCouncil'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -219,6 +219,22 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { _assertOnRamp(ETH_ON_RAMP, BASE_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); _assertOffRamp(ETH_OFF_RAMP, ETH_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); + + address computedGhoTokenAddress = vm.computeCreate2Address({ + salt: keccak256('based-GHO'), + initCodeHash: keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + address(GHO_TOKEN_IMPL), + MiscBase.PROXY_ADMIN, + abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) + ) + ) + ), + deployer: GovernanceV3Base.EXECUTOR_LVL_1 + }); + assertEq(address(GHO), computedGhoTokenAddress); } function _assertOnRamp( @@ -410,7 +426,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau address(uint160(uint256(vm.load(address(NEW_TOKEN_POOL), bytes32(0))) >> 2)), // pending owner address(0) ); - console.logBytes32(vm.load(address(NEW_TOKEN_POOL), bytes32(0))); assertEq(NEW_TOKEN_POOL.getToken(), address(GHO)); assertEq(NEW_TOKEN_POOL.getTokenDecimals(), GHO.decimals()); assertEq(NEW_TOKEN_POOL.getRmnProxy(), RMN_PROXY); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index df06080fd..8904ebb80 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -93,7 +93,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; - address internal RISK_COUNCIL_BASE = makeAddr('BASE: riskCouncil'); + address internal constant RISK_COUNCIL_BASE = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; address internal constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; IGhoToken internal constant GHO_TOKEN_BASE = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP @@ -557,6 +557,24 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { abi.encode(address(base.tokenPool)) ); _assertDisabledRateLimit(eth.c, address(eth.tokenPool)); + } else { + vm.selectFork(base.c.forkId); + // correct gho Token Address + address computedGhoTokenAddress = vm.computeCreate2Address({ + salt: keccak256('based-GHO'), + initCodeHash: keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + address(GHO_TOKEN_IMPL_BASE), + MiscBase.PROXY_ADMIN, + abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) + ) + ) + ), + deployer: address(GovernanceV3Base.EXECUTOR_LVL_1) + }); + assertEq(address(base.proposal.GHO_TOKEN_PROXY()), computedGhoTokenAddress); } } From 3167880d729f8b0df7b8537a11e525380c5a09eb Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 13:15:32 +0530 Subject: [PATCH 073/123] fix: merge --- src/interfaces/ccip/IEVM2EVMOffRamp.sol | 14 -------------- src/interfaces/ccip/IEVM2EVMOnRamp.sol | 11 ----------- 2 files changed, 25 deletions(-) diff --git a/src/interfaces/ccip/IEVM2EVMOffRamp.sol b/src/interfaces/ccip/IEVM2EVMOffRamp.sol index bbd030860..34f565594 100644 --- a/src/interfaces/ccip/IEVM2EVMOffRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOffRamp.sol @@ -64,18 +64,4 @@ interface IEVM2EVMOffRamp_1_5 is ITypeAndVersion { bytes[] calldata offchainTokenData, uint32[] memory tokenGasOverrides ) external; - - /// @notice Dynamic offRamp config - /// @dev since OffRampConfig is part of OffRampConfigChanged event, if changing it, we should update the ABI on Atlas - struct DynamicConfig { - uint32 permissionLessExecutionThresholdSeconds; // ─╮ Waiting time before manual execution is enabled - uint32 maxDataBytes; // │ Maximum payload data size in bytes - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of ERC20 token transfers that can be included per message - address router; // ─────────────────────────────────╯ Router address - address priceRegistry; // Price registry address - } - - /// @notice Returns the current dynamic config. - /// @return The current config. - function getDynamicConfig() external view returns (DynamicConfig memory); } diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol index 5b93291eb..a129d6a18 100644 --- a/src/interfaces/ccip/IEVM2EVMOnRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -46,17 +46,6 @@ interface IEVM2EVMOnRamp is ITypeAndVersion { bool enforceOutOfOrder; // ──────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. } - struct StaticConfig { - address linkToken; // ────────╮ Link token address - uint64 chainSelector; // ─────╯ Source chainSelector - uint64 destChainSelector; // ─╮ Destination chainSelector - uint64 defaultTxGasLimit; // │ Default gas limit for a tx - uint96 maxNopFeesJuels; // ───╯ Max nop fee balance onramp can have - address prevOnRamp; // Address of previous-version OnRamp - address rmnProxy; // Address of RMN proxy - address tokenAdminRegistry; // Address of the token admin registry - } - /// @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); From 1f7aea3114492ae1ecb62b379f532db3d2066887 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 13:16:04 +0530 Subject: [PATCH 074/123] feat: add rate limit --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 17 +- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 79 +++++-- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 21 +- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 60 ++++- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 205 ++++++++++++------ .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 17 +- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 104 ++++++--- 7 files changed, 358 insertions(+), 145 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 3f9b1eb85..fdff5f797 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -22,16 +22,21 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + // Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; + constructor(address tokenPoolArb, address tokenPoolBase) { TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPoolArb); REMOTE_TOKEN_POOL_BASE = tokenPoolBase; } function execute() external { - IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ - isEnabled: false, - capacity: 0, - rate: 0 + IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE }); IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] @@ -44,8 +49,8 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { remoteChainSelector: BASE_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(REMOTE_GHO_TOKEN_BASE), - outboundRateLimiterConfig: emptyRateLimiterConfig, - inboundRateLimiterConfig: emptyRateLimiterConfig + outboundRateLimiterConfig: rateLimiterConfig, + inboundRateLimiterConfig: rateLimiterConfig }); TOKEN_POOL.applyChainUpdates({ diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 228c1c99d..7d5ecdc19 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -47,6 +47,8 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; uint64 internal constant BASE_CHAIN_SELECTOR = CCIPUtils.BASE_CHAIN_SELECTOR; uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; IGhoToken internal constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = @@ -100,19 +102,17 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { } function _upgradeArbTo1_5_1() internal { - vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ETH, + address(NEW_GHO_CCIP_STEWARD) + ); + vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + upgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); + vm.stopPrank(); - executePayload( - vm, - address( - new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ETH, - address(NEW_GHO_CCIP_STEWARD) - ) - ) - ); + executePayload(vm, address(upgradeProposal)); } function _deployNewTokenPoolArb() private returns (address) { @@ -161,6 +161,8 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); assertEq(proposal.REMOTE_TOKEN_POOL_BASE(), NEW_REMOTE_POOL_BASE); assertEq(proposal.REMOTE_GHO_TOKEN_BASE(), NEW_REMOTE_TOKEN_BASE); + assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); @@ -256,6 +258,27 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + 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() + }); + } + + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return amount / CCIP_RATE_LIMIT_REFILL_RATE + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config @@ -287,31 +310,36 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ); assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(BASE_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(BASE_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); } function test_sendMessageToBaseSucceeds(uint256 amount) public { - uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + uint256 bridgeableAmount = _min( + GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill deal(address(GHO), alice, amount); vm.prank(alice); GHO.approve(address(ROUTER), amount); uint256 aliceBalance = GHO.balanceOf(alice); + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; ( IClient.EVM2AnyMessage memory message, @@ -329,18 +357,23 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ROUTER.ccipSend{value: eventArg.feeTokenAmount}(BASE_CHAIN_SELECTOR, message); assertEq(GHO.balanceOf(alice), aliceBalance - amount); - assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bridgeableAmount - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel - amount); } function test_sendMessageToEthSucceeds(uint256 amount) public { - uint256 bridgeableAmount = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; + uint256 bridgeableAmount = _min( + GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill deal(address(GHO), alice, amount); vm.prank(alice); GHO.approve(address(ROUTER), amount); uint256 aliceBalance = GHO.balanceOf(alice); + uint256 bucketLevel = GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel; ( IClient.EVM2AnyMessage memory message, @@ -358,15 +391,16 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ROUTER.ccipSend{value: eventArg.feeTokenAmount}(ETH_CHAIN_SELECTOR, message); assertEq(GHO.balanceOf(alice), aliceBalance - amount); - assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bridgeableAmount - amount); + assertEq(GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketLevel, bucketLevel - amount); } function test_offRampViaBaseSucceeds(uint256 amount) public { (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( address(NEW_TOKEN_POOL) ); - uint256 mintAbleAmount = bucketCapacity - bucketLevel; + uint256 mintAbleAmount = _min(bucketCapacity - bucketLevel, CCIP_RATE_LIMIT_CAPACITY); amount = bound(amount, 1, mintAbleAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); @@ -395,8 +429,9 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { (uint256 bucketCapacity, uint256 bucketLevel) = GHO.getFacilitatorBucket( address(NEW_TOKEN_POOL) ); - uint256 mintAbleAmount = bucketCapacity - bucketLevel; + uint256 mintAbleAmount = _min(bucketCapacity - bucketLevel, CCIP_RATE_LIMIT_CAPACITY); amount = bound(amount, 1, mintAbleAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); @@ -423,6 +458,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { function test_cannotUseBaseOffRampForEthMessages() public { uint256 amount = 100e18; + skip(_getInboundRefillTime(amount)); vm.expectRevert( abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, address(BASE_OFF_RAMP)) @@ -444,6 +480,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { function test_cannotOffRampOtherChainMessages() public { uint256 amount = 100e18; + skip(_getInboundRefillTime(amount)); vm.expectRevert( abi.encodeWithSelector( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index fe351823a..0abd4a9b3 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -52,6 +52,11 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://arbiscan.io/address/ address public immutable REMOTE_TOKEN_POOL_ARB; + // Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; + constructor( address tokenPool, address tokenPoolEth, @@ -130,10 +135,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { } function _setupRemoteTokenPools() internal { - IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ - isEnabled: false, - capacity: 0, - rate: 0 + IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE }); IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] @@ -146,8 +151,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { remoteChainSelector: ETH_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(AaveV3EthereumAssets.GHO_UNDERLYING), - outboundRateLimiterConfig: emptyRateLimiterConfig, - inboundRateLimiterConfig: emptyRateLimiterConfig + outboundRateLimiterConfig: rateLimiterConfig, + inboundRateLimiterConfig: rateLimiterConfig }); } @@ -158,8 +163,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { remoteChainSelector: ARB_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(AaveV3ArbitrumAssets.GHO_UNDERLYING), - outboundRateLimiterConfig: emptyRateLimiterConfig, - inboundRateLimiterConfig: emptyRateLimiterConfig + outboundRateLimiterConfig: rateLimiterConfig, + inboundRateLimiterConfig: rateLimiterConfig }); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index a967157a2..ce148854f 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -51,6 +51,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; uint64 internal constant BASE_CHAIN_SELECTOR = CCIPUtils.BASE_CHAIN_SELECTOR; uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); @@ -210,6 +212,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { assertEq(proposal.GHO_CCIP_STEWARD(), address(NEW_GHO_CCIP_STEWARD)); assertEq(proposal.REMOTE_TOKEN_POOL_ARB(), NEW_REMOTE_POOL_ARB); assertEq(proposal.REMOTE_TOKEN_POOL_ETH(), NEW_REMOTE_POOL_ETH); + assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'BurnMintTokenPool 1.5.1'); @@ -316,6 +320,27 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + 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() + }); + } + + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return amount / CCIP_RATE_LIMIT_REFILL_RATE + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config @@ -451,19 +476,19 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); } } @@ -476,7 +501,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa } function test_sendMessageToArbSucceeds(uint256 amount) public { - amount = bound(amount, 1, 5_000_000e18); + amount = bound(amount, 1, CCIP_RATE_LIMIT_CAPACITY); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill // mock previously bridged amount vm.prank(address(NEW_TOKEN_POOL)); GHO.mint(alice, amount); // increase bucket level @@ -507,7 +533,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa } function test_sendMessageToEthSucceeds(uint256 amount) public { - amount = bound(amount, 1, 5_000_000e18); + amount = bound(amount, 1, CCIP_RATE_LIMIT_CAPACITY); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill // mock previously bridged amount vm.prank(address(NEW_TOKEN_POOL)); GHO.mint(alice, amount); // increase bucket level @@ -539,7 +566,15 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa } function test_offRampViaArbSucceeds(uint256 amount) public { - amount = bound(amount, 1, GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity); // initially, bucketLevel == 0 + amount = bound( + amount, + 1, + _min( + GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity, // initially, bucketLevel == 0 + CCIP_RATE_LIMIT_CAPACITY + ) + ); + skip(_getInboundRefillTime(amount)); // wait for the rate limiter to refill uint256 aliceBalance = GHO.balanceOf(alice); @@ -565,7 +600,15 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa } function test_offRampViaEthSucceeds(uint256 amount) public { - amount = bound(amount, 1, GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity); // initially, bucketLevel == 0 + amount = bound( + amount, + 1, + _min( + GHO.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity, // initially, bucketLevel == 0 + CCIP_RATE_LIMIT_CAPACITY + ) + ); + skip(_getInboundRefillTime(amount)); // wait for the rate limiter to refill uint256 aliceBalance = GHO.balanceOf(alice); @@ -592,6 +635,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa function test_cannotOffRampOtherChainMessages() public { uint256 amount = 100e18; + skip(_getInboundRefillTime(amount)); vm.expectRevert( abi.encodeWithSelector( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 8904ebb80..61c9b2818 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -14,6 +14,7 @@ import {IRouter} from 'src/interfaces/ccip/IRouter.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IPriceRegistry} from 'src/interfaces/ccip/IPriceRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; @@ -97,6 +98,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; IGhoToken internal constant GHO_TOKEN_BASE = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; ARB internal arb; BASE internal base; @@ -187,6 +190,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { function _upgradeEthArbTo1_5_1() internal returns (address, address) { // deploy new token pools and ghoCcipStewards vm.selectFork(eth.c.forkId); + IUpgradeableLockReleaseTokenPool_1_4 existingPoolEth = IUpgradeableLockReleaseTokenPool_1_4( GhoEthereum.GHO_CCIP_TOKEN_POOL ); @@ -228,70 +232,46 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { ); // execute CLL pre-requisites for the proposal - _performCLLPreReq(eth.c, GovernanceV3Ethereum.EXECUTOR_LVL_1); - _performCLLPreReq(arb.c, GovernanceV3Arbitrum.EXECUTOR_LVL_1); + vm.selectFork(eth.c.forkId); + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 ethUpgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( + newTokenPoolEth, + newTokenPoolArb, + newGhoCcipStewardEth + ); + vm.startPrank(eth.c.tokenAdminRegistry.owner()); + ethUpgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); + eth.c.tokenAdminRegistry.transferAdminRole( + address(eth.c.token), + GovernanceV3Ethereum.EXECUTOR_LVL_1 + ); + vm.stopPrank(); + + vm.selectFork(arb.c.forkId); + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 arbUpgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( + newTokenPoolArb, + newTokenPoolEth, + newGhoCcipStewardArb + ); + vm.startPrank(arb.c.tokenAdminRegistry.owner()); + arbUpgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); + arb.c.tokenAdminRegistry.transferAdminRole( + address(arb.c.token), + GovernanceV3Arbitrum.EXECUTOR_LVL_1 + ); + vm.stopPrank(); // execute proposal { vm.selectFork(eth.c.forkId); - executePayload( - vm, - address( - new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( - newTokenPoolEth, - newTokenPoolArb, - newGhoCcipStewardEth - ) - ) - ); + executePayload(vm, address(ethUpgradeProposal)); vm.selectFork(arb.c.forkId); - executePayload( - vm, - address( - new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( - newTokenPoolArb, - newTokenPoolEth, - newGhoCcipStewardArb - ) - ) - ); + executePayload(vm, address(arbUpgradeProposal)); } return (newTokenPoolEth, newTokenPoolArb); } - function _predictGhoTokenAddressBase(address logic) internal pure returns (address) { - return - _predictCreate2Address({ - creator: GovernanceV3Base.EXECUTOR_LVL_1, - salt: keccak256('based-GHO'), - creationCode: type(TransparentUpgradeableProxy).creationCode, - constructorArgs: abi.encode( - logic, - address(MiscBase.PROXY_ADMIN), - abi.encodeWithSignature('initialize(address)', GovernanceV3Base.EXECUTOR_LVL_1) - ) - }); - } - - function _predictCreate2Address( - address creator, - bytes32 salt, - bytes memory creationCode, - bytes memory constructorArgs - ) internal pure returns (address) { - bytes32 hash = keccak256( - abi.encodePacked( - bytes1(0xff), - creator, - salt, - keccak256(abi.encodePacked(creationCode, constructorArgs)) - ) - ); - return address(uint160(uint256(hash))); - } - function _deployNewBurnMintTokenPool( address ghoToken, address rmnProxy, @@ -510,7 +490,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { arb.tokenPool.getRemotePools(eth.c.chainSelector)[1], // 0th is the 1.4 token pool abi.encode(address(eth.tokenPool)) ); - _assertDisabledRateLimit(arb.c, address(arb.tokenPool)); + _assertSetRateLimit(arb.c, address(arb.tokenPool)); vm.selectFork(base.c.forkId); assertEq(base.proposal.GHO_TOKEN_IMPL(), _getImplementation(address(base.c.token))); @@ -535,7 +515,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { base.tokenPool.getRemotePools(eth.c.chainSelector)[0], abi.encode(address(eth.tokenPool)) ); - _assertDisabledRateLimit(base.c, address(base.tokenPool)); + _assertSetRateLimit(base.c, address(base.tokenPool)); vm.selectFork(eth.c.forkId); assertEq(eth.c.tokenAdminRegistry.getPool(address(eth.c.token)), address(eth.tokenPool)); @@ -556,7 +536,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { eth.tokenPool.getRemotePools(base.c.chainSelector)[0], abi.encode(address(base.tokenPool)) ); - _assertDisabledRateLimit(eth.c, address(eth.tokenPool)); + _assertSetRateLimit(eth.c, address(eth.tokenPool)); } else { vm.selectFork(base.c.forkId); // correct gho Token Address @@ -604,27 +584,27 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { assertTrue(router.isOffRamp(srcSelector, address(offRamp))); } - function _assertDisabledRateLimit(Common memory src, address tokenPool) internal view { + function _assertSetRateLimit(Common memory src, address tokenPool) internal view { (Common memory dst1, Common memory dst2) = _getDestination(src); IUpgradeableLockReleaseTokenPool_1_5_1 _tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( tokenPool ); assertEq( _tokenPool.getCurrentInboundRateLimiterState(dst1.chainSelector), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( _tokenPool.getCurrentOutboundRateLimiterState(dst1.chainSelector), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( _tokenPool.getCurrentInboundRateLimiterState(dst2.chainSelector), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( _tokenPool.getCurrentOutboundRateLimiterState(dst2.chainSelector), - _getDisabledConfig() + _getRateLimiterConfig() ); } @@ -658,12 +638,72 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + function _getRateLimiterConfig() internal pure returns (IRateLimiter.Config memory) { + return + IRateLimiter.Config({ + isEnabled: true, + capacity: uint128(CCIP_RATE_LIMIT_CAPACITY), + rate: uint128(CCIP_RATE_LIMIT_REFILL_RATE) + }); + } + + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config ) internal pure { assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } + + // @dev refresh token prices to the last stored such that price is not stale + // @dev assumed src.forkId is already active + function _refreshGasAndTokenPrices(Common memory src, Common memory dst) internal { + uint64 destChainSelector = dst.chainSelector; + IEVM2EVMOnRamp srcOnRamp = IEVM2EVMOnRamp(src.router.getOnRamp(destChainSelector)); + address bridgeToken = address(src.token); + address feeToken = src.router.getWrappedNative(); // needed as we do tests with wrapped native as fee token + address linkToken = srcOnRamp.getStaticConfig().linkToken; // needed as feeTokenAmount is converted to linkTokenAmount + IInternal.TokenPriceUpdate[] memory tokenPriceUpdates = new IInternal.TokenPriceUpdate[](3); + IInternal.GasPriceUpdate[] memory gasPriceUpdates = new IInternal.GasPriceUpdate[](1); + IPriceRegistry priceRegistry = IPriceRegistry(srcOnRamp.getDynamicConfig().priceRegistry); // both ramps have the same price registry + + tokenPriceUpdates[0] = IInternal.TokenPriceUpdate({ + sourceToken: bridgeToken, + usdPerToken: priceRegistry.getTokenPrice(bridgeToken).value + }); + tokenPriceUpdates[1] = IInternal.TokenPriceUpdate({ + sourceToken: feeToken, + usdPerToken: priceRegistry.getTokenPrice(feeToken).value + }); + tokenPriceUpdates[2] = IInternal.TokenPriceUpdate({ + sourceToken: linkToken, + usdPerToken: priceRegistry.getTokenPrice(linkToken).value + }); + + gasPriceUpdates[0] = IInternal.GasPriceUpdate({ + destChainSelector: destChainSelector, + usdPerUnitGas: priceRegistry.getDestinationChainGasPrice(destChainSelector).value + }); + + vm.prank(priceRegistry.owner()); + priceRegistry.updatePrices( + IInternal.PriceUpdates({ + tokenPriceUpdates: tokenPriceUpdates, + gasPriceUpdates: gasPriceUpdates + }) + ); + } } contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLaunch_20241223_Base { @@ -685,9 +725,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa function test_E2E_Eth_Base(uint256 amount) public { { vm.selectFork(eth.c.forkId); - uint256 bridgeableAmount = eth.tokenPool.getBridgeLimit() - - eth.tokenPool.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + eth.tokenPool.getBridgeLimit() - eth.tokenPool.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(eth.c, base.c); vm.prank(alice); eth.c.token.approve(address(eth.c.router), amount); @@ -719,6 +763,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa // base execute message vm.selectFork(base.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(base.c, eth.c); assertEq(base.c.token.balanceOf(alice), 0); assertEq(base.c.token.totalSupply(), 0); // first bridge assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, 0); // first bridge @@ -741,6 +787,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa { // send base from base vm.selectFork(base.c.forkId); + + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(base.c, eth.c); vm.prank(alice); base.c.token.approve(address(base.c.router), amount); @@ -765,6 +814,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa // eth execute message vm.selectFork(eth.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(eth.c, base.c); uint256 bridgedAmount = eth.tokenPool.getCurrentBridgedAmount(); vm.expectEmit(address(eth.tokenPool)); @@ -784,8 +835,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa function test_E2E_Arb_Base(uint256 amount) public { { vm.selectFork(arb.c.forkId); - uint256 bridgeableAmount = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; + uint256 bridgeableAmount = _min( + arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel, + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(arb.c, base.c); vm.prank(alice); arb.c.token.approve(address(arb.c.router), amount); @@ -818,6 +874,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa // base execute message vm.selectFork(base.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(base.c, arb.c); assertEq(base.c.token.balanceOf(alice), 0); assertEq(base.c.token.totalSupply(), 0); // first bridge assertEq(base.c.token.getFacilitator(address(base.tokenPool)).bucketLevel, 0); // first bridge @@ -840,6 +898,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa { // send base from base vm.selectFork(base.c.forkId); + + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(base.c, arb.c); vm.prank(alice); base.c.token.approve(address(base.c.router), amount); @@ -864,6 +925,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa // arb execute message vm.selectFork(arb.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(arb.c, base.c); uint256 facilitatorLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; vm.expectEmit(address(arb.tokenPool)); @@ -886,9 +949,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa function test_E2E_Eth_Arb(uint256 amount) public { { vm.selectFork(eth.c.forkId); - uint256 bridgeableAmount = eth.tokenPool.getBridgeLimit() - - eth.tokenPool.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + eth.tokenPool.getBridgeLimit() - eth.tokenPool.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(eth.c, arb.c); vm.prank(alice); eth.c.token.approve(address(eth.c.router), amount); @@ -918,6 +985,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa // arb execute message vm.selectFork(arb.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(arb.c, eth.c); aliceBalance = arb.c.token.balanceOf(alice); uint256 bucketLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; @@ -944,6 +1013,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa vm.selectFork(arb.c.forkId); vm.prank(alice); arb.c.token.approve(address(arb.c.router), amount); + skip(_getOutboundRefillTime(amount)); + _refreshGasAndTokenPrices(arb.c, eth.c); uint256 aliceBalance = arb.c.token.balanceOf(alice); uint256 bucketLevel = arb.c.token.getFacilitator(address(arb.tokenPool)).bucketLevel; @@ -970,6 +1041,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PostExecution is AaveV3Base_GHOBaseLa // eth execute message vm.selectFork(eth.c.forkId); + skip(_getInboundRefillTime(amount)); + _refreshGasAndTokenPrices(eth.c, arb.c); uint256 bridgedAmount = eth.tokenPool.getCurrentBridgedAmount(); vm.expectEmit(address(eth.tokenPool)); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index 262d5cd35..3b7caeeac 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -22,16 +22,21 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + // Token Rate Limit Capacity: 300_000 GHO + uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) + uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; + constructor(address tokenPoolEth, address tokenPoolBase) { TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(tokenPoolEth); REMOTE_TOKEN_POOL_BASE = tokenPoolBase; } function execute() external { - IRateLimiter.Config memory emptyRateLimiterConfig = IRateLimiter.Config({ - isEnabled: false, - capacity: 0, - rate: 0 + IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: CCIP_RATE_LIMIT_CAPACITY, + rate: CCIP_RATE_LIMIT_REFILL_RATE }); IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[] @@ -44,8 +49,8 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { remoteChainSelector: BASE_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(REMOTE_GHO_TOKEN_BASE), - outboundRateLimiterConfig: emptyRateLimiterConfig, - inboundRateLimiterConfig: emptyRateLimiterConfig + outboundRateLimiterConfig: rateLimiterConfig, + inboundRateLimiterConfig: rateLimiterConfig }); TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 52bff3e33..17d6a6ec8 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -47,6 +47,8 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { uint64 internal constant ARB_CHAIN_SELECTOR = CCIPUtils.ARB_CHAIN_SELECTOR; uint64 internal constant BASE_CHAIN_SELECTOR = CCIPUtils.BASE_CHAIN_SELECTOR; uint64 internal constant ETH_CHAIN_SELECTOR = CCIPUtils.ETH_CHAIN_SELECTOR; + uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; + uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; IGhoToken internal constant GHO = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = @@ -100,19 +102,17 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { } function _upgradeEthTo1_5_1() internal { - vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ARB, + address(NEW_GHO_CCIP_STEWARD) + ); + vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1); + upgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); + vm.stopPrank(); - executePayload( - vm, - address( - new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ARB, - address(NEW_GHO_CCIP_STEWARD) - ) - ) - ); + executePayload(vm, address(upgradeProposal)); } function _deployNewTokenPoolEth() private returns (address) { @@ -164,13 +164,18 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); assertEq(proposal.REMOTE_TOKEN_POOL_BASE(), NEW_REMOTE_POOL_BASE); assertEq(proposal.REMOTE_GHO_TOKEN_BASE(), NEW_REMOTE_TOKEN_BASE); + assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); + assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); + assertEq(TOKEN_ADMIN_REGISTRY.typeAndVersion(), 'TokenAdminRegistry 1.5.0'); assertEq(NEW_TOKEN_POOL.typeAndVersion(), 'LockReleaseTokenPool 1.5.1'); assertEq(ROUTER.typeAndVersion(), 'Router 1.2.0'); + _assertOnRamp(ARB_ON_RAMP, ETH_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); _assertOnRamp(BASE_ON_RAMP, ETH_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); _assertOffRamp(BASE_OFF_RAMP, BASE_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), GovernanceV3Ethereum.EXECUTOR_LVL_1); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); @@ -247,13 +252,6 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { 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)); - } - function _getImplementation(address proxy) internal view returns (address) { bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); return address(uint160(uint256(vm.load(proxy, slot)))); @@ -263,6 +261,34 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + 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() + }); + } + + function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { + return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding + } + + function _getInboundRefillTime(uint256 amount) internal pure returns (uint256) { + return amount / CCIP_RATE_LIMIT_REFILL_RATE + 1; // account for rounding + } + + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + } + function test_BasePoolConfig() public view { assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); assertEq(NEW_TOKEN_POOL.getSupportedChains()[0], ARB_CHAIN_SELECTOR); @@ -287,26 +313,29 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ); assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(BASE_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); assertEq( NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(BASE_CHAIN_SELECTOR), - _getDisabledConfig() + _getRateLimiterConfig() ); } function test_sendMessageToBaseSucceeds(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - - NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getBridgeLimit() - NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill deal(address(GHO), alice, amount); vm.prank(alice); @@ -335,9 +364,12 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { } function test_sendMessageToArbSucceeds(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getBridgeLimit() - - NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getBridgeLimit() - NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getOutboundRefillTime(amount)); // wait for the rate limiter to refill deal(address(GHO), alice, amount); vm.prank(alice); @@ -366,11 +398,16 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { } function test_offRampViaBaseSucceeds(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); uint256 poolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + uint256 currentBridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); vm.expectEmit(address(NEW_TOKEN_POOL)); emit Released(address(BASE_OFF_RAMP), alice, amount); @@ -391,16 +428,21 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), poolBalance - amount); assertEq(GHO.balanceOf(alice), aliceBalance + amount); - assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgeableAmount - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), currentBridgedAmount - amount); assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), GHO.balanceOf(address(NEW_TOKEN_POOL))); } function test_offRampViaArbSucceeds(uint256 amount) public { - uint256 bridgeableAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); + uint256 bridgeableAmount = _min( + NEW_TOKEN_POOL.getCurrentBridgedAmount(), + CCIP_RATE_LIMIT_CAPACITY + ); amount = bound(amount, 1, bridgeableAmount); + skip(_getInboundRefillTime(amount)); uint256 aliceBalance = GHO.balanceOf(alice); uint256 poolBalance = GHO.balanceOf(address(NEW_TOKEN_POOL)); + uint256 currentBridgedAmount = NEW_TOKEN_POOL.getCurrentBridgedAmount(); vm.expectEmit(address(NEW_TOKEN_POOL)); emit Released(address(ARB_OFF_RAMP), alice, amount); @@ -421,12 +463,13 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(GHO.balanceOf(address(NEW_TOKEN_POOL)), poolBalance - amount); assertEq(GHO.balanceOf(alice), aliceBalance + amount); - assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgeableAmount - amount); + assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), currentBridgedAmount - amount); assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), GHO.balanceOf(address(NEW_TOKEN_POOL))); } function test_cannotUseBaseOffRampForArbMessages() public { uint256 amount = 100e18; + skip(_getInboundRefillTime(amount)); vm.expectRevert( abi.encodeWithSelector(CallerIsNotARampOnRouter.selector, address(BASE_OFF_RAMP)) @@ -448,6 +491,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { function test_cannotOffRampOtherChainMessages() public { uint256 amount = 100e18; + skip(_getInboundRefillTime(amount)); vm.expectRevert( abi.encodeWithSelector( From 36c044626933826ae8f40bbf8e01265ae8a747ef Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 13:24:30 +0530 Subject: [PATCH 075/123] fix: riskCouncil --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 5 +++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 13 +++++++------ .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 5 +++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 7d5ecdc19..83d21aff2 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -62,6 +62,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); + address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted @@ -150,7 +151,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { new GhoCcipSteward( address(GHO), newTokenPool, - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // riskAdmin, using executor for convenience + RISK_COUNCIL, false // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool ) ); @@ -173,7 +174,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { _assertOffRamp(ETH_OFF_RAMP, ETH_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); _assertOffRamp(BASE_OFF_RAMP, BASE_CHAIN_SELECTOR, ARB_CHAIN_SELECTOR, ROUTER); - assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 61c9b2818..4a8556d73 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -92,9 +92,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { Common c; } + address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; // common across all chains address internal constant RMN_PROXY_BASE = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; - address internal constant RISK_COUNCIL_BASE = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; address internal constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; IGhoToken internal constant GHO_TOKEN_BASE = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP @@ -206,7 +206,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { new GhoCcipSteward({ ghoTokenPool: newTokenPoolEth, ghoToken: AaveV3EthereumAssets.GHO_UNDERLYING, - riskCouncil: makeAddr('ETH: riskAdmin'), + riskCouncil: RISK_COUNCIL, bridgeLimitEnabled: true }) ); @@ -226,7 +226,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { new GhoCcipSteward({ ghoTokenPool: newTokenPoolArb, ghoToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, - riskCouncil: makeAddr('ARB: riskAdmin'), + riskCouncil: RISK_COUNCIL, bridgeLimitEnabled: false }) ); @@ -361,7 +361,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), ghoToken: address(GHO_TOKEN_BASE), - riskCouncil: RISK_COUNCIL_BASE, + riskCouncil: RISK_COUNCIL, borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ optimalUsageRatioMaxChange: 500, baseVariableBorrowRateMaxChange: 500, @@ -374,14 +374,14 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { new GhoBucketSteward({ owner: GovernanceV3Base.EXECUTOR_LVL_1, ghoToken: address(GHO_TOKEN_BASE), - riskCouncil: RISK_COUNCIL_BASE + riskCouncil: RISK_COUNCIL }) ); address ccipSteward = address( new GhoCcipSteward({ ghoToken: address(GHO_TOKEN_BASE), ghoTokenPool: ghoTokenPool, - riskCouncil: RISK_COUNCIL_BASE, + riskCouncil: RISK_COUNCIL, bridgeLimitEnabled: false }) ); @@ -494,6 +494,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(base.c.forkId); assertEq(base.proposal.GHO_TOKEN_IMPL(), _getImplementation(address(base.c.token))); + assertEq(address(base.proposal.GHO_TOKEN_PROXY()), address(base.c.token)); assertEq(base.c.tokenAdminRegistry.getPool(address(base.c.token)), address(base.tokenPool)); assertEq(base.tokenPool.getSupportedChains()[0], eth.c.chainSelector); assertEq(base.tokenPool.getSupportedChains()[1], arb.c.chainSelector); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 17d6a6ec8..e6165adc7 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -62,6 +62,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); + address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; // common across all chains IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted @@ -153,7 +154,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { new GhoCcipSteward( address(GHO), newTokenPool, - GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, using executor for convenience + RISK_COUNCIL, true // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool ) ); @@ -176,7 +177,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); _assertOffRamp(BASE_OFF_RAMP, BASE_CHAIN_SELECTOR, ETH_CHAIN_SELECTOR, ROUTER); - assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); From 68a84417997331a1ed00c3ef415eeca4710cbd94 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 20:00:52 +0530 Subject: [PATCH 076/123] feat: gho base listing --- ...aveV3Base_GHOBaseListing_20241223_after.md | 110 +++++++++ .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3Base_GHOBaseListing_20241223.sol | 69 ++++++ .../AaveV3Base_GHOBaseListing_20241223.t.sol | 209 ++++++++++++++++++ .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 2 +- .../GHOBaseLaunch.md | 36 ++- .../GHOBaseLaunch_20241223.s.sol | 39 ++-- src/20241223_Multi_GHOBaseLaunch/config.ts | 33 ++- src/interfaces/IGhoOracle.sol | 23 ++ 9 files changed, 502 insertions(+), 21 deletions(-) create mode 100644 diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol create mode 100644 src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol create mode 100644 src/interfaces/IGhoOracle.sol diff --git a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md new file mode 100644 index 000000000..392d1217f --- /dev/null +++ b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md @@ -0,0 +1,110 @@ +## Reserve changes + +### Reserves added + +#### GHO ([0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D](https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D)) + +| description | value | +| --- | --- | +| decimals | 18 | +| isActive | true | +| isFrozen | false | +| supplyCap | 2,500,000 GHO | +| borrowCap | 2,250,000 GHO | +| debtCeiling | 0 $ [0] | +| isSiloed | false | +| isFlashloanable | true | +| oracle | [0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73](https://basescan.org/address/0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73) | +| oracleDecimals | 8 | +| oracleLatestAnswer | 1 | +| usageAsCollateralEnabled | false | +| ltv | 0 % [0] | +| liquidationThreshold | 0 % [0] | +| liquidationBonus | 0 % | +| liquidationProtocolFee | 0 % [0] | +| reserveFactor | 10 % [1000] | +| aToken | [0xDD5745756C2de109183c6B5bB886F9207bEF114D](https://basescan.org/address/0xDD5745756C2de109183c6B5bB886F9207bEF114D) | +| aTokenImpl | [0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69](https://basescan.org/address/0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69) | +| variableDebtToken | [0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd](https://basescan.org/address/0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd) | +| variableDebtTokenImpl | [0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1](https://basescan.org/address/0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1) | +| borrowingEnabled | true | +| isBorrowableInIsolation | false | +| interestRateStrategy | [0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5](https://basescan.org/address/0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5) | +| aTokenName | Aave Base GHO | +| aTokenSymbol | aBasGHO | +| aTokenUnderlyingBalance | 1 GHO [1000000000000000000] | +| id | 7 | +| isPaused | false | +| variableDebtTokenName | Aave Base Variable Debt GHO | +| variableDebtTokenSymbol | variableDebtBasGHO | +| virtualAccountingActive | true | +| virtualBalance | 1 GHO [1000000000000000000] | +| optimalUsageRatio | 90 % | +| maxVariableBorrowRate | 77 % | +| baseVariableBorrowRate | 0 % | +| variableRateSlope1 | 12 % | +| variableRateSlope2 | 65 % | +| interestRate | ![ir](https://dash.onaave.com/api/static?variableRateSlope1=120000000000000000000000000&variableRateSlope2=650000000000000000000000000&optimalUsageRatio=900000000000000000000000000&baseVariableBorrowRate=0&maxVariableBorrowRate=770000000000000000000000000) | + + +## Raw diff + +```json +{ + "reserves": { + "0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D": { + "from": null, + "to": { + "aToken": "0xDD5745756C2de109183c6B5bB886F9207bEF114D", + "aTokenImpl": "0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69", + "aTokenName": "Aave Base GHO", + "aTokenSymbol": "aBasGHO", + "aTokenUnderlyingBalance": "1000000000000000000", + "borrowCap": 2250000, + "borrowingEnabled": true, + "debtCeiling": 0, + "decimals": 18, + "id": 7, + "interestRateStrategy": "0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5", + "isActive": true, + "isBorrowableInIsolation": false, + "isFlashloanable": true, + "isFrozen": false, + "isPaused": false, + "isSiloed": false, + "liquidationBonus": 0, + "liquidationProtocolFee": 0, + "liquidationThreshold": 0, + "ltv": 0, + "oracle": "0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73", + "oracleDecimals": 8, + "oracleLatestAnswer": "100000000", + "reserveFactor": 1000, + "supplyCap": 2500000, + "symbol": "GHO", + "underlying": "0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D", + "usageAsCollateralEnabled": false, + "variableDebtToken": "0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd", + "variableDebtTokenImpl": "0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1", + "variableDebtTokenName": "Aave Base Variable Debt GHO", + "variableDebtTokenSymbol": "variableDebtBasGHO", + "virtualAccountingActive": true, + "virtualBalance": "1000000000000000000" + } + } + }, + "strategies": { + "0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D": { + "from": null, + "to": { + "address": "0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5", + "baseVariableBorrowRate": "0", + "maxVariableBorrowRate": "770000000000000000000000000", + "optimalUsageRatio": "900000000000000000000000000", + "variableRateSlope1": "120000000000000000000000000", + "variableRateSlope2": "650000000000000000000000000" + } + } + } +} +``` \ No newline at end of file diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index ce148854f..60050356b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -94,7 +94,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24139320); + vm.createSelectFork(vm.rpcUrl('base'), 24430581); NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( _deployNewBurnMintTokenPool( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol new file mode 100644 index 000000000..80bee245d --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {IAaveV3ConfigEngine} from 'aave-v3-origin/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol'; +import {IEmissionManager} from 'aave-v3-origin/contracts/rewards/interfaces/IEmissionManager.sol'; +import {EngineFlags} from 'aave-v3-origin/contracts/extensions/v3-config-engine/EngineFlags.sol'; +import {AaveV3PayloadBase} from 'aave-helpers/src/v3-config-engine/AaveV3PayloadBase.sol'; +import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; + +/** + * @title GHO Base Listing + * @author Aave Labs + * - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338 + * - Snapshot: https://snapshot.box/#/s:aave.eth/proposal/0x03dc21e0423c60082dc23317af6ebaf997610cbc2cbb0f5a385653bd99a524fe + */ +contract AaveV3Base_GHOBaseListing_20241223 is AaveV3PayloadBase { + using SafeERC20 for IERC20; + + // https://basescan.org/address/0xac140648435d03f784879cd789130F22Ef588Fcd + address public constant EMISSION_ADMIN = 0xac140648435d03f784879cd789130F22Ef588Fcd; + // https://basescan.org/address/0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73 + address public constant GHO_PRICE_FEED = 0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73; + // predicted address, will be deployed in the launch AIP, https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D + address public constant GHO_TOKEN = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; + uint256 public constant GHO_SEED_AMOUNT = 1e18; + + function _postExecute() internal override { + IERC20(GHO_TOKEN).forceApprove(address(AaveV3Base.POOL), GHO_SEED_AMOUNT); + AaveV3Base.POOL.supply(GHO_TOKEN, GHO_SEED_AMOUNT, address(0), 0); + + (address aGhoToken, , ) = AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses( + GHO_TOKEN + ); + IEmissionManager(AaveV3Base.EMISSION_MANAGER).setEmissionAdmin(GHO_TOKEN, EMISSION_ADMIN); + IEmissionManager(AaveV3Base.EMISSION_MANAGER).setEmissionAdmin(aGhoToken, EMISSION_ADMIN); + } + + function newListings() public pure override returns (IAaveV3ConfigEngine.Listing[] memory) { + IAaveV3ConfigEngine.Listing[] memory listings = new IAaveV3ConfigEngine.Listing[](1); + + listings[0] = IAaveV3ConfigEngine.Listing({ + asset: GHO_TOKEN, + assetSymbol: 'GHO', + priceFeed: GHO_PRICE_FEED, + enabledToBorrow: EngineFlags.ENABLED, + borrowableInIsolation: EngineFlags.DISABLED, + withSiloedBorrowing: EngineFlags.DISABLED, + flashloanable: EngineFlags.ENABLED, + ltv: 0, + liqThreshold: 0, + liqBonus: 0, + reserveFactor: 10_00, + supplyCap: 2_500_000, + borrowCap: 2_250_000, + debtCeiling: 0, + liqProtocolFee: 0, + rateStrategyParams: IAaveV3ConfigEngine.InterestRateInputData({ + optimalUsageRatio: 90_00, + baseVariableBorrowRate: 0, + variableRateSlope1: 12_00, + variableRateSlope2: 65_00 + }) + }); + + return listings; + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol new file mode 100644 index 000000000..b38d30844 --- /dev/null +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Test.sol'; + +import {IEmissionManager} from 'aave-v3-origin/contracts/rewards/interfaces/IEmissionManager.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; +import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; +import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; +import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoOracle} from 'src/interfaces/IGhoOracle.sol'; + +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; +import {GovV3Helpers} from 'aave-helpers/src/GovV3Helpers.sol'; +import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; +import {MiscBase} from 'aave-address-book/MiscBase.sol'; +import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; +import {GhoAaveSteward} from 'gho-core/misc/GhoAaveSteward.sol'; +import {GhoBucketSteward} from 'gho-core/misc/GhoBucketSteward.sol'; +import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; + +import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; +import {AaveV3Base_GHOBaseListing_20241223} from './AaveV3Base_GHOBaseListing_20241223.sol'; + +/** + * @dev Test for AaveV3Base_Ads_20241231 + * command: FOUNDRY_PROFILE=base forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol -vv + */ +contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { + AaveV3Base_GHOBaseListing_20241223 internal proposal; + + ITokenAdminRegistry internal constant TOKEN_ADMIN_REGISTRY = + ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); + address internal constant ROUTER = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; + address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; + address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; + IGhoToken internal constant GHO_TOKEN = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + + address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); + address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); + IGhoAaveSteward internal NEW_GHO_AAVE_STEWARD; + IGhoBucketSteward internal NEW_GHO_BUCKET_STEWARD; + IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; + + function setUp() public virtual { + vm.createSelectFork(vm.rpcUrl('base'), 24430581); + _executeLaunchAIP(); // deploys gho token, token pool & stewards + + proposal = new AaveV3Base_GHOBaseListing_20241223(); + } + + function _executeLaunchAIP() internal { + NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( + _deployNewBurnMintTokenPool( + address(GHO_TOKEN), + RMN_PROXY, + ROUTER, + GovernanceV3Base.EXECUTOR_LVL_1, // owner + MiscBase.PROXY_ADMIN + ) + ); + (NEW_GHO_AAVE_STEWARD, NEW_GHO_BUCKET_STEWARD, NEW_GHO_CCIP_STEWARD) = _deployStewards(); + + _performCcipPreReq(); + + executePayload( + vm, + address( + new AaveV3Base_GHOBaseLaunch_20241223( + address(NEW_TOKEN_POOL), + NEW_REMOTE_POOL_ETH, + NEW_REMOTE_POOL_ARB, + address(NEW_GHO_AAVE_STEWARD), + address(NEW_GHO_BUCKET_STEWARD), + address(NEW_GHO_CCIP_STEWARD) + ) + ) + ); + } + + function _performCcipPreReq() internal { + vm.prank(TOKEN_ADMIN_REGISTRY.owner()); + TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO_TOKEN), GovernanceV3Base.EXECUTOR_LVL_1); + } + function _deployNewBurnMintTokenPool( + address ghoToken, + address rmnProxy, + address router, + address owner, + address proxyAdmin + ) private returns (address) { + address newTokenPoolImpl = address( + new UpgradeableBurnMintTokenPool( + ghoToken, + 18, + rmnProxy, + false // allowListEnabled + ) + ); + + return + address( + new TransparentUpgradeableProxy( + newTokenPoolImpl, + ProxyAdmin(proxyAdmin), + abi.encodeCall( + IUpgradeableBurnMintTokenPool_1_5_1.initialize, + ( + owner, + new address[](0), // allowList + router + ) + ) + ) + ); + } + function _deployStewards() + internal + returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) + { + address aaveSteward = address( + new GhoAaveSteward({ + owner: GovernanceV3Base.EXECUTOR_LVL_1, + addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), + poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), + ghoToken: address(GHO_TOKEN), + riskCouncil: RISK_COUNCIL, + borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ + optimalUsageRatioMaxChange: 500, + baseVariableBorrowRateMaxChange: 500, + variableRateSlope1MaxChange: 500, + variableRateSlope2MaxChange: 500 + }) + }) + ); + address bucketSteward = address( + new GhoBucketSteward({ + owner: GovernanceV3Base.EXECUTOR_LVL_1, + ghoToken: address(GHO_TOKEN), + riskCouncil: RISK_COUNCIL + }) + ); + address ccipSteward = address( + new GhoCcipSteward({ + ghoToken: address(GHO_TOKEN), + ghoTokenPool: address(NEW_TOKEN_POOL), + riskCouncil: RISK_COUNCIL, + bridgeLimitEnabled: false + }) + ); + return ( + IGhoAaveSteward(aaveSteward), + IGhoBucketSteward(bucketSteward), + IGhoCcipSteward(ccipSteward) + ); + } +} + +contract AaveV3Base_GHOBaseListing_20241223_Listing is AaveV3Base_GHOBaseListing_20241223_Base { + function setUp() public override { + super.setUp(); + + uint256 seedAmount = proposal.GHO_SEED_AMOUNT(); + // mock executor receives seed amount after Launch AIP (ie bridge activation) + vm.prank(address(NEW_TOKEN_POOL)); + GHO_TOKEN.mint(GovernanceV3Base.EXECUTOR_LVL_1, seedAmount); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest('AaveV3Base_GHOBaseListing_20241223', AaveV3Base.POOL, address(proposal)); + + (address aGhoToken, , ) = AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses( + proposal.GHO_TOKEN() + ); + assertGe(IERC20(aGhoToken).balanceOf(address(0)), proposal.GHO_SEED_AMOUNT()); + } + + function test_ghoPriceFeed() public view { + IGhoOracle priceOracle = IGhoOracle(proposal.GHO_PRICE_FEED()); + assertEq(priceOracle.latestAnswer(), 1e8); + assertEq(priceOracle.decimals(), 8); + } + + function test_GhoAdmin() public { + GovV3Helpers.executePayload(vm, address(proposal)); + (address aGhoToken, , ) = AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses( + proposal.GHO_TOKEN() + ); + assertEq( + IEmissionManager(AaveV3Base.EMISSION_MANAGER).getEmissionAdmin(proposal.GHO_TOKEN()), + proposal.EMISSION_ADMIN() + ); + assertEq( + IEmissionManager(AaveV3Base.EMISSION_MANAGER).getEmissionAdmin(aGhoToken), + proposal.EMISSION_ADMIN() + ); + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 4a8556d73..9fdda37b4 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -121,7 +121,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { function setUp() public virtual { arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24139320); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24430581); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21463360); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md index dac8d1d39..4f077ce26 100644 --- a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md @@ -1,7 +1,7 @@ --- title: "GHO Base Launch" author: "Aave Labs" -discussions: "" +discussions: "https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338" --- ## Simple Summary @@ -10,12 +10,38 @@ discussions: "" ## Specification +The table below illustrates the configured risk parameters for **GHO** + +| Parameter | Value | +| ------------------------- | -----------------------------------------: | +| Isolation Mode | false | +| Borrowable | ENABLED | +| Collateral Enabled | false | +| Supply Cap (BLT) | 2,500,000 | +| Borrow Cap (BLT) | 2,250,000 | +| Debt Ceiling | USD 0 | +| LTV | 0 % | +| LT | 0 % | +| Liquidation Bonus | 0 % | +| Liquidation Protocol Fee | 0 % | +| Reserve Factor | 10 % | +| Base Variable Borrow Rate | 0 % | +| Variable Slope 1 | 12 % | +| Variable Slope 2 | 65 % | +| Uoptimal | 90 % | +| Flashloanable | ENABLED | +| Siloed Borrowing | DISABLED | +| Borrowable in Isolation | DISABLED | +| Oracle | 0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73 | + +Additionaly [0xac140648435d03f784879cd789130F22Ef588Fcd](https://basescan.org/address/0xac140648435d03f784879cd789130F22Ef588Fcd) has been set as the emission admin for GHO and the corresponding aToken. + ## References -- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol), [AaveV3Base](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol) -- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol), [AaveV3Base](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol) -- [Snapshot](TODO) -- [Discussion](TODO) +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol), [AaveV3BaseLaunch](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol), [AaveV3BaseListing](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol), [AaveV3BaseLaunch](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol), [AaveV3BaseListing](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol), [E2EFlow](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol) +- [Snapshot](https://snapshot.box/#/s:aave.eth/proposal/0x03dc21e0423c60082dc23317af6ebaf997610cbc2cbb0f5a385653bd99a524fe) +- [Discussion](https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-emissions-manager-for-rewards/19338) ## Copyright diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol index dc4a2baaf..b954d900e 100644 --- a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol @@ -7,7 +7,7 @@ import {EthereumScript, ArbitrumScript, BaseScript} from 'solidity-utils/contrac import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; - +import {AaveV3Base_GHOBaseListing_20241223} from './AaveV3Base_GHOBaseListing_20241223.sol'; /** * @dev Deploy Ethereum * deploy-command: make deploy-ledger contract=src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch_20241223.s.sol:DeployEthereum chain=mainnet @@ -59,18 +59,22 @@ contract DeployArbitrum is ArbitrumScript { */ contract DeployBase is BaseScript { function run() external broadcast { - // deploy payloads - address payload0 = GovV3Helpers.deployDeterministic( - type(AaveV3Base_GHOBaseLaunch_20241223).creationCode + // compose action + IPayloadsControllerCore.ExecutionAction[] + memory launchActions = new IPayloadsControllerCore.ExecutionAction[](1); + launchActions[0] = GovV3Helpers.buildAction( + GovV3Helpers.deployDeterministic(type(AaveV3Base_GHOBaseLaunch_20241223).creationCode) ); - // compose action IPayloadsControllerCore.ExecutionAction[] - memory actions = new IPayloadsControllerCore.ExecutionAction[](1); - actions[0] = GovV3Helpers.buildAction(payload0); + memory listingActions = new IPayloadsControllerCore.ExecutionAction[](1); + listingActions[0] = GovV3Helpers.buildAction( + GovV3Helpers.deployDeterministic(type(AaveV3Base_GHOBaseListing_20241223).creationCode) + ); - // register action at payloadsController - GovV3Helpers.createPayload(actions); + // register both actions separately at payloadsController + GovV3Helpers.createPayload(launchActions); + GovV3Helpers.createPayload(listingActions); } } @@ -81,7 +85,7 @@ contract DeployBase is BaseScript { contract CreateProposal is EthereumScript { function run() external { // create payloads - PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](3); + PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](4); // compose actions for validation IPayloadsControllerCore.ExecutionAction[] @@ -99,9 +103,18 @@ contract CreateProposal is EthereumScript { payloads[1] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum); IPayloadsControllerCore.ExecutionAction[] - memory actionsBase = new IPayloadsControllerCore.ExecutionAction[](1); - actionsBase[0] = GovV3Helpers.buildAction(type(AaveV3Base_GHOBaseLaunch_20241223).creationCode); - payloads[2] = GovV3Helpers.buildBasePayload(vm, actionsBase); + memory actionsBaseLaunch = new IPayloadsControllerCore.ExecutionAction[](1); + actionsBaseLaunch[0] = GovV3Helpers.buildAction( + type(AaveV3Base_GHOBaseLaunch_20241223).creationCode + ); + payloads[2] = GovV3Helpers.buildBasePayload(vm, actionsBaseLaunch); + + IPayloadsControllerCore.ExecutionAction[] + memory actionsBaseListing = new IPayloadsControllerCore.ExecutionAction[](1); + actionsBaseListing[0] = GovV3Helpers.buildAction( + type(AaveV3Base_GHOBaseListing_20241223).creationCode + ); + payloads[3] = GovV3Helpers.buildBasePayload(vm, actionsBaseListing); // create proposal vm.startBroadcast(); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 6ae5ea3f6..aee9d730b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -15,6 +15,37 @@ export const config: ConfigFile = { poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21463360}}, AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, - AaveV3Base: {configs: {OTHERS: {}}, cache: {blockNumber: 24139320}}, + AaveV3Base: { + configs: { + ASSET_LISTING: [ + { + assetSymbol: 'GHO', + decimals: 18, + priceFeed: '0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73', + ltv: '0', + liqThreshold: '0', + liqBonus: '0', + debtCeiling: '0', + liqProtocolFee: '0', + enabledToBorrow: 'ENABLED', + flashloanable: 'ENABLED', + borrowableInIsolation: 'DISABLED', + withSiloedBorrowing: 'DISABLED', + reserveFactor: '10', + supplyCap: '2500000', + borrowCap: '2250000', + rateStrategyParams: { + optimalUtilizationRate: '90', + baseVariableBorrowRate: '0', + variableRateSlope1: '12', + variableRateSlope2: '65', + }, + asset: '0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D', + admin: '0xac140648435d03f784879cd789130F22Ef588Fcd', + }, + ], + }, + cache: {blockNumber: 24430581}, + }, }, }; diff --git a/src/interfaces/IGhoOracle.sol b/src/interfaces/IGhoOracle.sol new file mode 100644 index 000000000..65d895d9b --- /dev/null +++ b/src/interfaces/IGhoOracle.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @title IGhoOracle + * @notice Price feed for GHO (USD denominated) + * @dev Price fixed at 1 USD, Chainlink format with 8 decimals + * @author Aave + */ +interface IGhoOracle { + /** + * @notice Returns the price of a unit of GHO (USD denominated) + * @dev GHO price is fixed at 1 USD + * @return The price of a unit of GHO (with 8 decimals) + */ + function latestAnswer() external view returns (int256); + + /** + * @notice Returns the number of decimals the price is formatted with + * @return The number of decimals + */ + function decimals() external view returns (uint8); +} From 1662f90e03f2d56ccbdfa7bb9afe1048e888ddea Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 21:04:57 +0530 Subject: [PATCH 077/123] feat: aave stewards test --- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 109 +++++++++++++++++- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 2 +- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index b38d30844..72b19b048 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -8,11 +8,13 @@ import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; +import {DataTypes, IDefaultInterestRateStrategyV2, IPoolAddressesProvider, IPool} from 'aave-address-book/AaveV3.sol'; import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoOracle} from 'src/interfaces/IGhoOracle.sol'; +import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {GovV3Helpers} from 'aave-helpers/src/GovV3Helpers.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; @@ -90,6 +92,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { vm.prank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO_TOKEN), GovernanceV3Base.EXECUTOR_LVL_1); } + function _deployNewBurnMintTokenPool( address ghoToken, address rmnProxy, @@ -122,6 +125,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { ) ); } + function _deployStewards() internal returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) @@ -130,14 +134,14 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { new GhoAaveSteward({ owner: GovernanceV3Base.EXECUTOR_LVL_1, addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), - poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), + poolDataProvider: address(AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER), ghoToken: address(GHO_TOKEN), riskCouncil: RISK_COUNCIL, borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ - optimalUsageRatioMaxChange: 500, - baseVariableBorrowRateMaxChange: 500, - variableRateSlope1MaxChange: 500, - variableRateSlope2MaxChange: 500 + optimalUsageRatioMaxChange: 50_00, + baseVariableBorrowRateMaxChange: 50_00, + variableRateSlope1MaxChange: 50_00, + variableRateSlope2MaxChange: 50_00 }) }) ); @@ -207,3 +211,98 @@ contract AaveV3Base_GHOBaseListing_20241223_Listing is AaveV3Base_GHOBaseListing ); } } + +contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListing_20241223_Base { + using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + + function setUp() public override { + super.setUp(); + + uint256 seedAmount = proposal.GHO_SEED_AMOUNT(); + // mock executor receives seed amount after Launch AIP (ie bridge activation) + vm.prank(address(NEW_TOKEN_POOL)); + GHO_TOKEN.mint(GovernanceV3Base.EXECUTOR_LVL_1, seedAmount); + + executePayload(vm, address(proposal)); + } + + function test_aaveStewardCanUpdateBorrowRate() public { + IDefaultInterestRateStrategyV2 irStrategy = IDefaultInterestRateStrategyV2( + AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER.getInterestRateStrategyAddress(address(GHO_TOKEN)) + ); + + IDefaultInterestRateStrategyV2.InterestRateData + memory currentRateData = IDefaultInterestRateStrategyV2.InterestRateData({ + optimalUsageRatio: 90_00, + baseVariableBorrowRate: 0, + variableRateSlope1: 12_00, + variableRateSlope2: 65_00 + }); + + assertEq( + irStrategy.getInterestRateDataBps(address(GHO_TOKEN)), + currentRateData, + 'currentRateData' + ); + + currentRateData.variableRateSlope1 -= 10_00; + currentRateData.variableRateSlope2 -= 42_00; + + vm.prank(RISK_COUNCIL); + NEW_GHO_AAVE_STEWARD.updateGhoBorrowRate( + currentRateData.optimalUsageRatio, + currentRateData.baseVariableBorrowRate, + currentRateData.variableRateSlope1, + currentRateData.variableRateSlope2 + ); + + assertEq(irStrategy.getInterestRateDataBps(address(GHO_TOKEN)), currentRateData); + } + + function test_aaveStewardCanUpdateBorrowCap(uint256 newBorrowCap) public { + uint256 currentBorrowCap = AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getBorrowCap(); + assertEq(currentBorrowCap, 2_250_000, 'currentBorrowCap'); + vm.assume( + newBorrowCap != currentBorrowCap && + _isDifferenceLowerThanMax(currentBorrowCap, newBorrowCap, currentBorrowCap) + ); + + vm.prank(RISK_COUNCIL); + NEW_GHO_AAVE_STEWARD.updateGhoBorrowCap(newBorrowCap); + + assertEq(AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getBorrowCap(), newBorrowCap); + } + + function test_aaveStewardCanUpdateSupplyCap(uint256 newSupplyCap) public { + uint256 currentSupplyCap = AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getSupplyCap(); + assertEq(currentSupplyCap, 2_500_000, 'currentSupplyCap'); + + vm.assume( + currentSupplyCap != newSupplyCap && + _isDifferenceLowerThanMax(currentSupplyCap, newSupplyCap, currentSupplyCap) + ); + + vm.prank(RISK_COUNCIL); + NEW_GHO_AAVE_STEWARD.updateGhoSupplyCap(newSupplyCap); + + assertEq(AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getSupplyCap(), newSupplyCap); + } + + function assertEq( + IDefaultInterestRateStrategyV2.InterestRateData memory a, + IDefaultInterestRateStrategyV2.InterestRateData memory b + ) internal { + assertEq(a.optimalUsageRatio, b.optimalUsageRatio, 'optimalUsageRatio'); + assertEq(a.baseVariableBorrowRate, b.baseVariableBorrowRate, 'baseVariableBorrowRate'); + assertEq(a.variableRateSlope1, b.variableRateSlope1, 'variableRateSlope1'); + assertEq(a.variableRateSlope2, b.variableRateSlope2, 'variableRateSlope2'); + } + + function _isDifferenceLowerThanMax( + uint256 from, + uint256 to, + uint256 max + ) internal pure returns (bool) { + return from < to ? to - from <= max : from - to <= max; + } +} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 9fdda37b4..69356eca5 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -359,7 +359,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { new GhoAaveSteward({ owner: GovernanceV3Base.EXECUTOR_LVL_1, addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), - poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), + poolDataProvider: address(AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER), ghoToken: address(GHO_TOKEN_BASE), riskCouncil: RISK_COUNCIL, borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ From 414c76efcf34e5b8d06883f446c86e9270ad5b95 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 21:06:09 +0530 Subject: [PATCH 078/123] chore: fix typo --- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 72b19b048..cc5a4f8f1 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -239,11 +239,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin variableRateSlope2: 65_00 }); - assertEq( - irStrategy.getInterestRateDataBps(address(GHO_TOKEN)), - currentRateData, - 'currentRateData' - ); + assertEq(irStrategy.getInterestRateDataBps(address(GHO_TOKEN)), currentRateData); currentRateData.variableRateSlope1 -= 10_00; currentRateData.variableRateSlope2 -= 42_00; From 9f4a2b0b0ba52dd720f899dea702ff2718802029 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 31 Dec 2024 21:08:06 +0530 Subject: [PATCH 079/123] chore: upd title --- src/20241223_Multi_GHOBaseLaunch/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index aee9d730b..b3b8e5c6e 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -2,7 +2,7 @@ import {ConfigFile} from '../../generator/types'; export const config: ConfigFile = { rootOptions: { pools: ['AaveV3Ethereum', 'AaveV3Arbitrum', 'AaveV3Base'], - title: 'GHO Base Launch', + title: 'Launch GHO on Base', shortName: 'GHOBaseLaunch', date: '20241223', author: 'Aave Labs', From bdd018371c4d2ac31fb3db62cf19bac714470439 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:22:06 +0530 Subject: [PATCH 080/123] feat: add deployed token pools & stewards --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 19 ++- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 65 ++-------- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 119 ++---------------- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 17 ++- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 68 ++-------- .../config.ts | 4 +- 6 files changed, 42 insertions(+), 250 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index e0ea59206..0691f0aac 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -32,17 +32,22 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://arbiscan.io/address/0xF168B83598516A532a85995b52504a2Fa058C068 IUpgradeableBurnMintTokenPool_1_4 public constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(GhoArbitrum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP - IUpgradeableBurnMintTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; + // https://arbiscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + IUpgradeableBurnMintTokenPool_1_5_1 public constant NEW_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); - address public immutable NEW_GHO_CCIP_STEWARD; + // https://arbiscan.io/address/0xFAdC082665577b533e62A7B0E067f884cA5C5E8F + address public constant NEW_GHO_CCIP_STEWARD = 0xFAdC082665577b533e62A7B0E067f884cA5C5E8F; // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH - address public immutable NEW_REMOTE_POOL_ETH; + // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + address public constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; // https://arbiscan.io/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A + // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb address public constant EXISTING_TOKEN_POOL_UPGRADE_IMPL = - 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb + 0xA5Ba213867E175A182a5dd6A9193C6158738105A; // https://arbiscan.io/address/0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33 IGhoToken public constant GHO = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); @@ -52,12 +57,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; - constructor(address newTokenPoolArb, address newTokenPoolEth, address newGhoCcipSteward) { - NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); - NEW_REMOTE_POOL_ETH = newTokenPoolEth; - NEW_GHO_CCIP_STEWARD = newGhoCcipSteward; - } - function execute() external { _acceptOwnership(); _migrateLiquidity(); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 6664cadf3..ab9dd133a 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -21,15 +21,9 @@ import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; - import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; @@ -61,17 +55,19 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); - IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = + IGhoCcipSteward(0xFAdC082665577b533e62A7B0E067f884cA5C5E8F); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // GhoArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP - IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; + IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; - address internal NEW_REMOTE_POOL_ETH = makeAddr('LockReleaseTokenPool 1.5.1'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -81,14 +77,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 288070365); - NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); - NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); - proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ETH, - address(NEW_GHO_CCIP_STEWARD) - ); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 291207768); + proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry address CLL_OWNER = TOKEN_ADMIN_REGISTRY.owner(); @@ -100,47 +90,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { _validateConstants(); } - function _deployNewTokenPoolArb() private returns (address) { - IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( - GhoArbitrum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - existingTokenPool.getToken(), - IGhoToken(existingTokenPool.getToken()).decimals(), - existingTokenPool.getArmProxy(), - existingTokenPool.getAllowListEnabled() - ) - ); - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(MiscArbitrum.PROXY_ADMIN), - abi.encodeCall( - IUpgradeableBurnMintTokenPool_1_5_1.initialize, - ( - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner - existingTokenPool.getAllowList(), - existingTokenPool.getRouter() - ) - ) - ) - ); - } - - function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { - return - address( - new GhoCcipSteward( - address(GHO), - newTokenPool, - EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL(), - false // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool - ) - ); - } - function _validateConstants() private view { assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 2da12095e..cb341165f 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -18,19 +18,11 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; -import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; -import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; - import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; @@ -96,36 +88,17 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21366260); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21536364); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291207768); vm.selectFork(l1.c.forkId); - address newTokenPoolEth = _deployNewTokenPoolEth(); - address newGhoCcipStewardEth = _deployNewGhoCcipSteward( - newTokenPoolEth, - AaveV3EthereumAssets.GHO_UNDERLYING, - GovernanceV3Ethereum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience - true // bridgeLimitEnabled - ); - vm.selectFork(l2.c.forkId); - address newTokenPoolArb = _deployNewTokenPoolArb(); - address newGhoCcipStewardArb = _deployNewGhoCcipSteward( - newTokenPoolArb, - AaveV3ArbitrumAssets.GHO_UNDERLYING, - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // riskAdmin, set as executor for convenience - false // bridgeLimitEnabled - ); - - vm.selectFork(l1.c.forkId); - l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( - newTokenPoolEth, - newTokenPoolArb, - newGhoCcipStewardEth - ); + l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); l1.existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( 0x5756880B6a1EAba0175227bf02a7E87c1e02B28C ); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP - l1.newTokenPool = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); + l1.newTokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( + 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + ); l1.c.router = IRouter(l1.existingTokenPool.getRouter()); l2.c.chainSelector = l1.existingTokenPool.getSupportedChains()[0]; l1.c.token = IGhoToken(address(l1.existingTokenPool.getToken())); @@ -136,15 +109,13 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { l1.c.proxyPool = l1.existingTokenPool.getProxyPool(); vm.selectFork(l2.c.forkId); - l2.proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( - newTokenPoolArb, - newTokenPoolEth, - newGhoCcipStewardArb - ); + l2.proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); l2.existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( 0xF168B83598516A532a85995b52504a2Fa058C068 ); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP - l2.newTokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); + l2.newTokenPool = IUpgradeableBurnMintTokenPool_1_5_1( + 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + ); l2.c.router = IRouter(l2.existingTokenPool.getRouter()); l1.c.chainSelector = l2.existingTokenPool.getSupportedChains()[0]; l2.c.token = IGhoToken(address(l2.existingTokenPool.getToken())); @@ -312,76 +283,6 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { vm.stopPrank(); } - function _deployNewTokenPoolEth() private returns (address) { - IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( - GhoEthereum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolImpl = address( - new UpgradeableLockReleaseTokenPool( - existingTokenPool.getToken(), - IGhoToken(existingTokenPool.getToken()).decimals(), - existingTokenPool.getArmProxy(), - existingTokenPool.getAllowListEnabled(), - existingTokenPool.canAcceptLiquidity() - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(MiscEthereum.PROXY_ADMIN), - abi.encodeCall( - IUpgradeableLockReleaseTokenPool_1_5_1.initialize, - ( - GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner - existingTokenPool.getAllowList(), - existingTokenPool.getRouter(), - existingTokenPool.getBridgeLimit() - ) - ) - ) - ); - } - - function _deployNewTokenPoolArb() private returns (address) { - IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( - GhoArbitrum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - existingTokenPool.getToken(), - IGhoToken(existingTokenPool.getToken()).decimals(), - existingTokenPool.getArmProxy(), - existingTokenPool.getAllowListEnabled() - ) - ); - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(MiscArbitrum.PROXY_ADMIN), - abi.encodeCall( - IUpgradeableBurnMintTokenPool_1_5_1.initialize, - ( - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner - existingTokenPool.getAllowList(), - existingTokenPool.getRouter() - ) - ) - ) - ); - } - - function _deployNewGhoCcipSteward( - address newTokenPool, - address ghoToken, - address riskCouncil, - bool bridgeLimitEnabled - ) internal returns (address) { - return address(new GhoCcipSteward(ghoToken, newTokenPool, riskCouncil, bridgeLimitEnabled)); - } - function _getOutboundRefillTime(uint256 amount) internal pure returns (uint256) { return (amount / CCIP_RATE_LIMIT_REFILL_RATE) + 1; // account for rounding } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 4c3299f1b..4707e2981 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -28,25 +28,22 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://etherscan.io/address/0x5756880B6a1EAba0175227bf02a7E87c1e02B28C IUpgradeableLockReleaseTokenPool_1_4 public constant EXISTING_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_4(GhoEthereum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP - IUpgradeableLockReleaseTokenPool_1_5_1 public immutable NEW_TOKEN_POOL; - - address public immutable NEW_GHO_CCIP_STEWARD; + // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + IUpgradeableLockReleaseTokenPool_1_5_1 public constant NEW_TOKEN_POOL = + IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + // https://etherscan.io/address/0xFAdC082665577b533e62A7B0E067f884cA5C5E8F + address public constant NEW_GHO_CCIP_STEWARD = 0xFAdC082665577b533e62A7B0E067f884cA5C5E8F; // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb - address public immutable NEW_REMOTE_POOL_ARB; + // https://arbiscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + address public constant NEW_REMOTE_POOL_ARB = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; - constructor(address newTokenPoolEth, address newTokenPoolArb, address newGhoCcipSteward) { - NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); - NEW_REMOTE_POOL_ARB = newTokenPoolArb; - NEW_GHO_CCIP_STEWARD = newGhoCcipSteward; - } - function execute() external { _acceptOwnership(); _migrateLiquidity(); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index dcc6b3007..26e02c233 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -20,17 +20,11 @@ import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; - import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; @@ -62,17 +56,19 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); - IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = + IGhoCcipSteward(0xFAdC082665577b533e62A7B0E067f884cA5C5E8F); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x9Ec9F9804733df96D1641666818eFb5198eC50f0); IUpgradeableLockReleaseTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // GhoEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP - IUpgradeableLockReleaseTokenPool_1_5_1 internal NEW_TOKEN_POOL; + IUpgradeableLockReleaseTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = + IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + address internal constant NEW_REMOTE_POOL_ARB = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; - address internal NEW_REMOTE_POOL_ARB = makeAddr('BurnMintTokenPool 1.5.1'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -84,14 +80,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { error BridgeLimitExceeded(uint256 limit); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21366260); - NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(_deployNewTokenPoolEth()); - NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); - proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ARB, - address(NEW_GHO_CCIP_STEWARD) - ); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21536364); + proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry address CLL_OWNER = TOKEN_ADMIN_REGISTRY.owner(); @@ -103,50 +93,6 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { _validateConstants(); } - function _deployNewTokenPoolEth() private returns (address) { - IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( - GhoEthereum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolImpl = address( - new UpgradeableLockReleaseTokenPool( - existingTokenPool.getToken(), - IGhoToken(existingTokenPool.getToken()).decimals(), - existingTokenPool.getArmProxy(), - existingTokenPool.getAllowListEnabled(), - existingTokenPool.canAcceptLiquidity() - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(MiscEthereum.PROXY_ADMIN), - abi.encodeCall( - IUpgradeableLockReleaseTokenPool_1_5_1.initialize, - ( - GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner - existingTokenPool.getAllowList(), - existingTokenPool.getRouter(), - existingTokenPool.getBridgeLimit() - ) - ) - ) - ); - } - - function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { - return - address( - new GhoCcipSteward( - address(GHO), - newTokenPool, - EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL(), - true // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool - ) - ); - } - function _validateConstants() private view { assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index 15ad2de6e..56a654c22 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21366260}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21536364}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291207768}}, }, }; From 07c77156ae05c9dd451f38988de569263fde83e9 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:33:02 +0530 Subject: [PATCH 081/123] feat: rm `gho-core` & `ccip` --- .gitmodules | 7 ------- lib/ccip | 1 - lib/gho-core | 1 - remappings.txt | 11 +---------- 4 files changed, 1 insertion(+), 19 deletions(-) delete mode 160000 lib/ccip delete mode 160000 lib/gho-core diff --git a/.gitmodules b/.gitmodules index ad4e901de..f7316a1d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,3 @@ [submodule "lib/aave-helpers"] path = lib/aave-helpers url = https://github.com/bgd-labs/aave-helpers -[submodule "lib/ccip"] - path = lib/ccip - url = https://github.com/aave/ccip - branch = feat/1_5_1_token_pool -[submodule "lib/gho-core"] - path = lib/gho-core - url = https://github.com/aave/gho-core diff --git a/lib/ccip b/lib/ccip deleted file mode 160000 index ca12f6398..000000000 --- a/lib/ccip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ca12f6398157d7a0526bc3f153d69566884d9dd0 diff --git a/lib/gho-core b/lib/gho-core deleted file mode 160000 index 0a6fbd4d4..000000000 --- a/lib/gho-core +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0a6fbd4d4167f6e0e777aec0ae12bf4f18b4b0a8 diff --git a/remappings.txt b/remappings.txt index 9c8cea061..9fefc7eea 100644 --- a/remappings.txt +++ b/remappings.txt @@ -2,13 +2,4 @@ aave-address-book/=lib/aave-helpers/lib/aave-address-book/src/ 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/ -@openzeppelin/contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/ -@openzeppelin/contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ -aave-v3-origin-tests/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/tests/ -ds-test/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/ -erc4626-tests/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ -openzeppelin-contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/ -openzeppelin-contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/ -aave-ccip/=lib/ccip/contracts/src/v0.8/ccip -gho-core/=lib/gho-core/src/contracts +solidity-utils/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/src From 0947d4e25b3e2cb0e2f4880ec40b6abf391e63b4 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:43:55 +0530 Subject: [PATCH 082/123] feat: upd arb token pool & steward deployment --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 8 ++++---- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 6 +++--- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- src/20241209_Multi_GHOCCIP151Upgrade/config.ts | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 0691f0aac..57af3256a 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -32,12 +32,12 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://arbiscan.io/address/0xF168B83598516A532a85995b52504a2Fa058C068 IUpgradeableBurnMintTokenPool_1_4 public constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(GhoArbitrum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP - // https://arbiscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee IUpgradeableBurnMintTokenPool_1_5_1 public constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); - // https://arbiscan.io/address/0xFAdC082665577b533e62A7B0E067f884cA5C5E8F - address public constant NEW_GHO_CCIP_STEWARD = 0xFAdC082665577b533e62A7B0E067f884cA5C5E8F; + // https://arbiscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A + address public constant NEW_GHO_CCIP_STEWARD = 0x06179f7C1be40863405f374E7f5F8806c728660A; // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index ab9dd133a..32d8cc744 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -56,14 +56,14 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0xFAdC082665577b533e62A7B0E067f884cA5C5E8F); + IGhoCcipSteward(0x06179f7C1be40863405f374E7f5F8806c728660A); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // GhoArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; @@ -77,7 +77,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 291207768); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 291243768); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index cb341165f..e15cfc6e8 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -89,7 +89,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function setUp() public virtual { l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21536364); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291207768); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291243768); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); @@ -114,7 +114,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { 0xF168B83598516A532a85995b52504a2Fa058C068 ); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP l2.newTokenPool = IUpgradeableBurnMintTokenPool_1_5_1( - 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee ); l2.c.router = IRouter(l2.existingTokenPool.getRouter()); l1.c.chainSelector = l2.existingTokenPool.getSupportedChains()[0]; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 4707e2981..deacd8b51 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -36,8 +36,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb - // https://arbiscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 - address public constant NEW_REMOTE_POOL_ARB = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + address public constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 26e02c233..f3b6504d5 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -65,7 +65,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // GhoEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); - address internal constant NEW_REMOTE_POOL_ARB = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index 56a654c22..2b8682e45 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -12,6 +12,6 @@ export const config: ConfigFile = { }, poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21536364}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291207768}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291243768}}, }, }; From dc42f10a3524ed9e3daf0b564813817c6c8a2ff6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:50:36 +0530 Subject: [PATCH 083/123] feat: use deployed base token pool & stewards --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 14 +- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 82 +----- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 41 +-- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 129 ++-------- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 144 ++--------- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 238 ++---------------- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 14 +- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 83 +----- src/20241223_Multi_GHOBaseLaunch/config.ts | 6 +- 9 files changed, 110 insertions(+), 641 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index fdff5f797..468294b73 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -14,11 +14,12 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; - // https://arbiscan.io/address/ - IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; + // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); - // https://basescan.org/address/ - address public immutable REMOTE_TOKEN_POOL_BASE; + // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E + address public constant REMOTE_TOKEN_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted @@ -27,11 +28,6 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; - constructor(address tokenPoolArb, address tokenPoolBase) { - TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPoolArb); - REMOTE_TOKEN_POOL_BASE = tokenPoolBase; - } - function execute() external { IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ isEnabled: true, diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 83d21aff2..2aba37586 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; @@ -19,15 +19,8 @@ import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; - import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; @@ -57,24 +50,23 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOnRamp(0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3); IEVM2EVMOnRamp internal constant BASE_ON_RAMP = IEVM2EVMOnRamp(0xc1b6287A3292d6469F2D8545877E40A2f75CA9a6); - IEVM2EVMOffRamp_1_5 internal constant ETH_OFF_RAMP = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); - address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; - IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); + address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted - - IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; - - IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; + IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); + IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = + IGhoCcipSteward(0x06179f7C1be40863405f374E7f5F8806c728660A); + IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + address internal constant NEW_REMOTE_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; AaveV3Arbitrum_GHOBaseLaunch_20241223 internal proposal; - address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); - address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: BurnMintTokenPool 1.5.1'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -87,14 +79,9 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 288070365); - NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(_deployNewTokenPoolArb()); - NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 291243768); _upgradeArbTo1_5_1(); - proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_BASE - ); + proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); _validateConstants(); @@ -103,11 +90,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { } function _upgradeArbTo1_5_1() internal { - AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ETH, - address(NEW_GHO_CCIP_STEWARD) - ); + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1); upgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); @@ -116,47 +99,6 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { executePayload(vm, address(upgradeProposal)); } - function _deployNewTokenPoolArb() private returns (address) { - IUpgradeableBurnMintTokenPool_1_4 existingTokenPool = IUpgradeableBurnMintTokenPool_1_4( - GhoArbitrum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - existingTokenPool.getToken(), - IGhoToken(existingTokenPool.getToken()).decimals(), - existingTokenPool.getArmProxy(), - existingTokenPool.getAllowListEnabled() - ) - ); - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(MiscArbitrum.PROXY_ADMIN), - abi.encodeCall( - IUpgradeableBurnMintTokenPool_1_5_1.initialize, - ( - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner - existingTokenPool.getAllowList(), - existingTokenPool.getRouter() - ) - ) - ) - ); - } - - function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { - return - address( - new GhoCcipSteward( - address(GHO), - newTokenPool, - RISK_COUNCIL, - false // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool - ) - ); - } - function _validateConstants() private view { assertEq(proposal.BASE_CHAIN_SELECTOR(), BASE_CHAIN_SELECTOR); assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 0abd4a9b3..0dac6e736 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -32,47 +32,32 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://basescan.org/address/0x6f6C373d09C07425BaAE72317863d7F6bb731e37 ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); - // https://basescan.org/address/ - IUpgradeableBurnMintTokenPool_1_5_1 public immutable TOKEN_POOL; + // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E + IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); // https://basescan.org/address/0x26d595dddbad81bf976ef6f24686a12a800b141f address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; // predicted address, will be deployed in the AIP, https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); - // https://basescan.org/address/ - address public immutable GHO_AAVE_STEWARD; - // https://basescan.org/address/ - address public immutable GHO_BUCKET_STEWARD; - // https://basescan.org/address/ - address public immutable GHO_CCIP_STEWARD; + // https://basescan.org/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + address public constant GHO_AAVE_STEWARD = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + // https://basescan.org/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A + address public constant GHO_BUCKET_STEWARD = 0xA5Ba213867E175A182a5dd6A9193C6158738105A; + // https://basescan.org/address/0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B + address public constant GHO_CCIP_STEWARD = 0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B; - // https://etherscan.io/address/ - address public immutable REMOTE_TOKEN_POOL_ETH; - // https://arbiscan.io/address/ - address public immutable REMOTE_TOKEN_POOL_ARB; + // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + address public constant REMOTE_TOKEN_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + address public constant REMOTE_TOKEN_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; - constructor( - address tokenPool, - address tokenPoolEth, - address tokenPoolArb, - address ghoAaveSteward, - address ghoBucketSteward, - address ghoCcipSteward - ) { - TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(tokenPool); - REMOTE_TOKEN_POOL_ETH = tokenPoolEth; - REMOTE_TOKEN_POOL_ARB = tokenPoolArb; - GHO_AAVE_STEWARD = ghoAaveSteward; - GHO_BUCKET_STEWARD = ghoBucketSteward; - GHO_CCIP_STEWARD = ghoCcipSteward; - } - function execute() external { _acceptOwnership(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 60050356b..f725e6b33 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -14,9 +14,9 @@ import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IOwnable} from 'src/interfaces/IOwnable.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; -import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; -import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; +import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; +import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -27,11 +27,6 @@ import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {GhoAaveSteward} from 'gho-core/misc/GhoAaveSteward.sol'; -import {GhoBucketSteward} from 'gho-core/misc/GhoBucketSteward.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; @@ -73,15 +68,19 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IGhoToken internal constant GHO = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; - IGhoAaveSteward internal NEW_GHO_AAVE_STEWARD; - IGhoBucketSteward internal NEW_GHO_BUCKET_STEWARD; - IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; + IGhoAaveSteward internal constant NEW_GHO_AAVE_STEWARD = + IGhoAaveSteward(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = + IGhoBucketSteward(0xA5Ba213867E175A182a5dd6A9193C6158738105A); + IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = + IGhoCcipSteward(0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B); + IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); + address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; - IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; AaveV3Base_GHOBaseLaunch_20241223 internal proposal; - address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); - address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -94,27 +93,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24430581); - - NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( - _deployNewBurnMintTokenPool( - address(GHO), - RMN_PROXY, - address(ROUTER), - GovernanceV3Base.EXECUTOR_LVL_1, // owner - MiscBase.PROXY_ADMIN - ) - ); - (NEW_GHO_AAVE_STEWARD, NEW_GHO_BUCKET_STEWARD, NEW_GHO_CCIP_STEWARD) = _deployStewards(); - - proposal = new AaveV3Base_GHOBaseLaunch_20241223( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ETH, - NEW_REMOTE_POOL_ARB, - address(NEW_GHO_AAVE_STEWARD), - address(NEW_GHO_BUCKET_STEWARD), - address(NEW_GHO_CCIP_STEWARD) - ); + vm.createSelectFork(vm.rpcUrl('base'), 24519153); + proposal = new AaveV3Base_GHOBaseLaunch_20241223(); _performCcipPreReq(); _validateConstants(); @@ -125,80 +105,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO), GovernanceV3Base.EXECUTOR_LVL_1); } - function _deployNewBurnMintTokenPool( - address ghoToken, - address rmnProxy, - address router, - address owner, - address proxyAdmin - ) private returns (address) { - address newTokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - ghoToken, - 18, - rmnProxy, - false // allowListEnabled - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(proxyAdmin), - abi.encodeCall( - IUpgradeableBurnMintTokenPool_1_5_1.initialize, - ( - owner, - new address[](0), // allowList - router - ) - ) - ) - ); - } - - function _deployStewards() - internal - returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) - { - address aaveSteward = address( - new GhoAaveSteward({ - owner: GovernanceV3Base.EXECUTOR_LVL_1, - addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), - poolDataProvider: address(AaveV3Base.UI_POOL_DATA_PROVIDER), - ghoToken: address(GHO), - riskCouncil: RISK_COUNCIL, - borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ - optimalUsageRatioMaxChange: 500, - baseVariableBorrowRateMaxChange: 500, - variableRateSlope1MaxChange: 500, - variableRateSlope2MaxChange: 500 - }) - }) - ); - address bucketSteward = address( - new GhoBucketSteward({ - owner: GovernanceV3Base.EXECUTOR_LVL_1, - ghoToken: address(GHO), - riskCouncil: RISK_COUNCIL - }) - ); - address ccipSteward = address( - new GhoCcipSteward({ - ghoToken: address(GHO), - ghoTokenPool: address(NEW_TOKEN_POOL), - riskCouncil: RISK_COUNCIL, - bridgeLimitEnabled: false - }) - ); - return ( - IGhoAaveSteward(aaveSteward), - IGhoBucketSteward(bucketSteward), - IGhoCcipSteward(ccipSteward) - ); - } - function _validateConstants() private view { assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); @@ -402,7 +308,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau NEW_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER(), address(AaveV3Base.POOL_ADDRESSES_PROVIDER) ); - assertEq(NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), address(AaveV3Base.UI_POOL_DATA_PROVIDER)); + assertEq( + NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), + address(AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER) + ); assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); IGhoAaveSteward.BorrowRateConfig memory config = NEW_GHO_AAVE_STEWARD.getBorrowRateConfig(); assertEq(config.optimalUsageRatioMaxChange, 500); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index cc5a4f8f1..b7600f25c 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -5,12 +5,12 @@ import 'forge-std/Test.sol'; import {IEmissionManager} from 'aave-v3-origin/contracts/rewards/interfaces/IEmissionManager.sol'; import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; -import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; -import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; -import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; -import {DataTypes, IDefaultInterestRateStrategyV2, IPoolAddressesProvider, IPool} from 'aave-address-book/AaveV3.sol'; +import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; +import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoOracle} from 'src/interfaces/IGhoOracle.sol'; @@ -18,16 +18,8 @@ import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/ import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {GovV3Helpers} from 'aave-helpers/src/GovV3Helpers.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; -import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.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/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {GhoAaveSteward} from 'gho-core/misc/GhoAaveSteward.sol'; -import {GhoBucketSteward} from 'gho-core/misc/GhoBucketSteward.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; - import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; import {AaveV3Base_GHOBaseListing_20241223} from './AaveV3Base_GHOBaseListing_20241223.sol'; @@ -44,127 +36,29 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; IGhoToken internal constant GHO_TOKEN = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP - - address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); - address internal NEW_REMOTE_POOL_ETH = makeAddr('ETH: LockReleaseTokenPool 1.5.1'); - IGhoAaveSteward internal NEW_GHO_AAVE_STEWARD; - IGhoBucketSteward internal NEW_GHO_BUCKET_STEWARD; - IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; - IUpgradeableBurnMintTokenPool_1_5_1 internal NEW_TOKEN_POOL; + address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + IGhoAaveSteward internal constant NEW_GHO_AAVE_STEWARD = + IGhoAaveSteward(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = + IGhoBucketSteward(0xA5Ba213867E175A182a5dd6A9193C6158738105A); + IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = + IGhoCcipSteward(0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B); + IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = + IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24430581); + vm.createSelectFork(vm.rpcUrl('base'), 24519153); _executeLaunchAIP(); // deploys gho token, token pool & stewards proposal = new AaveV3Base_GHOBaseListing_20241223(); } function _executeLaunchAIP() internal { - NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1( - _deployNewBurnMintTokenPool( - address(GHO_TOKEN), - RMN_PROXY, - ROUTER, - GovernanceV3Base.EXECUTOR_LVL_1, // owner - MiscBase.PROXY_ADMIN - ) - ); - (NEW_GHO_AAVE_STEWARD, NEW_GHO_BUCKET_STEWARD, NEW_GHO_CCIP_STEWARD) = _deployStewards(); - - _performCcipPreReq(); - - executePayload( - vm, - address( - new AaveV3Base_GHOBaseLaunch_20241223( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ETH, - NEW_REMOTE_POOL_ARB, - address(NEW_GHO_AAVE_STEWARD), - address(NEW_GHO_BUCKET_STEWARD), - address(NEW_GHO_CCIP_STEWARD) - ) - ) - ); - } - - function _performCcipPreReq() internal { + // CLL pre-requisite vm.prank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO_TOKEN), GovernanceV3Base.EXECUTOR_LVL_1); - } - - function _deployNewBurnMintTokenPool( - address ghoToken, - address rmnProxy, - address router, - address owner, - address proxyAdmin - ) private returns (address) { - address newTokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - ghoToken, - 18, - rmnProxy, - false // allowListEnabled - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(proxyAdmin), - abi.encodeCall( - IUpgradeableBurnMintTokenPool_1_5_1.initialize, - ( - owner, - new address[](0), // allowList - router - ) - ) - ) - ); - } - - function _deployStewards() - internal - returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) - { - address aaveSteward = address( - new GhoAaveSteward({ - owner: GovernanceV3Base.EXECUTOR_LVL_1, - addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), - poolDataProvider: address(AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER), - ghoToken: address(GHO_TOKEN), - riskCouncil: RISK_COUNCIL, - borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ - optimalUsageRatioMaxChange: 50_00, - baseVariableBorrowRateMaxChange: 50_00, - variableRateSlope1MaxChange: 50_00, - variableRateSlope2MaxChange: 50_00 - }) - }) - ); - address bucketSteward = address( - new GhoBucketSteward({ - owner: GovernanceV3Base.EXECUTOR_LVL_1, - ghoToken: address(GHO_TOKEN), - riskCouncil: RISK_COUNCIL - }) - ); - address ccipSteward = address( - new GhoCcipSteward({ - ghoToken: address(GHO_TOKEN), - ghoTokenPool: address(NEW_TOKEN_POOL), - riskCouncil: RISK_COUNCIL, - bridgeLimitEnabled: false - }) - ); - return ( - IGhoAaveSteward(aaveSteward), - IGhoBucketSteward(bucketSteward), - IGhoCcipSteward(ccipSteward) - ); + executePayload(vm, address(new AaveV3Base_GHOBaseLaunch_20241223())); } } @@ -241,8 +135,8 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin assertEq(irStrategy.getInterestRateDataBps(address(GHO_TOKEN)), currentRateData); - currentRateData.variableRateSlope1 -= 10_00; - currentRateData.variableRateSlope2 -= 42_00; + currentRateData.variableRateSlope1 -= 4_00; + currentRateData.variableRateSlope2 -= 3_00; vm.prank(RISK_COUNCIL); NEW_GHO_AAVE_STEWARD.updateGhoBorrowRate( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 69356eca5..8466cef90 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -5,8 +5,8 @@ import 'forge-std/Test.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; -import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; -import {IUpgradeableBurnMintTokenPool_1_4, IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; +import {IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; @@ -16,29 +16,18 @@ import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IPriceRegistry} from 'src/interfaces/ccip/IPriceRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; -import {IGhoAaveSteward} from 'gho-core/misc/interfaces/IGhoAaveSteward.sol'; -import {IGhoBucketSteward} from 'gho-core/misc/interfaces/IGhoBucketSteward.sol'; -import {IGhoCcipSteward} from 'gho-core/misc/interfaces/IGhoCcipSteward.sol'; +import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; +import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; +import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; -import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; -import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {MiscBase} from 'aave-address-book/MiscBase.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; -import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; -import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {UpgradeableBurnMintTokenPool} from 'aave-ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol'; -import {GhoAaveSteward} from 'gho-core/misc/GhoAaveSteward.sol'; -import {GhoBucketSteward} from 'gho-core/misc/GhoBucketSteward.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -120,35 +109,23 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 288070365); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24430581); - eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21463360); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291243768); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24519153); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21536364); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); eth.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); eth.c.token = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); - (address newTokenPoolEth, address newTokenPoolArb) = _upgradeEthArbTo1_5_1(); + _upgradeEthArbTo1_5_1(); arb.c.chainSelector = 4949039107694359620; base.c.chainSelector = 15971525489660198786; eth.c.chainSelector = 5009297550715157269; - vm.selectFork(base.c.forkId); - address newTokenPoolBase = _deployNewBurnMintTokenPool( - address(GHO_TOKEN_BASE), - RMN_PROXY_BASE, - ROUTER_BASE, - GovernanceV3Base.EXECUTOR_LVL_1, // owner - MiscBase.PROXY_ADMIN - ); - (GHO_AAVE_STEWARD_BASE, GHO_BUCKET_STEWARD_BASE, GHO_CCIP_STEWARD_BASE) = _deployStewardsBase( - newTokenPoolBase - ); - vm.selectFork(arb.c.forkId); - arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(newTokenPoolArb, newTokenPoolBase); - arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolArb); + arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); + arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); arb.c.router = IRouter(arb.tokenPool.getRouter()); arb.c.baseOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(base.c.chainSelector)); arb.c.ethOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(eth.c.chainSelector)); @@ -156,15 +133,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { arb.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); vm.selectFork(base.c.forkId); - base.proposal = new AaveV3Base_GHOBaseLaunch_20241223( - newTokenPoolBase, - newTokenPoolEth, - newTokenPoolArb, - address(GHO_AAVE_STEWARD_BASE), - address(GHO_BUCKET_STEWARD_BASE), - address(GHO_CCIP_STEWARD_BASE) + base.proposal = new AaveV3Base_GHOBaseLaunch_20241223(); + base.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1( + 0xDe6539018B095353A40753Dc54C91C68c9487D4E ); - base.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(newTokenPoolBase); base.c.tokenAdminRegistry = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); base.c.token = GHO_TOKEN_BASE; base.c.router = IRouter(base.tokenPool.getRouter()); @@ -174,8 +146,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { base.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0xCA04169671A81E4fB8768cfaD46c347ae65371F1); vm.selectFork(eth.c.forkId); - eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(newTokenPoolEth, newTokenPoolBase); - eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1(newTokenPoolEth); + eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); + eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( + 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + ); eth.c.router = IRouter(eth.tokenPool.getRouter()); eth.c.arbOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(arb.c.chainSelector)); eth.c.baseOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(base.c.chainSelector)); @@ -188,70 +162,22 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { } function _upgradeEthArbTo1_5_1() internal returns (address, address) { - // deploy new token pools and ghoCcipStewards vm.selectFork(eth.c.forkId); - IUpgradeableLockReleaseTokenPool_1_4 existingPoolEth = IUpgradeableLockReleaseTokenPool_1_4( - GhoEthereum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolEth = _deployNewLockReleaseTokenPool( - AaveV3EthereumAssets.GHO_UNDERLYING, - existingPoolEth.getArmProxy(), - existingPoolEth.getRouter(), - existingPoolEth.getBridgeLimit(), - GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner - MiscEthereum.PROXY_ADMIN - ); - address newGhoCcipStewardEth = address( - new GhoCcipSteward({ - ghoTokenPool: newTokenPoolEth, - ghoToken: AaveV3EthereumAssets.GHO_UNDERLYING, - riskCouncil: RISK_COUNCIL, - bridgeLimitEnabled: true - }) - ); - - vm.selectFork(arb.c.forkId); - IUpgradeableBurnMintTokenPool_1_4 existingPoolArb = IUpgradeableBurnMintTokenPool_1_4( - GhoArbitrum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolArb = _deployNewBurnMintTokenPool( - AaveV3ArbitrumAssets.GHO_UNDERLYING, - existingPoolArb.getArmProxy(), - existingPoolArb.getRouter(), - GovernanceV3Arbitrum.EXECUTOR_LVL_1, // owner - MiscArbitrum.PROXY_ADMIN - ); - address newGhoCcipStewardArb = address( - new GhoCcipSteward({ - ghoTokenPool: newTokenPoolArb, - ghoToken: AaveV3ArbitrumAssets.GHO_UNDERLYING, - riskCouncil: RISK_COUNCIL, - bridgeLimitEnabled: false - }) - ); - // execute CLL pre-requisites for the proposal - vm.selectFork(eth.c.forkId); - AaveV3Ethereum_GHOCCIP151Upgrade_20241209 ethUpgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( - newTokenPoolEth, - newTokenPoolArb, - newGhoCcipStewardEth - ); vm.startPrank(eth.c.tokenAdminRegistry.owner()); + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 ethUpgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); ethUpgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); eth.c.tokenAdminRegistry.transferAdminRole( address(eth.c.token), GovernanceV3Ethereum.EXECUTOR_LVL_1 ); vm.stopPrank(); + executePayload(vm, address(ethUpgradeProposal)); vm.selectFork(arb.c.forkId); - AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 arbUpgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209( - newTokenPoolArb, - newTokenPoolEth, - newGhoCcipStewardArb - ); + // execute CLL pre-requisites for the proposal + AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 arbUpgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); vm.startPrank(arb.c.tokenAdminRegistry.owner()); arbUpgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); arb.c.tokenAdminRegistry.transferAdminRole( @@ -259,86 +185,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { GovernanceV3Arbitrum.EXECUTOR_LVL_1 ); vm.stopPrank(); - - // execute proposal - { - vm.selectFork(eth.c.forkId); - executePayload(vm, address(ethUpgradeProposal)); - - vm.selectFork(arb.c.forkId); - executePayload(vm, address(arbUpgradeProposal)); - } - - return (newTokenPoolEth, newTokenPoolArb); - } - - function _deployNewBurnMintTokenPool( - address ghoToken, - address rmnProxy, - address router, - address owner, - address proxyAdmin - ) private returns (address) { - address newTokenPoolImpl = address( - new UpgradeableBurnMintTokenPool( - ghoToken, - 18, // optimistic token deployment for base, hence hardcoding 18 decimals for ghoToken - rmnProxy, - false // allowListEnabled - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(proxyAdmin), - abi.encodeCall( - IUpgradeableBurnMintTokenPool_1_5_1.initialize, - ( - owner, - new address[](0), // allowList - router - ) - ) - ) - ); - } - - function _deployNewLockReleaseTokenPool( - address ghoToken, - address rmnProxy, - address router, - uint256 bridgeLimit, - address owner, - address proxyAdmin - ) private returns (address) { - address newTokenPoolImpl = address( - new UpgradeableLockReleaseTokenPool( - ghoToken, - 18, // optimistic token deployment for base, hence hardcoding 18 decimals for ghoToken - rmnProxy, - false, // allowListEnabled - true // acceptLiquidity - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(proxyAdmin), - abi.encodeCall( - IUpgradeableLockReleaseTokenPool_1_5_1.initialize, - ( - owner, - new address[](0), // allowList - router, - bridgeLimit - ) - ) - ) - ); + executePayload(vm, address(arbUpgradeProposal)); } function _performCLLPreReq(Common memory c, address newAdmin) internal { @@ -352,45 +199,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { } } - function _deployStewardsBase( - address ghoTokenPool - ) internal returns (IGhoAaveSteward, IGhoBucketSteward, IGhoCcipSteward) { - address aaveSteward = address( - new GhoAaveSteward({ - owner: GovernanceV3Base.EXECUTOR_LVL_1, - addressesProvider: address(AaveV3Base.POOL_ADDRESSES_PROVIDER), - poolDataProvider: address(AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER), - ghoToken: address(GHO_TOKEN_BASE), - riskCouncil: RISK_COUNCIL, - borrowRateConfig: IGhoAaveSteward.BorrowRateConfig({ - optimalUsageRatioMaxChange: 500, - baseVariableBorrowRateMaxChange: 500, - variableRateSlope1MaxChange: 500, - variableRateSlope2MaxChange: 500 - }) - }) - ); - address bucketSteward = address( - new GhoBucketSteward({ - owner: GovernanceV3Base.EXECUTOR_LVL_1, - ghoToken: address(GHO_TOKEN_BASE), - riskCouncil: RISK_COUNCIL - }) - ); - address ccipSteward = address( - new GhoCcipSteward({ - ghoToken: address(GHO_TOKEN_BASE), - ghoTokenPool: ghoTokenPool, - riskCouncil: RISK_COUNCIL, - bridgeLimitEnabled: false - }) - ); - return ( - IGhoAaveSteward(aaveSteward), - IGhoBucketSteward(bucketSteward), - IGhoCcipSteward(ccipSteward) - ); - } function _getTokenMessage( CCIPSendParams memory params ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index 3b7caeeac..c49ce5bb0 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -14,11 +14,12 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; - // https://etherscan.io/address/ - IUpgradeableLockReleaseTokenPool_1_5_1 public immutable TOKEN_POOL; + // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + IUpgradeableLockReleaseTokenPool_1_5_1 public constant TOKEN_POOL = + IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); - // https://basescan.org/address/ - address public immutable REMOTE_TOKEN_POOL_BASE; + // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E + address public constant REMOTE_TOKEN_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted @@ -27,11 +28,6 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // Token Rate Limit Refill Rate: 60 GHO per second (=> 216_000 GHO per hour) uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; - constructor(address tokenPoolEth, address tokenPoolBase) { - TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(tokenPoolEth); - REMOTE_TOKEN_POOL_BASE = tokenPoolBase; - } - function execute() external { IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ isEnabled: true, diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index e6165adc7..a58b39641 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {IUpgradeableLockReleaseTokenPool_1_4, IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; +import {IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IPool as IPool_CCIP} from 'src/interfaces/ccip/tokenPool/IPool.sol'; import {IClient} from 'src/interfaces/ccip/IClient.sol'; import {IInternal} from 'src/interfaces/ccip/IInternal.sol'; @@ -16,18 +16,11 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; -import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.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/pools/GHO/UpgradeableLockReleaseTokenPool.sol'; -import {GhoCcipSteward} from 'gho-core/misc/GhoCcipSteward.sol'; - import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; @@ -62,19 +55,18 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); + address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + address internal constant NEW_REMOTE_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; // common across all chains IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); - address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted - - IGhoCcipSteward internal NEW_GHO_CCIP_STEWARD; - - IUpgradeableLockReleaseTokenPool_1_5_1 internal NEW_TOKEN_POOL; + IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = + IGhoCcipSteward(0xFAdC082665577b533e62A7B0E067f884cA5C5E8F); + IUpgradeableLockReleaseTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = + IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); AaveV3Ethereum_GHOBaseLaunch_20241223 internal proposal; - address internal NEW_REMOTE_POOL_ARB = makeAddr('ARB: BurnMintTokenPool 1.5.1'); - address internal NEW_REMOTE_POOL_BASE = makeAddr('BASE: BurnMintTokenPool 1.5.1'); - address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -87,14 +79,9 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21463360); - NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(_deployNewTokenPoolEth()); - NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(_deployNewGhoCcipSteward(address(NEW_TOKEN_POOL))); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21536364); _upgradeEthTo1_5_1(); - proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_BASE - ); + proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); _validateConstants(); @@ -103,11 +90,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { } function _upgradeEthTo1_5_1() internal { - AaveV3Ethereum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209( - address(NEW_TOKEN_POOL), - NEW_REMOTE_POOL_ARB, - address(NEW_GHO_CCIP_STEWARD) - ); + AaveV3Ethereum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1); upgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); @@ -116,50 +99,6 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { executePayload(vm, address(upgradeProposal)); } - function _deployNewTokenPoolEth() private returns (address) { - IUpgradeableLockReleaseTokenPool_1_4 existingTokenPool = IUpgradeableLockReleaseTokenPool_1_4( - GhoEthereum.GHO_CCIP_TOKEN_POOL - ); - address newTokenPoolImpl = address( - new UpgradeableLockReleaseTokenPool( - existingTokenPool.getToken(), - IGhoToken(existingTokenPool.getToken()).decimals(), - existingTokenPool.getArmProxy(), - existingTokenPool.getAllowListEnabled(), - existingTokenPool.canAcceptLiquidity() - ) - ); - - return - address( - new TransparentUpgradeableProxy( - newTokenPoolImpl, - ProxyAdmin(MiscEthereum.PROXY_ADMIN), - abi.encodeCall( - IUpgradeableLockReleaseTokenPool_1_5_1.initialize, - ( - GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner - existingTokenPool.getAllowList(), - existingTokenPool.getRouter(), - existingTokenPool.getBridgeLimit() - ) - ) - ) - ); - } - - function _deployNewGhoCcipSteward(address newTokenPool) internal returns (address) { - return - address( - new GhoCcipSteward( - address(GHO), - newTokenPool, - RISK_COUNCIL, - true // bridgeLimitEnabled Whether the bridge limit feature is supported in the GhoTokenPool - ) - ); - } - function _validateConstants() private view { assertEq(proposal.BASE_CHAIN_SELECTOR(), BASE_CHAIN_SELECTOR); assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index b3b8e5c6e..c12979234 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -13,8 +13,8 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21463360}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 288070365}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21536364}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291243768}}, AaveV3Base: { configs: { ASSET_LISTING: [ @@ -45,7 +45,7 @@ export const config: ConfigFile = { }, ], }, - cache: {blockNumber: 24430581}, + cache: {blockNumber: 24519153}, }, }, }; From f86c4d469e6b6d0f3bde01ba0cebb72ae1870ca8 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 2 Jan 2025 22:53:31 +0530 Subject: [PATCH 084/123] feat: notify gho bucket steward --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 20 +++++++++++++++++++ ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 19 +++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 57af3256a..2de5a7334 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -8,6 +8,7 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {ILegacyProxyAdmin} from 'src/interfaces/ILegacyProxyAdmin.sol'; +import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; @@ -36,6 +37,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { IUpgradeableBurnMintTokenPool_1_5_1 public constant NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + // https://arbiscan.io/address/0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2 + IGhoBucketSteward public constant EXISTING_GHO_BUCKET_STEWARD = + IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); // https://arbiscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A address public constant NEW_GHO_CCIP_STEWARD = 0x06179f7C1be40863405f374E7f5F8806c728660A; @@ -113,6 +117,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { chainsToAdd: chains }); NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); + _notifyGhoBucketSteward(); // register new pool TOKEN_ADMIN_REGISTRY.setPool(address(GHO), address(NEW_TOKEN_POOL)); @@ -124,4 +129,19 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { EXISTING_TOKEN_POOL_UPGRADE_IMPL ); } + + function _notifyGhoBucketSteward() internal { + address[] memory facilitatorList = new address[](1); + facilitatorList[0] = address(EXISTING_TOKEN_POOL); + EXISTING_GHO_BUCKET_STEWARD.setControlledFacilitator({ + facilitatorList: facilitatorList, + approve: false + }); + + facilitatorList[0] = address(NEW_TOKEN_POOL); + EXISTING_GHO_BUCKET_STEWARD.setControlledFacilitator({ + facilitatorList: facilitatorList, + approve: true + }); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 32d8cc744..67826a4c9 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -15,6 +15,7 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; @@ -57,7 +58,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(0x06179f7C1be40863405f374E7f5F8806c728660A); - + IGhoBucketSteward internal constant EXISTING_GHO_BUCKET_STEWARD = + IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = @@ -97,6 +99,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); assertEq(address(proposal.EXISTING_REMOTE_POOL_ETH()), ETH_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(address(proposal.EXISTING_GHO_BUCKET_STEWARD()), address(EXISTING_GHO_BUCKET_STEWARD)); + assertEq(address(proposal.NEW_GHO_CCIP_STEWARD()), address(NEW_GHO_CCIP_STEWARD)); assertEq(address(proposal.NEW_REMOTE_POOL_ETH()), NEW_REMOTE_POOL_ETH); assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); @@ -121,6 +125,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); + assertTrue(GHO.hasRole(GHO.BUCKET_MANAGER_ROLE(), address(EXISTING_GHO_BUCKET_STEWARD))); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); @@ -332,6 +337,18 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); assertEq(_readInitialized(_getImplementation(address(NEW_TOKEN_POOL))), 255); } + + function test_bucketStewardUpdate() public { + assertEq(EXISTING_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 1); + assertTrue(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(EXISTING_TOKEN_POOL))); + assertFalse(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + + executePayload(vm, address(proposal)); + + assertEq(EXISTING_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 1); + assertFalse(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(EXISTING_TOKEN_POOL))); + assertTrue(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + } } contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is From 6b9ad21960ee854258bddffbc6b8ac42f546ad3b Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:33:20 +0530 Subject: [PATCH 085/123] feat: update aave steward --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 47 +++-- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 177 ++++++++++++++++-- ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 4 +- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 26 ++- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 153 +++++++++++++-- .../config.ts | 4 +- src/interfaces/IOwnable.sol | 8 + 7 files changed, 367 insertions(+), 52 deletions(-) create mode 100644 src/interfaces/IOwnable.sol diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 2de5a7334..9e1008c01 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -10,6 +10,7 @@ import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {ILegacyProxyAdmin} from 'src/interfaces/ILegacyProxyAdmin.sol'; import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; @@ -37,8 +38,12 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { IUpgradeableBurnMintTokenPool_1_5_1 public constant NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + // https://arbiscan.io/address/0xcd04d93bea13921dad05240d577090b5ac36dfca + address public constant EXISTING_GHO_AAVE_STEWARD = 0xCd04D93bEA13921DaD05240D577090b5AC36DfCA; + // https://arbiscan.io/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 + address public constant NEW_GHO_AAVE_STEWARD = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; // https://arbiscan.io/address/0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2 - IGhoBucketSteward public constant EXISTING_GHO_BUCKET_STEWARD = + IGhoBucketSteward public constant GHO_BUCKET_STEWARD = IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); // https://arbiscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A address public constant NEW_GHO_CCIP_STEWARD = 0x06179f7C1be40863405f374E7f5F8806c728660A; @@ -65,6 +70,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { _acceptOwnership(); _migrateLiquidity(); _setupAndRegisterNewPool(); + _updateStewards(); } // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -116,32 +122,37 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { remoteChainSelectorsToRemove: new uint64[](0), chainsToAdd: chains }); - NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); - _notifyGhoBucketSteward(); // register new pool TOKEN_ADMIN_REGISTRY.setPool(address(GHO), address(NEW_TOKEN_POOL)); } - function _upgradeExistingTokenPool() internal { - ILegacyProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( - ITransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), - EXISTING_TOKEN_POOL_UPGRADE_IMPL + function _updateStewards() internal { + // Gho Aave Steward + AaveV3Arbitrum.ACL_MANAGER.revokeRole( + AaveV3Arbitrum.ACL_MANAGER.RISK_ADMIN_ROLE(), + EXISTING_GHO_AAVE_STEWARD + ); + AaveV3Arbitrum.ACL_MANAGER.grantRole( + AaveV3Arbitrum.ACL_MANAGER.RISK_ADMIN_ROLE(), + NEW_GHO_AAVE_STEWARD ); - } - function _notifyGhoBucketSteward() internal { + // Gho Bucket Steward address[] memory facilitatorList = new address[](1); facilitatorList[0] = address(EXISTING_TOKEN_POOL); - EXISTING_GHO_BUCKET_STEWARD.setControlledFacilitator({ - facilitatorList: facilitatorList, - approve: false - }); - + GHO_BUCKET_STEWARD.setControlledFacilitator({facilitatorList: facilitatorList, approve: false}); facilitatorList[0] = address(NEW_TOKEN_POOL); - EXISTING_GHO_BUCKET_STEWARD.setControlledFacilitator({ - facilitatorList: facilitatorList, - approve: true - }); + GHO_BUCKET_STEWARD.setControlledFacilitator({facilitatorList: facilitatorList, approve: true}); + + // Gho Ccip Steward + NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); + } + + function _upgradeExistingTokenPool() internal { + ILegacyProxyAdmin(MiscArbitrum.PROXY_ADMIN).upgrade( + ITransparentUpgradeableProxy(payable(address(EXISTING_TOKEN_POOL))), + EXISTING_TOKEN_POOL_UPGRADE_IMPL + ); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 67826a4c9..064c998e6 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -15,9 +15,13 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IOwnable} from 'src/interfaces/IOwnable.sol'; +import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; +import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; @@ -54,12 +58,17 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0x91e46cc5590A4B9182e47f40006140A7077Dec31); IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); + IGhoAaveSteward public constant EXISTING_GHO_AAVE_STEWARD = + IGhoAaveSteward(0xCd04D93bEA13921DaD05240D577090b5AC36DfCA); + IGhoAaveSteward public constant NEW_GHO_AAVE_STEWARD = + IGhoAaveSteward(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); + IGhoBucketSteward internal constant GHO_BUCKET_STEWARD = + IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(0x06179f7C1be40863405f374E7f5F8806c728660A); - IGhoBucketSteward internal constant EXISTING_GHO_BUCKET_STEWARD = - IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); + IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = @@ -79,7 +88,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 291243768); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 291301479); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -99,7 +108,9 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); assertEq(address(proposal.EXISTING_REMOTE_POOL_ETH()), ETH_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); - assertEq(address(proposal.EXISTING_GHO_BUCKET_STEWARD()), address(EXISTING_GHO_BUCKET_STEWARD)); + assertEq(address(proposal.EXISTING_GHO_AAVE_STEWARD()), address(EXISTING_GHO_AAVE_STEWARD)); + assertEq(address(proposal.NEW_GHO_AAVE_STEWARD()), address(NEW_GHO_AAVE_STEWARD)); + assertEq(address(proposal.GHO_BUCKET_STEWARD()), address(GHO_BUCKET_STEWARD)); assertEq(address(proposal.NEW_GHO_CCIP_STEWARD()), address(NEW_GHO_CCIP_STEWARD)); assertEq(address(proposal.NEW_REMOTE_POOL_ETH()), NEW_REMOTE_POOL_ETH); assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); @@ -125,11 +136,40 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); - assertTrue(GHO.hasRole(GHO.BUCKET_MANAGER_ROLE(), address(EXISTING_GHO_BUCKET_STEWARD))); + assertTrue( + AaveV3Arbitrum.ACL_MANAGER.hasRole( + AaveV3Arbitrum.ACL_MANAGER.RISK_ADMIN_ROLE(), + address(EXISTING_GHO_AAVE_STEWARD) + ) + ); + + assertTrue(GHO.hasRole(GHO.BUCKET_MANAGER_ROLE(), address(GHO_BUCKET_STEWARD))); + + assertEq(IOwnable(address(NEW_GHO_AAVE_STEWARD)).owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq( + NEW_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER(), + EXISTING_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER() + ); + assertEq( + NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), + EXISTING_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER() + ); + assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), EXISTING_GHO_AAVE_STEWARD.RISK_COUNCIL()); + assertEq( + NEW_GHO_AAVE_STEWARD.getBorrowRateConfig(), + IGhoAaveSteward.BorrowRateConfig({ + optimalUsageRatioMaxChange: 5_00, + baseVariableBorrowRateMaxChange: 5_00, + variableRateSlope1MaxChange: 5_00, + variableRateSlope2MaxChange: 5_00 + }) + ); + + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); - assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *not present* in remote token pool, only on eth + assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *not present* on remote token pool, only on eth } function _getTokenMessage( @@ -221,11 +261,44 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { return a < b ? a : b; } + function _isDifferenceLowerThanMax( + uint256 from, + uint256 to, + uint256 max + ) internal pure returns (bool) { + return from < to ? to - from <= max : from - to <= max; + } + + function assertEq( + IDefaultInterestRateStrategyV2.InterestRateData memory a, + IDefaultInterestRateStrategyV2.InterestRateData memory b + ) internal pure { + assertEq(a.optimalUsageRatio, b.optimalUsageRatio); + assertEq(a.baseVariableBorrowRate, b.baseVariableBorrowRate); + assertEq(a.variableRateSlope1, b.variableRateSlope1); + assertEq(a.variableRateSlope2, b.variableRateSlope2); + assertEq(abi.encode(a), abi.encode(b)); // sanity check + } + + function assertEq( + IGhoAaveSteward.BorrowRateConfig memory a, + IGhoAaveSteward.BorrowRateConfig memory b + ) internal pure { + assertEq(a.optimalUsageRatioMaxChange, b.optimalUsageRatioMaxChange); + assertEq(a.baseVariableBorrowRateMaxChange, b.baseVariableBorrowRateMaxChange); + assertEq(a.variableRateSlope1MaxChange, b.variableRateSlope1MaxChange); + assertEq(a.variableRateSlope2MaxChange, b.variableRateSlope2MaxChange); + assertEq(abi.encode(a), abi.encode(b)); // sanity check + } + function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config ) internal pure { - assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + assertEq(bucket.isEnabled, config.isEnabled); + assertEq(bucket.capacity, config.capacity); + assertEq(bucket.rate, config.rate); + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); // sanity check } } @@ -338,22 +411,39 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(_readInitialized(_getImplementation(address(NEW_TOKEN_POOL))), 255); } - function test_bucketStewardUpdate() public { - assertEq(EXISTING_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 1); - assertTrue(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(EXISTING_TOKEN_POOL))); - assertFalse(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + function test_stewardRolesAndConfig() public { + bytes32 RISK_ADMIN_ROLE = AaveV3Arbitrum.ACL_MANAGER.RISK_ADMIN_ROLE(); + assertTrue( + AaveV3Arbitrum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(EXISTING_GHO_AAVE_STEWARD)) + ); + assertFalse(AaveV3Arbitrum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(NEW_GHO_AAVE_STEWARD))); + + assertEq(GHO_BUCKET_STEWARD.getControlledFacilitators().length, 1); + assertTrue(GHO_BUCKET_STEWARD.isControlledFacilitator(address(EXISTING_TOKEN_POOL))); + assertFalse(GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(0)); executePayload(vm, address(proposal)); - assertEq(EXISTING_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 1); - assertFalse(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(EXISTING_TOKEN_POOL))); - assertTrue(EXISTING_GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + assertFalse( + AaveV3Arbitrum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(EXISTING_GHO_AAVE_STEWARD)) + ); + assertTrue(AaveV3Arbitrum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(NEW_GHO_AAVE_STEWARD))); + + assertEq(GHO_BUCKET_STEWARD.getControlledFacilitators().length, 1); + assertFalse(GHO_BUCKET_STEWARD.isControlledFacilitator(address(EXISTING_TOKEN_POOL))); + assertTrue(GHO_BUCKET_STEWARD.isControlledFacilitator(address(NEW_TOKEN_POOL))); + + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); } } contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base { + using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + function setUp() public override { super.setUp(); @@ -529,7 +619,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(GHO.balanceOf(alice), aliceBalance + amount); } - function test_stewardCanChangeAndDisableRateLimit() public { + function test_ccipStewardCanChangeAndDisableRateLimit() public { assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); // sanity IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ @@ -573,4 +663,61 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is _getDisabledConfig() ); } + + function test_aaveStewardCanUpdateBorrowRate() public { + IDefaultInterestRateStrategyV2 irStrategy = IDefaultInterestRateStrategyV2( + AaveV3Arbitrum.AAVE_PROTOCOL_DATA_PROVIDER.getInterestRateStrategyAddress(address(GHO)) + ); + + IDefaultInterestRateStrategyV2.InterestRateData + memory currentRateData = IDefaultInterestRateStrategyV2.InterestRateData({ + optimalUsageRatio: 90_00, + baseVariableBorrowRate: 0, + variableRateSlope1: 12_50, + variableRateSlope2: 40_00 + }); + + assertEq(irStrategy.getInterestRateDataBps(address(GHO)), currentRateData); + + currentRateData.variableRateSlope1 -= 4_00; + currentRateData.variableRateSlope2 -= 3_00; + + vm.prank(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL()); + NEW_GHO_AAVE_STEWARD.updateGhoBorrowRate( + currentRateData.optimalUsageRatio, + currentRateData.baseVariableBorrowRate, + currentRateData.variableRateSlope1, + currentRateData.variableRateSlope2 + ); + + assertEq(irStrategy.getInterestRateDataBps(address(GHO)), currentRateData); + } + + function test_aaveStewardCanUpdateBorrowCap(uint256 newBorrowCap) public { + uint256 currentBorrowCap = AaveV3Arbitrum.POOL.getConfiguration(address(GHO)).getBorrowCap(); + assertEq(currentBorrowCap, 22_500_000); + vm.assume( + newBorrowCap != currentBorrowCap && + _isDifferenceLowerThanMax(currentBorrowCap, newBorrowCap, currentBorrowCap) + ); + + vm.prank(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL()); + NEW_GHO_AAVE_STEWARD.updateGhoBorrowCap(newBorrowCap); + + assertEq(AaveV3Arbitrum.POOL.getConfiguration(address(GHO)).getBorrowCap(), newBorrowCap); + } + + function test_aaveStewardCanUpdateSupplyCap(uint256 newSupplyCap) public { + uint256 currentSupplyCap = AaveV3Arbitrum.POOL.getConfiguration(address(GHO)).getSupplyCap(); + assertEq(currentSupplyCap, 25_000_000); + vm.assume( + currentSupplyCap != newSupplyCap && + _isDifferenceLowerThanMax(currentSupplyCap, newSupplyCap, currentSupplyCap) + ); + + vm.prank(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL()); + NEW_GHO_AAVE_STEWARD.updateGhoSupplyCap(newSupplyCap); + + assertEq(AaveV3Arbitrum.POOL.getConfiguration(address(GHO)).getSupplyCap(), newSupplyCap); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index e15cfc6e8..7beafe135 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -88,8 +88,8 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21536364); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291243768); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21538729); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291301479); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index deacd8b51..23f3f54b4 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -7,7 +7,7 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IProxyPool} from 'src/interfaces/ccip/IProxyPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; -import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {AaveV3EthereumAssets, AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; /** @@ -31,6 +31,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 IUpgradeableLockReleaseTokenPool_1_5_1 public constant NEW_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + + // https://etherscan.io/address/0xFEb4e54591660F42288312AE8eB59e9f2B746b66 + address public constant EXISTING_GHO_AAVE_STEWARD = 0xFEb4e54591660F42288312AE8eB59e9f2B746b66; + // https://etherscan.io/address/0x6e637e1E48025E51315d50ab96d5b3be1971A715 + address public constant NEW_GHO_AAVE_STEWARD = 0x6e637e1E48025E51315d50ab96d5b3be1971A715; // https://etherscan.io/address/0xFAdC082665577b533e62A7B0E067f884cA5C5E8F address public constant NEW_GHO_CCIP_STEWARD = 0xFAdC082665577b533e62A7B0E067f884cA5C5E8F; @@ -48,6 +53,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { _acceptOwnership(); _migrateLiquidity(); _setupAndRegisterNewPool(); + _updateStewards(); } // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -94,10 +100,24 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { remoteChainSelectorsToRemove: new uint64[](0), chainsToAdd: chains }); - NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); - NEW_TOKEN_POOL.setBridgeLimitAdmin(NEW_GHO_CCIP_STEWARD); // register new pool TOKEN_ADMIN_REGISTRY.setPool(AaveV3EthereumAssets.GHO_UNDERLYING, address(NEW_TOKEN_POOL)); } + + function _updateStewards() internal { + // Gho Aave Steward + AaveV3Ethereum.ACL_MANAGER.revokeRole( + AaveV3Ethereum.ACL_MANAGER.RISK_ADMIN_ROLE(), + EXISTING_GHO_AAVE_STEWARD + ); + AaveV3Ethereum.ACL_MANAGER.grantRole( + AaveV3Ethereum.ACL_MANAGER.RISK_ADMIN_ROLE(), + NEW_GHO_AAVE_STEWARD + ); + + // Gho Ccip Steward + NEW_TOKEN_POOL.setRateLimitAdmin(NEW_GHO_CCIP_STEWARD); + NEW_TOKEN_POOL.setBridgeLimitAdmin(NEW_GHO_CCIP_STEWARD); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index f3b6504d5..6a2835035 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -15,8 +15,12 @@ import {ITypeAndVersion} from 'src/interfaces/ccip/ITypeAndVersion.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; +import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IOwnable} from 'src/interfaces/IOwnable.sol'; +import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; +import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; @@ -54,6 +58,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); + IGhoAaveSteward public constant EXISTING_GHO_AAVE_STEWARD = + IGhoAaveSteward(0xFEb4e54591660F42288312AE8eB59e9f2B746b66); + IGhoAaveSteward public constant NEW_GHO_AAVE_STEWARD = + IGhoAaveSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = @@ -80,7 +88,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { error BridgeLimitExceeded(uint256 limit); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21536364); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21538729); proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -100,6 +108,9 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(address(proposal.EXISTING_TOKEN_POOL()), address(EXISTING_TOKEN_POOL)); assertEq(address(proposal.EXISTING_REMOTE_POOL_ARB()), ARB_PROXY_POOL); assertEq(address(proposal.NEW_TOKEN_POOL()), address(NEW_TOKEN_POOL)); + assertEq(address(proposal.EXISTING_GHO_AAVE_STEWARD()), address(EXISTING_GHO_AAVE_STEWARD)); + assertEq(address(proposal.NEW_GHO_AAVE_STEWARD()), address(NEW_GHO_AAVE_STEWARD)); + assertEq(address(proposal.NEW_GHO_CCIP_STEWARD()), address(NEW_GHO_CCIP_STEWARD)); assertEq(address(proposal.NEW_REMOTE_POOL_ARB()), NEW_REMOTE_POOL_ARB); assertEq(proposal.CCIP_RATE_LIMIT_CAPACITY(), CCIP_RATE_LIMIT_CAPACITY); assertEq(proposal.CCIP_RATE_LIMIT_REFILL_RATE(), CCIP_RATE_LIMIT_REFILL_RATE); @@ -122,8 +133,33 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(ROUTER.getOnRamp(ARB_CHAIN_SELECTOR), address(ON_RAMP)); assertTrue(ROUTER.isOffRamp(ARB_CHAIN_SELECTOR, address(OFF_RAMP))); - assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); + assertTrue( + AaveV3Ethereum.ACL_MANAGER.hasRole( + AaveV3Ethereum.ACL_MANAGER.RISK_ADMIN_ROLE(), + address(EXISTING_GHO_AAVE_STEWARD) + ) + ); + assertEq(IOwnable(address(NEW_GHO_AAVE_STEWARD)).owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); + assertEq( + NEW_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER(), + EXISTING_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER() + ); + assertEq( + NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), + EXISTING_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER() + ); + assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), EXISTING_GHO_AAVE_STEWARD.RISK_COUNCIL()); + assertEq( + NEW_GHO_AAVE_STEWARD.getBorrowRateConfig(), + IGhoAaveSteward.BorrowRateConfig({ + optimalUsageRatioMaxChange: 5_00, + baseVariableBorrowRateMaxChange: 5_00, + variableRateSlope1MaxChange: 5_00, + variableRateSlope2MaxChange: 5_00 + }) + ); + assertEq(EXISTING_TOKEN_POOL.getRateLimitAdmin(), address(EXISTING_GHO_CCIP_STEWARD)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), EXISTING_GHO_CCIP_STEWARD.RISK_COUNCIL()); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); @@ -200,6 +236,15 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { return IRateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); } + function _getImplementation(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + + function _readInitialized(address proxy) internal view returns (uint8) { + return uint8(uint256(vm.load(proxy, bytes32(0)))); + } + function _getRateLimiterConfig() internal view returns (IRateLimiter.Config memory) { return IRateLimiter.Config({ @@ -230,19 +275,35 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { } function assertEq( - IRateLimiter.TokenBucket memory bucket, - IRateLimiter.Config memory config + IDefaultInterestRateStrategyV2.InterestRateData memory a, + IDefaultInterestRateStrategyV2.InterestRateData memory b ) internal pure { - assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + assertEq(a.optimalUsageRatio, b.optimalUsageRatio); + assertEq(a.baseVariableBorrowRate, b.baseVariableBorrowRate); + assertEq(a.variableRateSlope1, b.variableRateSlope1); + assertEq(a.variableRateSlope2, b.variableRateSlope2); + assertEq(abi.encode(a), abi.encode(b)); // sanity check } - function _getImplementation(address proxy) internal view returns (address) { - bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); - return address(uint160(uint256(vm.load(proxy, slot)))); + function assertEq( + IGhoAaveSteward.BorrowRateConfig memory a, + IGhoAaveSteward.BorrowRateConfig memory b + ) internal pure { + assertEq(a.optimalUsageRatioMaxChange, b.optimalUsageRatioMaxChange); + assertEq(a.baseVariableBorrowRateMaxChange, b.baseVariableBorrowRateMaxChange); + assertEq(a.variableRateSlope1MaxChange, b.variableRateSlope1MaxChange); + assertEq(a.variableRateSlope2MaxChange, b.variableRateSlope2MaxChange); + assertEq(abi.encode(a), abi.encode(b)); // sanity check } - function _readInitialized(address proxy) internal view returns (uint8) { - return uint8(uint256(vm.load(proxy, bytes32(0)))); + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(bucket.isEnabled, config.isEnabled); + assertEq(bucket.capacity, config.capacity); + assertEq(bucket.rate, config.rate); + assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); // sanity check } } @@ -354,11 +415,34 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_SetupAndProposalActions is assertEq(_readInitialized(address(NEW_TOKEN_POOL)), 1); assertEq(_readInitialized(_getImplementation(address(NEW_TOKEN_POOL))), 255); } + + function test_stewardRolesAndConfig() public { + bytes32 RISK_ADMIN_ROLE = AaveV3Ethereum.ACL_MANAGER.RISK_ADMIN_ROLE(); + assertTrue( + AaveV3Ethereum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(EXISTING_GHO_AAVE_STEWARD)) + ); + assertFalse(AaveV3Ethereum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(NEW_GHO_AAVE_STEWARD))); + + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(0)); + assertEq(NEW_TOKEN_POOL.getBridgeLimitAdmin(), address(0)); + + executePayload(vm, address(proposal)); + + assertFalse( + AaveV3Ethereum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(EXISTING_GHO_AAVE_STEWARD)) + ); + assertTrue(AaveV3Ethereum.ACL_MANAGER.hasRole(RISK_ADMIN_ROLE, address(NEW_GHO_AAVE_STEWARD))); + + assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); + assertEq(NEW_TOKEN_POOL.getBridgeLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); + } } contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base { + using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + function setUp() public override { super.setUp(); @@ -550,7 +634,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getCurrentBridgedAmount(), bridgedAmount - amount); } - function test_stewardCanChangeAndDisableRateLimit() public { + function test_ccipStewardCanChangeAndDisableRateLimit() public { assertEq(NEW_TOKEN_POOL.getRateLimitAdmin(), address(NEW_GHO_CCIP_STEWARD)); // sanity IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ @@ -595,7 +679,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is ); } - function test_stewardCanSetBridgeLimit(uint256 newBridgeLimit) public { + function test_ccipStewardCanSetBridgeLimit(uint256 newBridgeLimit) public { uint256 currentBridgeLimit = NEW_TOKEN_POOL.getBridgeLimit(); vm.assume( newBridgeLimit != currentBridgeLimit && @@ -606,4 +690,49 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getBridgeLimit(), newBridgeLimit); } + + function test_aaveStewardCanUpdateBorrowRate() public { + IDefaultInterestRateStrategyV2 irStrategy = IDefaultInterestRateStrategyV2( + AaveV3Ethereum.AAVE_PROTOCOL_DATA_PROVIDER.getInterestRateStrategyAddress(address(GHO)) + ); + + IDefaultInterestRateStrategyV2.InterestRateData + memory currentRateData = IDefaultInterestRateStrategyV2.InterestRateData({ + optimalUsageRatio: 99_00, + baseVariableBorrowRate: 12_50, + variableRateSlope1: 0, + variableRateSlope2: 0 + }); + + assertEq(irStrategy.getInterestRateDataBps(address(GHO)), currentRateData); + + currentRateData.baseVariableBorrowRate += 4_00; + + vm.prank(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL()); + NEW_GHO_AAVE_STEWARD.updateGhoBorrowRate( + currentRateData.optimalUsageRatio, + currentRateData.baseVariableBorrowRate, + currentRateData.variableRateSlope1, + currentRateData.variableRateSlope2 + ); + + assertEq(irStrategy.getInterestRateDataBps(address(GHO)), currentRateData); + } + + function test_aaveStewardCanUpdateBorrowCap(uint256 newBorrowCap) public { + uint256 currentBorrowCap = AaveV3Ethereum.POOL.getConfiguration(address(GHO)).getBorrowCap(); + assertEq(currentBorrowCap, 155_000_000); + vm.assume( + newBorrowCap != currentBorrowCap && + _isDifferenceLowerThanMax(currentBorrowCap, newBorrowCap, currentBorrowCap) + ); + + vm.prank(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL()); + NEW_GHO_AAVE_STEWARD.updateGhoBorrowCap(newBorrowCap); + + assertEq(AaveV3Ethereum.POOL.getConfiguration(address(GHO)).getBorrowCap(), newBorrowCap); + + // @dev gho cannot be supplied on ethereum + assertEq(AaveV3Ethereum.POOL.getConfiguration(address(GHO)).getSupplyCap(), 0); + } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index 2b8682e45..bb7d24f2c 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21536364}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291243768}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21538729}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291301479}}, }, }; diff --git a/src/interfaces/IOwnable.sol b/src/interfaces/IOwnable.sol new file mode 100644 index 000000000..a02af3dd1 --- /dev/null +++ b/src/interfaces/IOwnable.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IOwnable { + /// @notice Returns the owner of the contract. + /// @dev This method is named to match with the OpenZeppelin Ownable contract. + function owner() external view returns (address); +} From 16930a27c400444af4d1af78e4d77928b195ef3c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:38:18 +0530 Subject: [PATCH 086/123] upd: upstream --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 4 ++-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 2 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 2aba37586..fdcd9d3ca 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -79,7 +79,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 291243768); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 291301479); _upgradeArbTo1_5_1(); proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 8466cef90..39472a760 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -109,9 +109,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291243768); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291301479); base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24519153); - eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21536364); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21538729); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index a58b39641..b04cb5790 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -79,7 +79,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21536364); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21538729); _upgradeEthTo1_5_1(); proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index c12979234..2af7a0345 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -13,8 +13,8 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21536364}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291243768}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21538729}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291301479}}, AaveV3Base: { configs: { ASSET_LISTING: [ From 30194d1bd6f25e6ee66348c28818629860753156 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:15:40 +0530 Subject: [PATCH 087/123] chore: use existing IOwnable --- .../AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- .../AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 2 +- src/interfaces/IOwnable.sol | 8 -------- 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 src/interfaces/IOwnable.sol diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 064c998e6..1ae30e0df 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -18,7 +18,7 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; -import {IOwnable} from 'src/interfaces/IOwnable.sol'; +import {IOwnable} from 'aave-address-book/common/IOwnable.sol'; import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 6a2835035..8779bb283 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -17,7 +17,7 @@ import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; -import {IOwnable} from 'src/interfaces/IOwnable.sol'; +import {IOwnable} from 'aave-address-book/common/IOwnable.sol'; import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; diff --git a/src/interfaces/IOwnable.sol b/src/interfaces/IOwnable.sol deleted file mode 100644 index a02af3dd1..000000000 --- a/src/interfaces/IOwnable.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IOwnable { - /// @notice Returns the owner of the contract. - /// @dev This method is named to match with the OpenZeppelin Ownable contract. - function owner() external view returns (address); -} From 8cf93658f7f53dbedfc25ceae4d0435f4ee2c3a4 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:51:07 +0530 Subject: [PATCH 088/123] chore: steward tests --- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 3 +- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 110 +++++++++++++++--- 2 files changed, 98 insertions(+), 15 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index f725e6b33..3ac7f5341 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -12,11 +12,11 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IEVM2EVMOnRamp} from 'src/interfaces/ccip/IEVM2EVMOnRamp.sol'; import {IEVM2EVMOffRamp_1_5} from 'src/interfaces/ccip/IEVM2EVMOffRamp.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; -import {IOwnable} from 'src/interfaces/IOwnable.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {IOwnable} from 'aave-address-book/common/IOwnable.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -324,6 +324,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq(NEW_GHO_BUCKET_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); assertEq(NEW_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 0); // before AIP, no controlled facilitators are set + assertEq(IOwnable(address(NEW_GHO_CCIP_STEWARD)).owner(), GovernanceV3Base.EXECUTOR_LVL_1); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), address(GHO)); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index b7600f25c..bf0a92a49 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -8,6 +8,7 @@ import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; +import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; @@ -20,6 +21,7 @@ import {GovV3Helpers} from 'aave-helpers/src/GovV3Helpers.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; +import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; import {AaveV3Base_GHOBaseListing_20241223} from './AaveV3Base_GHOBaseListing_20241223.sol'; @@ -60,6 +62,41 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO_TOKEN), GovernanceV3Base.EXECUTOR_LVL_1); executePayload(vm, address(new AaveV3Base_GHOBaseLaunch_20241223())); } + + function _isDifferenceLowerThanMax( + uint256 from, + uint256 to, + uint256 max + ) internal pure returns (bool) { + return from < to ? to - from <= max : from - to <= max; + } + + function _isIncreaseLowerThanMax( + uint256 from, + uint256 to, + uint256 max + ) internal pure returns (bool) { + return to >= from && to - from <= max; + } + + function assertEq( + IRateLimiter.TokenBucket memory bucket, + IRateLimiter.Config memory config + ) internal pure { + assertEq(bucket.capacity, config.capacity); + assertEq(bucket.rate, config.rate); + assertEq(bucket.isEnabled, config.isEnabled); + } + + function assertEq( + IDefaultInterestRateStrategyV2.InterestRateData memory a, + IDefaultInterestRateStrategyV2.InterestRateData memory b + ) internal { + assertEq(a.optimalUsageRatio, b.optimalUsageRatio); + assertEq(a.baseVariableBorrowRate, b.baseVariableBorrowRate); + assertEq(a.variableRateSlope1, b.variableRateSlope1); + assertEq(a.variableRateSlope2, b.variableRateSlope2); + } } contract AaveV3Base_GHOBaseListing_20241223_Listing is AaveV3Base_GHOBaseListing_20241223_Base { @@ -178,21 +215,66 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin assertEq(AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getSupplyCap(), newSupplyCap); } - function assertEq( - IDefaultInterestRateStrategyV2.InterestRateData memory a, - IDefaultInterestRateStrategyV2.InterestRateData memory b - ) internal { - assertEq(a.optimalUsageRatio, b.optimalUsageRatio, 'optimalUsageRatio'); - assertEq(a.baseVariableBorrowRate, b.baseVariableBorrowRate, 'baseVariableBorrowRate'); - assertEq(a.variableRateSlope1, b.variableRateSlope1, 'variableRateSlope1'); - assertEq(a.variableRateSlope2, b.variableRateSlope2, 'variableRateSlope2'); + function test_bucketStewardCanUpdateBucketCapacity(uint128 newBucketCapacity) public { + uint128 currentBucketCapacity = GHO_TOKEN + .getFacilitator(address(NEW_TOKEN_POOL)) + .bucketCapacity; + assertEq(currentBucketCapacity, 20_000_000e18); + vm.assume( + newBucketCapacity != currentBucketCapacity && + _isIncreaseLowerThanMax(currentBucketCapacity, newBucketCapacity, currentBucketCapacity) + ); + + vm.startPrank(RISK_COUNCIL); + NEW_GHO_BUCKET_STEWARD.updateFacilitatorBucketCapacity( + address(NEW_TOKEN_POOL), + newBucketCapacity + ); + + assertEq(GHO_TOKEN.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity, newBucketCapacity); } - function _isDifferenceLowerThanMax( - uint256 from, - uint256 to, - uint256 max - ) internal pure returns (bool) { - return from < to ? to - from <= max : from - to <= max; + function test_ccipStewardCanChangeAndDisableRateLimit() public { + _runCcipStewardCanChangeAndDisableRateLimit(CCIPUtils.ETH_CHAIN_SELECTOR); + skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); + _runCcipStewardCanChangeAndDisableRateLimit(CCIPUtils.ARB_CHAIN_SELECTOR); + } + + function _runCcipStewardCanChangeAndDisableRateLimit(uint64 remoteChain) internal { + IRateLimiter.Config memory outboundConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 500_000e18, + rate: 100e18 + }); + IRateLimiter.Config memory inboundConfig = IRateLimiter.Config({ + isEnabled: true, + capacity: 100_000e18, + rate: 50e18 + }); + + // we assert the steward can change the rate limit + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateRateLimit( + remoteChain, + outboundConfig.isEnabled, + outboundConfig.capacity, + outboundConfig.rate, + inboundConfig.isEnabled, + inboundConfig.capacity, + inboundConfig.rate + ); + + assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(remoteChain), outboundConfig); + assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(remoteChain), inboundConfig); + + skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); + + // now we assert the steward can disable the rate limit + vm.prank(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL()); + NEW_GHO_CCIP_STEWARD.updateRateLimit(remoteChain, false, 0, 0, false, 0, 0); + + IRateLimiter.Config memory disabledConfig = IRateLimiter.Config(false, 0, 0); + assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(remoteChain), disabledConfig); + assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(remoteChain), disabledConfig); } } From dd101af4283ffcd9d81d5b9b1a37810012cfb59e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 17:03:35 +0530 Subject: [PATCH 089/123] fix: ccip stewards tests --- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 3ac7f5341..319639bb3 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -324,7 +324,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq(NEW_GHO_BUCKET_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); assertEq(NEW_GHO_BUCKET_STEWARD.getControlledFacilitators().length, 0); // before AIP, no controlled facilitators are set - assertEq(IOwnable(address(NEW_GHO_CCIP_STEWARD)).owner(), GovernanceV3Base.EXECUTOR_LVL_1); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), address(GHO)); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); From fbdefd11b281923c85124dac704f53a04ee55063 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 17:38:15 +0530 Subject: [PATCH 090/123] test: listing pre-req negative cases --- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index bf0a92a49..d6c84819e 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -51,8 +51,6 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { function setUp() public virtual { vm.createSelectFork(vm.rpcUrl('base'), 24519153); - _executeLaunchAIP(); // deploys gho token, token pool & stewards - proposal = new AaveV3Base_GHOBaseListing_20241223(); } @@ -63,6 +61,12 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { executePayload(vm, address(new AaveV3Base_GHOBaseLaunch_20241223())); } + function _mockBridgeSeedAmount() internal { + uint256 seedAmount = proposal.GHO_SEED_AMOUNT(); + vm.prank(address(NEW_TOKEN_POOL)); + GHO_TOKEN.mint(GovernanceV3Base.EXECUTOR_LVL_1, seedAmount); + } + function _isDifferenceLowerThanMax( uint256 from, uint256 to, @@ -99,14 +103,42 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { } } -contract AaveV3Base_GHOBaseListing_20241223_Listing is AaveV3Base_GHOBaseListing_20241223_Base { +contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is + AaveV3Base_GHOBaseListing_20241223_Base +{ + uint40 internal payloadId; + function setUp() public override { super.setUp(); + payloadId = GovV3Helpers.readyPayload(vm, address(proposal)); + } - uint256 seedAmount = proposal.GHO_SEED_AMOUNT(); - // mock executor receives seed amount after Launch AIP (ie bridge activation) - vm.prank(address(NEW_TOKEN_POOL)); - GHO_TOKEN.mint(GovernanceV3Base.EXECUTOR_LVL_1, seedAmount); + function test_listingFailsPreLaunch() public { + vm.expectRevert(abi.encodePacked('29')); // gho token not deployed, reverts on token.decimals() check + GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); + } + + function test_listingFailsWithoutSeedAmount() public { + test_listingFailsPreLaunch(); + _executeLaunchAIP(); // deploys gho token, token pool & stewards + + vm.expectRevert(abi.encodePacked('29')); // seed amount has not been bridged yet, reverts on pool.supply() + GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); + } + + function test_listingSucceedsOnlyAfterLaunchAndSeedAmount() public { + test_listingFailsWithoutSeedAmount(); + _mockBridgeSeedAmount(); + + GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); + } +} + +contract AaveV3Base_GHOBaseListing_20241223_Listing is AaveV3Base_GHOBaseListing_20241223_Base { + function setUp() public override { + super.setUp(); + _executeLaunchAIP(); // deploys gho token, token pool & stewards + _mockBridgeSeedAmount(); } /** @@ -148,11 +180,8 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin function setUp() public override { super.setUp(); - - uint256 seedAmount = proposal.GHO_SEED_AMOUNT(); - // mock executor receives seed amount after Launch AIP (ie bridge activation) - vm.prank(address(NEW_TOKEN_POOL)); - GHO_TOKEN.mint(GovernanceV3Base.EXECUTOR_LVL_1, seedAmount); + _executeLaunchAIP(); // deploys gho token, token pool & stewards + _mockBridgeSeedAmount(); executePayload(vm, address(proposal)); } From b06cb8ecdc3422864c4adc4dbd021060af332a75 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 18:02:34 +0530 Subject: [PATCH 091/123] chore: minor cleanup --- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index d6c84819e..ab0e94796 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -75,14 +75,6 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { return from < to ? to - from <= max : from - to <= max; } - function _isIncreaseLowerThanMax( - uint256 from, - uint256 to, - uint256 max - ) internal pure returns (bool) { - return to >= from && to - from <= max; - } - function assertEq( IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config @@ -131,6 +123,11 @@ contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is _mockBridgeSeedAmount(); GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); + + (, , , , , , , , bool isActive, ) = AaveV3Base + .AAVE_PROTOCOL_DATA_PROVIDER + .getReserveConfigurationData(address(GHO_TOKEN)); + assertTrue(isActive); } } @@ -244,23 +241,25 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin assertEq(AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getSupplyCap(), newSupplyCap); } - function test_bucketStewardCanUpdateBucketCapacity(uint128 newBucketCapacity) public { - uint128 currentBucketCapacity = GHO_TOKEN - .getFacilitator(address(NEW_TOKEN_POOL)) - .bucketCapacity; + function test_bucketStewardCanUpdateBucketCapacity(uint256 newBucketCapacity) public { + (uint256 currentBucketCapacity, ) = GHO_TOKEN.getFacilitatorBucket(address(NEW_TOKEN_POOL)); assertEq(currentBucketCapacity, 20_000_000e18); - vm.assume( - newBucketCapacity != currentBucketCapacity && - _isIncreaseLowerThanMax(currentBucketCapacity, newBucketCapacity, currentBucketCapacity) + newBucketCapacity = bound( + newBucketCapacity, + currentBucketCapacity + 1, + 2 * currentBucketCapacity ); vm.startPrank(RISK_COUNCIL); NEW_GHO_BUCKET_STEWARD.updateFacilitatorBucketCapacity( address(NEW_TOKEN_POOL), - newBucketCapacity + uint128(newBucketCapacity) ); - assertEq(GHO_TOKEN.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity, newBucketCapacity); + assertEq( + GHO_TOKEN.getFacilitator(address(NEW_TOKEN_POOL)).bucketCapacity, + uint128(newBucketCapacity) + ); } function test_ccipStewardCanChangeAndDisableRateLimit() public { From e7c651e3608e071219a1d99c04ceb7100ecf018d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Fri, 3 Jan 2025 18:45:14 +0530 Subject: [PATCH 092/123] test: verbose error msg --- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index ab0e94796..9c6f2ffad 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -16,6 +16,7 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoOracle} from 'src/interfaces/IGhoOracle.sol'; import {ReserveConfiguration} from 'aave-v3-origin/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; +import {Errors} from 'aave-address-book/governance-v3/Errors.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {GovV3Helpers} from 'aave-helpers/src/GovV3Helpers.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; @@ -106,7 +107,7 @@ contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is } function test_listingFailsPreLaunch() public { - vm.expectRevert(abi.encodePacked('29')); // gho token not deployed, reverts on token.decimals() check + vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // gho token not deployed, reverts on token.decimals() check GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); } @@ -114,7 +115,7 @@ contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is test_listingFailsPreLaunch(); _executeLaunchAIP(); // deploys gho token, token pool & stewards - vm.expectRevert(abi.encodePacked('29')); // seed amount has not been bridged yet, reverts on pool.supply() + vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // seed amount has not been bridged yet, reverts on pool.supply() GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); } From 7c6f9da9381c104190c5a405c0accbb0ef653d21 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Sat, 4 Jan 2025 00:01:24 +0530 Subject: [PATCH 093/123] feat: QoL cleanup --- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 34 +++++++++---------- .../AaveV3Base_GHOBaseListing_20241223.sol | 5 +++ .../AaveV3Base_GHOBaseListing_20241223.t.sol | 8 ++--- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 2 +- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index fdcd9d3ca..70d02eb10 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -229,7 +229,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } - function test_BasePoolConfig() public view { + function test_basePoolConfig() public view { assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); assertEq(NEW_TOKEN_POOL.getSupportedChains()[0], ETH_CHAIN_SELECTOR); assertEq(NEW_TOKEN_POOL.getSupportedChains()[1], BASE_CHAIN_SELECTOR); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 0dac6e736..d23dafc81 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -60,14 +60,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { function execute() external { _acceptOwnership(); - - if (_deployAndInitializeGhoToken() != address(GHO_TOKEN_PROXY)) revert(); - + _deployAndInitializeGhoToken(); _setupStewardsAndTokenPoolOnGho(); - - _setupRemoteTokenPools(); // eth & arb - - TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN_PROXY), address(TOKEN_POOL)); + _setupRemoteAndRegisterTokenPool(); } function _acceptOwnership() internal { @@ -75,15 +70,16 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { TOKEN_POOL.acceptOwnership(); } - function _deployAndInitializeGhoToken() internal returns (address) { - return - address( - new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( - GHO_TOKEN_IMPL, - ProxyAdmin(MiscBase.PROXY_ADMIN), - abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) - ) - ); + function _deployAndInitializeGhoToken() internal { + address ghoTokenProxy = address( + new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( + GHO_TOKEN_IMPL, + ProxyAdmin(MiscBase.PROXY_ADMIN), + abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) + ) + ); + // burn all gas, assert predicted address match + assert(ghoTokenProxy == address(GHO_TOKEN_PROXY)); } function _setupStewardsAndTokenPoolOnGho() internal { @@ -119,7 +115,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { TOKEN_POOL.setRateLimitAdmin(GHO_CCIP_STEWARD); } - function _setupRemoteTokenPools() internal { + function _setupRemoteAndRegisterTokenPool() internal { IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ isEnabled: true, capacity: CCIP_RATE_LIMIT_CAPACITY, @@ -153,9 +149,13 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { }); } + // setup remote token pools TOKEN_POOL.applyChainUpdates({ remoteChainSelectorsToRemove: new uint64[](0), chainsToAdd: chainsToAdd }); + + // register token pool + TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN_PROXY), address(TOKEN_POOL)); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol index 80bee245d..12931f62f 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol @@ -26,6 +26,11 @@ contract AaveV3Base_GHOBaseListing_20241223 is AaveV3PayloadBase { address public constant GHO_TOKEN = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; uint256 public constant GHO_SEED_AMOUNT = 1e18; + function _preExecute() internal override { + // robot should simulate and only execute if seed amount has been bridged + assert(IERC20(GHO_TOKEN).balanceOf(address(this)) >= GHO_SEED_AMOUNT); + } + function _postExecute() internal override { IERC20(GHO_TOKEN).forceApprove(address(AaveV3Base.POOL), GHO_SEED_AMOUNT); AaveV3Base.POOL.supply(GHO_TOKEN, GHO_SEED_AMOUNT, address(0), 0); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 9c6f2ffad..cf7146f2d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -127,7 +127,7 @@ contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is (, , , , , , , , bool isActive, ) = AaveV3Base .AAVE_PROTOCOL_DATA_PROVIDER - .getReserveConfigurationData(address(GHO_TOKEN)); + .getReserveConfigurationData(proposal.GHO_TOKEN()); assertTrue(isActive); } } @@ -157,7 +157,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Listing is AaveV3Base_GHOBaseListing assertEq(priceOracle.decimals(), 8); } - function test_GhoAdmin() public { + function test_ghoAdmin() public { GovV3Helpers.executePayload(vm, address(proposal)); (address aGhoToken, , ) = AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses( proposal.GHO_TOKEN() @@ -215,7 +215,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin function test_aaveStewardCanUpdateBorrowCap(uint256 newBorrowCap) public { uint256 currentBorrowCap = AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getBorrowCap(); - assertEq(currentBorrowCap, 2_250_000, 'currentBorrowCap'); + assertEq(currentBorrowCap, 2_250_000); vm.assume( newBorrowCap != currentBorrowCap && _isDifferenceLowerThanMax(currentBorrowCap, newBorrowCap, currentBorrowCap) @@ -229,7 +229,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin function test_aaveStewardCanUpdateSupplyCap(uint256 newSupplyCap) public { uint256 currentSupplyCap = AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getSupplyCap(); - assertEq(currentSupplyCap, 2_500_000, 'currentSupplyCap'); + assertEq(currentSupplyCap, 2_500_000); vm.assume( currentSupplyCap != newSupplyCap && diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index b04cb5790..34369f46f 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -229,7 +229,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } - function test_BasePoolConfig() public view { + function test_basePoolConfig() public view { assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); assertEq(NEW_TOKEN_POOL.getSupportedChains()[0], ARB_CHAIN_SELECTOR); assertEq(NEW_TOKEN_POOL.getSupportedChains()[1], BASE_CHAIN_SELECTOR); From e90cf743cc7d1c0080fa21981764ca2fd526f2df Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:02:27 +0530 Subject: [PATCH 094/123] chore: new ccip stewards with timelock getter --- ...AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- ...veV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 16 ++++++++++++++-- .../AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 4 ++-- ...AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 4 ++-- ...veV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 16 ++++++++++++++-- src/20241209_Multi_GHOCCIP151Upgrade/config.ts | 4 ++-- src/interfaces/IGhoCcipSteward.sol | 6 ++++++ 7 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 9e1008c01..5ba8f6a8e 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -45,8 +45,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://arbiscan.io/address/0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2 IGhoBucketSteward public constant GHO_BUCKET_STEWARD = IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); - // https://arbiscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A - address public constant NEW_GHO_CCIP_STEWARD = 0x06179f7C1be40863405f374E7f5F8806c728660A; + // https://arbiscan.io/address/0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396 + address public constant NEW_GHO_CCIP_STEWARD = 0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396; // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 1ae30e0df..35d0b8258 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -67,7 +67,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x06179f7C1be40863405f374E7f5F8806c728660A); + IGhoCcipSteward(0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); @@ -88,7 +88,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 291301479); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 292550754); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -170,6 +170,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *not present* on remote token pool, only on eth + assertEq( + abi.encode(NEW_GHO_CCIP_STEWARD.getCcipTimelocks()), + abi.encode(IGhoCcipSteward.CcipDebounce(0, 0)) + ); } function _getTokenMessage( @@ -647,6 +651,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ETH_CHAIN_SELECTOR), outboundConfig); assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), inboundConfig); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().rateLimitLastUpdate, vm.getBlockTimestamp()); skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); @@ -662,6 +667,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ETH_CHAIN_SELECTOR), _getDisabledConfig() ); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().rateLimitLastUpdate, vm.getBlockTimestamp()); } function test_aaveStewardCanUpdateBorrowRate() public { @@ -691,6 +697,10 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is ); assertEq(irStrategy.getInterestRateDataBps(address(GHO)), currentRateData); + assertEq( + NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoBorrowRateLastUpdate, + vm.getBlockTimestamp() + ); } function test_aaveStewardCanUpdateBorrowCap(uint256 newBorrowCap) public { @@ -705,6 +715,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is NEW_GHO_AAVE_STEWARD.updateGhoBorrowCap(newBorrowCap); assertEq(AaveV3Arbitrum.POOL.getConfiguration(address(GHO)).getBorrowCap(), newBorrowCap); + assertEq(NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoBorrowCapLastUpdate, vm.getBlockTimestamp()); } function test_aaveStewardCanUpdateSupplyCap(uint256 newSupplyCap) public { @@ -719,5 +730,6 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_PostUpgrade is NEW_GHO_AAVE_STEWARD.updateGhoSupplyCap(newSupplyCap); assertEq(AaveV3Arbitrum.POOL.getConfiguration(address(GHO)).getSupplyCap(), newSupplyCap); + assertEq(NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoSupplyCapLastUpdate, vm.getBlockTimestamp()); } } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 7beafe135..33ca64691 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -88,8 +88,8 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21538729); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291301479); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21564756); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 292550754); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index 23f3f54b4..bdcbf4056 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -36,8 +36,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { address public constant EXISTING_GHO_AAVE_STEWARD = 0xFEb4e54591660F42288312AE8eB59e9f2B746b66; // https://etherscan.io/address/0x6e637e1E48025E51315d50ab96d5b3be1971A715 address public constant NEW_GHO_AAVE_STEWARD = 0x6e637e1E48025E51315d50ab96d5b3be1971A715; - // https://etherscan.io/address/0xFAdC082665577b533e62A7B0E067f884cA5C5E8F - address public constant NEW_GHO_CCIP_STEWARD = 0xFAdC082665577b533e62A7B0E067f884cA5C5E8F; + // https://etherscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + address public constant NEW_GHO_CCIP_STEWARD = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 8779bb283..0d7939cf6 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -65,7 +65,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0xFAdC082665577b533e62A7B0E067f884cA5C5E8F); + IGhoCcipSteward(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x9Ec9F9804733df96D1641666818eFb5198eC50f0); @@ -88,7 +88,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { error BridgeLimitExceeded(uint256 limit); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21538729); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21564756); proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -164,6 +164,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3EthereumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertTrue(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); // *present* on eth token pool + assertEq( + abi.encode(NEW_GHO_CCIP_STEWARD.getCcipTimelocks()), + abi.encode(IGhoCcipSteward.CcipDebounce(0, 0)) + ); } function _getTokenMessage( @@ -662,6 +666,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(ARB_CHAIN_SELECTOR), outboundConfig); assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), inboundConfig); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().rateLimitLastUpdate, vm.getBlockTimestamp()); skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); @@ -677,6 +682,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(ARB_CHAIN_SELECTOR), _getDisabledConfig() ); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().rateLimitLastUpdate, vm.getBlockTimestamp()); } function test_ccipStewardCanSetBridgeLimit(uint256 newBridgeLimit) public { @@ -689,6 +695,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is NEW_GHO_CCIP_STEWARD.updateBridgeLimit(newBridgeLimit); assertEq(NEW_TOKEN_POOL.getBridgeLimit(), newBridgeLimit); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().bridgeLimitLastUpdate, vm.getBlockTimestamp()); } function test_aaveStewardCanUpdateBorrowRate() public { @@ -717,6 +724,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is ); assertEq(irStrategy.getInterestRateDataBps(address(GHO)), currentRateData); + assertEq( + NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoBorrowRateLastUpdate, + vm.getBlockTimestamp() + ); } function test_aaveStewardCanUpdateBorrowCap(uint256 newBorrowCap) public { @@ -731,6 +742,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is NEW_GHO_AAVE_STEWARD.updateGhoBorrowCap(newBorrowCap); assertEq(AaveV3Ethereum.POOL.getConfiguration(address(GHO)).getBorrowCap(), newBorrowCap); + assertEq(NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoBorrowCapLastUpdate, vm.getBlockTimestamp()); // @dev gho cannot be supplied on ethereum assertEq(AaveV3Ethereum.POOL.getConfiguration(address(GHO)).getSupplyCap(), 0); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index bb7d24f2c..a6c995ab9 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21538729}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291301479}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21564756}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 292550754}}, }, }; diff --git a/src/interfaces/IGhoCcipSteward.sol b/src/interfaces/IGhoCcipSteward.sol index 39bec9294..57c1e8017 100644 --- a/src/interfaces/IGhoCcipSteward.sol +++ b/src/interfaces/IGhoCcipSteward.sol @@ -41,6 +41,12 @@ interface IGhoCcipSteward { uint128 inboundRate ) external; + /** + * @notice Returns timestamp of the last update of Ccip parameters. + * @return The CcipDebounce struct describing the last update of Ccip parameters. + */ + function getCcipTimelocks() external view returns (CcipDebounce memory); + /** * @notice Returns the minimum delay that must be respected between parameters update. * @return The minimum delay between parameter updates (in seconds) From 9dbf84e968cb51f550f3ccd12cf2475d1089e748 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:16:25 +0530 Subject: [PATCH 095/123] chore: upd upstream --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 2 +- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 4 ++-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 2 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 70d02eb10..403ff1a19 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -79,7 +79,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 291301479); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 292550754); _upgradeArbTo1_5_1(); proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index cf7146f2d..0dc3d79fd 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -115,7 +115,7 @@ contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is test_listingFailsPreLaunch(); _executeLaunchAIP(); // deploys gho token, token pool & stewards - vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // seed amount has not been bridged yet, reverts on pool.supply() + vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // seed amount has not been bridged yet, reverts on _preExecute() GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 39472a760..e5010ceaa 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -109,9 +109,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 291301479); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 292550754); base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24519153); - eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21538729); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21564756); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 34369f46f..65f2e284f 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -79,7 +79,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21538729); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21564756); _upgradeEthTo1_5_1(); proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 2af7a0345..e13945b82 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -13,8 +13,8 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21538729}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 291301479}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21564756}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 292550754}}, AaveV3Base: { configs: { ASSET_LISTING: [ From f960d7833c4d08729a29f2e46ba9b38bd621257c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:26:23 +0530 Subject: [PATCH 096/123] chore: new ccip stewards with timelock getter on base --- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 4 ++-- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 15 ++++++--------- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 8 ++++++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 2 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 2 +- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index d23dafc81..956f77958 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -45,8 +45,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { address public constant GHO_AAVE_STEWARD = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; // https://basescan.org/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A address public constant GHO_BUCKET_STEWARD = 0xA5Ba213867E175A182a5dd6A9193C6158738105A; - // https://basescan.org/address/0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B - address public constant GHO_CCIP_STEWARD = 0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B; + // https://basescan.org/address/0x6e637e1E48025E51315d50ab96d5b3be1971A715 + address public constant GHO_CCIP_STEWARD = 0x6e637e1E48025E51315d50ab96d5b3be1971A715; // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 address public constant REMOTE_TOKEN_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 319639bb3..d3c04aa9d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -73,7 +73,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = IGhoBucketSteward(0xA5Ba213867E175A182a5dd6A9193C6158738105A); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B); + IGhoCcipSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; @@ -93,7 +93,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24519153); + vm.createSelectFork(vm.rpcUrl('base'), 24685477); proposal = new AaveV3Base_GHOBaseLaunch_20241223(); _performCcipPreReq(); @@ -328,13 +328,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223_PreExecution is AaveV3Base_GHOBaseLau assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertEq(NEW_GHO_CCIP_STEWARD.RISK_COUNCIL(), RISK_COUNCIL); assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); - uint256 ccipDebounceValue = uint256(vm.load(address(NEW_GHO_CCIP_STEWARD), bytes32(0))); - IGhoCcipSteward.CcipDebounce memory ccipDebounce = IGhoCcipSteward.CcipDebounce({ - bridgeLimitLastUpdate: uint40(ccipDebounceValue >> 216), - rateLimitLastUpdate: uint40(ccipDebounceValue >> 176) - }); - assertEq(ccipDebounce.bridgeLimitLastUpdate, 0); - assertEq(ccipDebounce.rateLimitLastUpdate, 0); + assertEq( + abi.encode(NEW_GHO_CCIP_STEWARD.getCcipTimelocks()), + abi.encode(IGhoCcipSteward.CcipDebounce(0, 0)) + ); } function test_newTokenPoolInitialization() public { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 0dc3d79fd..24005441d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -46,12 +46,12 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = IGhoBucketSteward(0xA5Ba213867E175A182a5dd6A9193C6158738105A); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x2Ce400703dAcc37b7edFA99D228b8E70a4d3831B); + IGhoCcipSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24519153); + vm.createSelectFork(vm.rpcUrl('base'), 24685477); proposal = new AaveV3Base_GHOBaseListing_20241223(); } @@ -225,6 +225,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin NEW_GHO_AAVE_STEWARD.updateGhoBorrowCap(newBorrowCap); assertEq(AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getBorrowCap(), newBorrowCap); + assertEq(NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoBorrowCapLastUpdate, vm.getBlockTimestamp()); } function test_aaveStewardCanUpdateSupplyCap(uint256 newSupplyCap) public { @@ -240,6 +241,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin NEW_GHO_AAVE_STEWARD.updateGhoSupplyCap(newSupplyCap); assertEq(AaveV3Base.POOL.getConfiguration(address(GHO_TOKEN)).getSupplyCap(), newSupplyCap); + assertEq(NEW_GHO_AAVE_STEWARD.getGhoTimelocks().ghoSupplyCapLastUpdate, vm.getBlockTimestamp()); } function test_bucketStewardCanUpdateBucketCapacity(uint256 newBucketCapacity) public { @@ -295,6 +297,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(remoteChain), outboundConfig); assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(remoteChain), inboundConfig); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().rateLimitLastUpdate, vm.getBlockTimestamp()); skip(NEW_GHO_CCIP_STEWARD.MINIMUM_DELAY() + 1); @@ -305,5 +308,6 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin IRateLimiter.Config memory disabledConfig = IRateLimiter.Config(false, 0, 0); assertEq(NEW_TOKEN_POOL.getCurrentOutboundRateLimiterState(remoteChain), disabledConfig); assertEq(NEW_TOKEN_POOL.getCurrentInboundRateLimiterState(remoteChain), disabledConfig); + assertEq(NEW_GHO_CCIP_STEWARD.getCcipTimelocks().rateLimitLastUpdate, vm.getBlockTimestamp()); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index e5010ceaa..3b117a24d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -110,7 +110,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { function setUp() public virtual { arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 292550754); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24519153); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24685477); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21564756); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index e13945b82..f0bb9856d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -45,7 +45,7 @@ export const config: ConfigFile = { }, ], }, - cache: {blockNumber: 24519153}, + cache: {blockNumber: 24685477}, }, }, }; From c832f5ddfa37783b0ca5070af5159051a0a754a6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:54:33 +0530 Subject: [PATCH 097/123] feat: use oz v5.1 proxies --- ...eV3Arbitrum_GHOCCIP151Upgrade_20241209.sol | 16 ++++++------- ...3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol | 22 ++++++++++++------ ...AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol | 8 +++---- ...eV3Ethereum_GHOCCIP151Upgrade_20241209.sol | 16 ++++++------- ...3Ethereum_GHOCCIP151Upgrade_20241209.t.sol | 23 ++++++++++++------- .../config.ts | 4 ++-- 6 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol index 5ba8f6a8e..a1b86e1b9 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol @@ -34,24 +34,24 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://arbiscan.io/address/0xF168B83598516A532a85995b52504a2Fa058C068 IUpgradeableBurnMintTokenPool_1_4 public constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(GhoArbitrum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP - // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + // https://arbiscan.io/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB IUpgradeableBurnMintTokenPool_1_5_1 public constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); // https://arbiscan.io/address/0xcd04d93bea13921dad05240d577090b5ac36dfca address public constant EXISTING_GHO_AAVE_STEWARD = 0xCd04D93bEA13921DaD05240D577090b5AC36DfCA; - // https://arbiscan.io/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 - address public constant NEW_GHO_AAVE_STEWARD = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; + // https://arbiscan.io/address/0xd2D586f849620ef042FE3aF52eAa10e9b78bf7De + address public constant NEW_GHO_AAVE_STEWARD = 0xd2D586f849620ef042FE3aF52eAa10e9b78bf7De; // https://arbiscan.io/address/0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2 IGhoBucketSteward public constant GHO_BUCKET_STEWARD = IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); - // https://arbiscan.io/address/0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396 - address public constant NEW_GHO_CCIP_STEWARD = 0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396; + // https://arbiscan.io/address/0xCd5ab470AaC5c13e1063ee700503f3346b7C90Db + address public constant NEW_GHO_CCIP_STEWARD = 0xCd5ab470AaC5c13e1063ee700503f3346b7C90Db; // https://etherscan.io/address/0x9Ec9F9804733df96D1641666818eFb5198eC50f0 address public constant EXISTING_REMOTE_POOL_ETH = 0x9Ec9F9804733df96D1641666818eFb5198eC50f0; // ProxyPool on ETH - // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 - address public constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A + address public constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; // https://arbiscan.io/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A // https://github.com/aave/ccip/commit/ca73ec8c4f7dc0f6a99ae1ea0acde43776c7b9bb diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol index 35d0b8258..212ae0857 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.t.sol @@ -29,6 +29,7 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from './AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; @@ -61,21 +62,21 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoAaveSteward public constant EXISTING_GHO_AAVE_STEWARD = IGhoAaveSteward(0xCd04D93bEA13921DaD05240D577090b5AC36DfCA); IGhoAaveSteward public constant NEW_GHO_AAVE_STEWARD = - IGhoAaveSteward(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); + IGhoAaveSteward(0xd2D586f849620ef042FE3aF52eAa10e9b78bf7De); IGhoBucketSteward internal constant GHO_BUCKET_STEWARD = IGhoBucketSteward(0xa9afaE6A53E90f9E4CE0717162DF5Bc3d9aBe7B2); IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0xb329CEFF2c362F315900d245eC88afd24C4949D5); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396); + IGhoCcipSteward(0xCd5ab470AaC5c13e1063ee700503f3346b7C90Db); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50); IUpgradeableBurnMintTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_4(0xF168B83598516A532a85995b52504a2Fa058C068); // GhoArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); - address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); + address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 internal proposal; @@ -88,7 +89,7 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event CCIPSendRequested(IInternal.EVM2EVMMessage message); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 292550754); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 293345614); proposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -148,11 +149,11 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(IOwnable(address(NEW_GHO_AAVE_STEWARD)).owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); assertEq( NEW_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER(), - EXISTING_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER() + address(AaveV3Arbitrum.POOL_ADDRESSES_PROVIDER) ); assertEq( NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), - EXISTING_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER() + address(AaveV3Arbitrum.AAVE_PROTOCOL_DATA_PROVIDER) ); assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), EXISTING_GHO_AAVE_STEWARD.RISK_COUNCIL()); assertEq( @@ -174,6 +175,8 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { abi.encode(NEW_GHO_CCIP_STEWARD.getCcipTimelocks()), abi.encode(IGhoCcipSteward.CcipDebounce(0, 0)) ); + + assertEq(_getProxyAdmin(address(NEW_TOKEN_POOL)).UPGRADE_INTERFACE_VERSION(), '5.0.0'); } function _getTokenMessage( @@ -240,6 +243,11 @@ contract AaveV3Arbitrum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { return address(uint160(uint256(vm.load(proxy, slot)))); } + function _getProxyAdmin(address proxy) internal view returns (ProxyAdmin) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + return ProxyAdmin(address(uint160(uint256(vm.load(proxy, slot))))); + } + function _readInitialized(address proxy) internal view returns (uint8) { return uint8(uint256(vm.load(proxy, bytes32(0)))); } diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol index 33ca64691..533474dab 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3E2E_GHOCCIP151Upgrade_20241209.t.sol @@ -88,8 +88,8 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21564756); - l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 292550754); + l1.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21581477); + l2.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 293345614); vm.selectFork(l1.c.forkId); l1.proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); @@ -97,7 +97,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { 0x5756880B6a1EAba0175227bf02a7E87c1e02B28C ); // MiscEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP l1.newTokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( - 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + 0x06179f7C1be40863405f374E7f5F8806c728660A ); l1.c.router = IRouter(l1.existingTokenPool.getRouter()); l2.c.chainSelector = l1.existingTokenPool.getSupportedChains()[0]; @@ -114,7 +114,7 @@ contract AaveV3E2E_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { 0xF168B83598516A532a85995b52504a2Fa058C068 ); // MiscArbitrum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP l2.newTokenPool = IUpgradeableBurnMintTokenPool_1_5_1( - 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB ); l2.c.router = IRouter(l2.existingTokenPool.getRouter()); l1.c.chainSelector = l2.existingTokenPool.getSupportedChains()[0]; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol index bdcbf4056..9c9dd50c7 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol @@ -28,21 +28,21 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209 is IProposalGenericExecutor { // https://etherscan.io/address/0x5756880B6a1EAba0175227bf02a7E87c1e02B28C IUpgradeableLockReleaseTokenPool_1_4 public constant EXISTING_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_4(GhoEthereum.GHO_CCIP_TOKEN_POOL); // will be updated in address-book after AIP - // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A IUpgradeableLockReleaseTokenPool_1_5_1 public constant NEW_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IUpgradeableLockReleaseTokenPool_1_5_1(0x06179f7C1be40863405f374E7f5F8806c728660A); // https://etherscan.io/address/0xFEb4e54591660F42288312AE8eB59e9f2B746b66 address public constant EXISTING_GHO_AAVE_STEWARD = 0xFEb4e54591660F42288312AE8eB59e9f2B746b66; - // https://etherscan.io/address/0x6e637e1E48025E51315d50ab96d5b3be1971A715 - address public constant NEW_GHO_AAVE_STEWARD = 0x6e637e1E48025E51315d50ab96d5b3be1971A715; - // https://etherscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee - address public constant NEW_GHO_CCIP_STEWARD = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + // https://etherscan.io/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 + address public constant NEW_GHO_AAVE_STEWARD = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; + // https://etherscan.io/address/0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39 + address public constant NEW_GHO_CCIP_STEWARD = 0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39; // https://arbiscan.io/address/0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50 address public constant EXISTING_REMOTE_POOL_ARB = 0x26329558f08cbb40d6a4CCA0E0C67b29D64A8c50; // ProxyPool on Arb - // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee - address public constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + // https://arbiscan.io/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB + address public constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol index 0d7939cf6..b535de501 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol +++ b/src/20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.t.sol @@ -29,6 +29,7 @@ import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from './AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; @@ -61,19 +62,19 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { IGhoAaveSteward public constant EXISTING_GHO_AAVE_STEWARD = IGhoAaveSteward(0xFEb4e54591660F42288312AE8eB59e9f2B746b66); IGhoAaveSteward public constant NEW_GHO_AAVE_STEWARD = - IGhoAaveSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); + IGhoAaveSteward(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); IGhoCcipSteward internal constant EXISTING_GHO_CCIP_STEWARD = IGhoCcipSteward(0x101Efb7b9Beb073B1219Cd5473a7C8A2f2EB84f4); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + IGhoCcipSteward(0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39); IProxyPool internal constant EXISTING_PROXY_POOL = IProxyPool(0x9Ec9F9804733df96D1641666818eFb5198eC50f0); IUpgradeableLockReleaseTokenPool_1_4 internal constant EXISTING_TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_4(0x5756880B6a1EAba0175227bf02a7E87c1e02B28C); // GhoEthereum.GHO_CCIP_TOKEN_POOL; will be updated in address-book after AIP IUpgradeableLockReleaseTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); - address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + IUpgradeableLockReleaseTokenPool_1_5_1(0x06179f7C1be40863405f374E7f5F8806c728660A); + address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; AaveV3Ethereum_GHOCCIP151Upgrade_20241209 internal proposal; @@ -88,7 +89,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { error BridgeLimitExceeded(uint256 limit); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21564756); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21581477); proposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); // pre-req - chainlink transfers gho token pool ownership on token admin registry @@ -142,11 +143,11 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { assertEq(IOwnable(address(NEW_GHO_AAVE_STEWARD)).owner(), GovernanceV3Ethereum.EXECUTOR_LVL_1); assertEq( NEW_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER(), - EXISTING_GHO_AAVE_STEWARD.POOL_ADDRESSES_PROVIDER() + address(AaveV3Ethereum.POOL_ADDRESSES_PROVIDER) ); assertEq( NEW_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER(), - EXISTING_GHO_AAVE_STEWARD.POOL_DATA_PROVIDER() + address(AaveV3Ethereum.AAVE_PROTOCOL_DATA_PROVIDER) ); assertEq(NEW_GHO_AAVE_STEWARD.RISK_COUNCIL(), EXISTING_GHO_AAVE_STEWARD.RISK_COUNCIL()); assertEq( @@ -168,6 +169,8 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { abi.encode(NEW_GHO_CCIP_STEWARD.getCcipTimelocks()), abi.encode(IGhoCcipSteward.CcipDebounce(0, 0)) ); + + assertEq(_getProxyAdmin(address(NEW_TOKEN_POOL)).UPGRADE_INTERFACE_VERSION(), '5.0.0'); } function _getTokenMessage( @@ -248,6 +251,10 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_Base is ProtocolV3TestBase { function _readInitialized(address proxy) internal view returns (uint8) { return uint8(uint256(vm.load(proxy, bytes32(0)))); } + function _getProxyAdmin(address proxy) internal view returns (ProxyAdmin) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + return ProxyAdmin(address(uint160(uint256(vm.load(proxy, slot))))); + } function _getRateLimiterConfig() internal view returns (IRateLimiter.Config memory) { return @@ -706,7 +713,7 @@ contract AaveV3Ethereum_GHOCCIP151Upgrade_20241209_PostUpgrade is IDefaultInterestRateStrategyV2.InterestRateData memory currentRateData = IDefaultInterestRateStrategyV2.InterestRateData({ optimalUsageRatio: 99_00, - baseVariableBorrowRate: 12_50, + baseVariableBorrowRate: 11_50, variableRateSlope1: 0, variableRateSlope2: 0 }); diff --git a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts index a6c995ab9..84435de4a 100644 --- a/src/20241209_Multi_GHOCCIP151Upgrade/config.ts +++ b/src/20241209_Multi_GHOCCIP151Upgrade/config.ts @@ -11,7 +11,7 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21564756}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 292550754}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21581477}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 293345614}}, }, }; From 0510e4e15f65040aa8d914ea626743ed7ce09358 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 9 Jan 2025 00:12:08 +0530 Subject: [PATCH 098/123] upd: use latest eth/arb deployments --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 4 ++-- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 8 ++++---- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 8 ++++---- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 4 ++-- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 4 ++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 8 ++++---- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 4 ++-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 8 ++++---- src/20241223_Multi_GHOBaseLaunch/config.ts | 4 ++-- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 468294b73..96dce6c86 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -14,9 +14,9 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; - // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + // https://arbiscan.io/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E address public constant REMOTE_TOKEN_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 403ff1a19..36a409ac6 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -59,10 +59,10 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x06179f7C1be40863405f374E7f5F8806c728660A); + IGhoCcipSteward(0xCd5ab470AaC5c13e1063ee700503f3346b7C90Db); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); - address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); + address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; address internal constant NEW_REMOTE_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; AaveV3Arbitrum_GHOBaseLaunch_20241223 internal proposal; @@ -79,7 +79,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 292550754); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 293345614); _upgradeArbTo1_5_1(); proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 956f77958..d5bf66b62 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -48,10 +48,10 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://basescan.org/address/0x6e637e1E48025E51315d50ab96d5b3be1971A715 address public constant GHO_CCIP_STEWARD = 0x6e637e1E48025E51315d50ab96d5b3be1971A715; - // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 - address public constant REMOTE_TOKEN_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; - // https://arbiscan.io/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee - address public constant REMOTE_TOKEN_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A + address public constant REMOTE_TOKEN_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; + // https://arbiscan.io/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB + address public constant REMOTE_TOKEN_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index d3c04aa9d..9fb5b3139 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -76,8 +76,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IGhoCcipSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); - address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; - address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; + address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; AaveV3Base_GHOBaseLaunch_20241223 internal proposal; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 24005441d..f65f306ef 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -39,8 +39,8 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; IGhoToken internal constant GHO_TOKEN = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP - address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; - address internal constant NEW_REMOTE_POOL_ETH = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; + address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; + address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; IGhoAaveSteward internal constant NEW_GHO_AAVE_STEWARD = IGhoAaveSteward(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 3b117a24d..671d25283 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -109,9 +109,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 292550754); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 293345614); base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24685477); - eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21564756); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21581477); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); @@ -125,7 +125,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(arb.c.forkId); arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); - arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); + arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); arb.c.router = IRouter(arb.tokenPool.getRouter()); arb.c.baseOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(base.c.chainSelector)); arb.c.ethOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(eth.c.chainSelector)); @@ -148,7 +148,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(eth.c.forkId); eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( - 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + 0x06179f7C1be40863405f374E7f5F8806c728660A ); eth.c.router = IRouter(eth.tokenPool.getRouter()); eth.c.arbOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(arb.c.chainSelector)); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index c49ce5bb0..203d24b02 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -14,9 +14,9 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint64 public constant BASE_CHAIN_SELECTOR = 15971525489660198786; - // https://etherscan.io/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 + // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A IUpgradeableLockReleaseTokenPool_1_5_1 public constant TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IUpgradeableLockReleaseTokenPool_1_5_1(0x06179f7C1be40863405f374E7f5F8806c728660A); // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E address public constant REMOTE_TOKEN_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 65f2e284f..48f056554 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -56,14 +56,14 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted - address internal constant NEW_REMOTE_POOL_ARB = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; + address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; address internal constant NEW_REMOTE_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; // common across all chains IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0xFAdC082665577b533e62A7B0E067f884cA5C5E8F); + IGhoCcipSteward(0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39); IUpgradeableLockReleaseTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_5_1(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IUpgradeableLockReleaseTokenPool_1_5_1(0x06179f7C1be40863405f374E7f5F8806c728660A); AaveV3Ethereum_GHOBaseLaunch_20241223 internal proposal; @@ -79,7 +79,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21564756); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21581477); _upgradeEthTo1_5_1(); proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index f0bb9856d..776b69e59 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -13,8 +13,8 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21564756}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 292550754}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21581477}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 293345614}}, AaveV3Base: { configs: { ASSET_LISTING: [ From f2f91949fad62dcc2c2230d5f99d519a7f7b3105 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 9 Jan 2025 01:02:33 +0530 Subject: [PATCH 099/123] feat: predeploy gho token --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 8 +-- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 4 +- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 61 +++++-------------- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 41 +++++-------- .../AaveV3Base_GHOBaseListing_20241223.sol | 6 +- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 14 ++--- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 27 ++------ .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 8 +-- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 4 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 4 +- 10 files changed, 59 insertions(+), 118 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 96dce6c86..39fc5696d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -18,10 +18,10 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); - // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E - address public constant REMOTE_TOKEN_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; - // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D - address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + // https://basescan.org/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 + address public constant REMOTE_TOKEN_POOL_BASE = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; + // https://basescan.org/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + address public constant REMOTE_GHO_TOKEN_BASE = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 36a409ac6..0fc21c4cb 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -56,14 +56,14 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5(0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b); address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; - address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + address public constant NEW_REMOTE_TOKEN_BASE = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; IRouter internal constant ROUTER = IRouter(0x141fa059441E0ca23ce184B6A78bafD2A517DdE8); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = IGhoCcipSteward(0xCd5ab470AaC5c13e1063ee700503f3346b7C90Db); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; - address internal constant NEW_REMOTE_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; + address internal constant NEW_REMOTE_POOL_BASE = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; AaveV3Arbitrum_GHOBaseLaunch_20241223 internal proposal; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index d5bf66b62..929ba2a3c 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -1,9 +1,6 @@ // SPDX-License-Identifier: MIT 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 {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; @@ -12,7 +9,6 @@ import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; -import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; @@ -32,21 +28,19 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://basescan.org/address/0x6f6C373d09C07425BaAE72317863d7F6bb731e37 ITokenAdminRegistry public constant TOKEN_ADMIN_REGISTRY = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); - // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E + // https://basescan.org/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); + IUpgradeableBurnMintTokenPool_1_5_1(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); - // https://basescan.org/address/0x26d595dddbad81bf976ef6f24686a12a800b141f - address public constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - // predicted address, will be deployed in the AIP, https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D - IGhoToken public constant GHO_TOKEN_PROXY = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); + // https://basescan.org/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + IGhoToken public constant GHO_TOKEN = IGhoToken(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); - // https://basescan.org/address/0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6 - address public constant GHO_AAVE_STEWARD = 0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6; - // https://basescan.org/address/0xA5Ba213867E175A182a5dd6A9193C6158738105A - address public constant GHO_BUCKET_STEWARD = 0xA5Ba213867E175A182a5dd6A9193C6158738105A; - // https://basescan.org/address/0x6e637e1E48025E51315d50ab96d5b3be1971A715 - address public constant GHO_CCIP_STEWARD = 0x6e637e1E48025E51315d50ab96d5b3be1971A715; + // https://basescan.org/address/0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39 + address public constant GHO_AAVE_STEWARD = 0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39; + // https://basescan.org/address/0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396 + address public constant GHO_BUCKET_STEWARD = 0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396; + // https://basescan.org/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB + address public constant GHO_CCIP_STEWARD = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A address public constant REMOTE_TOKEN_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; @@ -60,50 +54,27 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { function execute() external { _acceptOwnership(); - _deployAndInitializeGhoToken(); _setupStewardsAndTokenPoolOnGho(); _setupRemoteAndRegisterTokenPool(); } function _acceptOwnership() internal { - TOKEN_ADMIN_REGISTRY.acceptAdminRole(address(GHO_TOKEN_PROXY)); + TOKEN_ADMIN_REGISTRY.acceptAdminRole(address(GHO_TOKEN)); TOKEN_POOL.acceptOwnership(); } - function _deployAndInitializeGhoToken() internal { - address ghoTokenProxy = address( - new TransparentUpgradeableProxy{salt: keccak256('based-GHO')}( - GHO_TOKEN_IMPL, - ProxyAdmin(MiscBase.PROXY_ADMIN), - abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) - ) - ); - // burn all gas, assert predicted address match - assert(ghoTokenProxy == address(GHO_TOKEN_PROXY)); - } - function _setupStewardsAndTokenPoolOnGho() internal { - GHO_TOKEN_PROXY.grantRole( - GHO_TOKEN_PROXY.FACILITATOR_MANAGER_ROLE(), - GovernanceV3Base.EXECUTOR_LVL_1 - ); - GHO_TOKEN_PROXY.grantRole( - GHO_TOKEN_PROXY.BUCKET_MANAGER_ROLE(), - GovernanceV3Base.EXECUTOR_LVL_1 - ); + GHO_TOKEN.grantRole(GHO_TOKEN.FACILITATOR_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); + GHO_TOKEN.grantRole(GHO_TOKEN.BUCKET_MANAGER_ROLE(), GovernanceV3Base.EXECUTOR_LVL_1); // Token Pool as facilitator with 20M GHO capacity - GHO_TOKEN_PROXY.addFacilitator( - address(TOKEN_POOL), - 'CCIP TokenPool v1.5.1', - CCIP_BUCKET_CAPACITY - ); + GHO_TOKEN.addFacilitator(address(TOKEN_POOL), 'CCIP TokenPool v1.5.1', CCIP_BUCKET_CAPACITY); // Gho Aave Steward AaveV3Base.ACL_MANAGER.grantRole(AaveV3Base.ACL_MANAGER.RISK_ADMIN_ROLE(), GHO_AAVE_STEWARD); // Gho Bucket Steward - GHO_TOKEN_PROXY.grantRole(GHO_TOKEN_PROXY.BUCKET_MANAGER_ROLE(), GHO_BUCKET_STEWARD); + GHO_TOKEN.grantRole(GHO_TOKEN.BUCKET_MANAGER_ROLE(), GHO_BUCKET_STEWARD); address[] memory facilitatorList = new address[](1); facilitatorList[0] = address(TOKEN_POOL); IGhoBucketSteward(GHO_BUCKET_STEWARD).setControlledFacilitator({ @@ -156,6 +127,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { }); // register token pool - TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN_PROXY), address(TOKEN_POOL)); + TOKEN_ADMIN_REGISTRY.setPool(address(GHO_TOKEN), address(TOKEN_POOL)); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 9fb5b3139..f2c0889a8 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -23,10 +23,9 @@ import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; -import {MiscBase} from 'aave-address-book/MiscBase.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; -import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; @@ -64,18 +63,17 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IRouter internal constant ROUTER = IRouter(0x881e3A65B4d4a04dD529061dd0071cf975F58bCD); address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; - address internal constant GHO_TOKEN_IMPL = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; - IGhoToken internal constant GHO = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + IGhoToken internal constant GHO = IGhoToken(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; IGhoAaveSteward internal constant NEW_GHO_AAVE_STEWARD = - IGhoAaveSteward(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IGhoAaveSteward(0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39); IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = - IGhoBucketSteward(0xA5Ba213867E175A182a5dd6A9193C6158738105A); + IGhoBucketSteward(0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); + IGhoCcipSteward(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); + IUpgradeableBurnMintTokenPool_1_5_1(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; @@ -93,7 +91,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24685477); + vm.createSelectFork(vm.rpcUrl('base'), 24787260); proposal = new AaveV3Base_GHOBaseLaunch_20241223(); _performCcipPreReq(); @@ -111,8 +109,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { assertEq(proposal.CCIP_BUCKET_CAPACITY(), 20_000_000e18); assertEq(address(proposal.TOKEN_ADMIN_REGISTRY()), address(TOKEN_ADMIN_REGISTRY)); assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); - assertEq(proposal.GHO_TOKEN_IMPL(), GHO_TOKEN_IMPL); - assertEq(address(proposal.GHO_TOKEN_PROXY()), address(GHO)); + assertEq(address(proposal.GHO_TOKEN()), address(GHO)); assertEq(proposal.GHO_AAVE_STEWARD(), address(NEW_GHO_AAVE_STEWARD)); assertEq(proposal.GHO_BUCKET_STEWARD(), address(NEW_GHO_BUCKET_STEWARD)); assertEq(proposal.GHO_CCIP_STEWARD(), address(NEW_GHO_CCIP_STEWARD)); @@ -130,21 +127,8 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { _assertOffRamp(ARB_OFF_RAMP, ARB_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); _assertOffRamp(ETH_OFF_RAMP, ETH_CHAIN_SELECTOR, BASE_CHAIN_SELECTOR, ROUTER); - address computedGhoTokenAddress = vm.computeCreate2Address({ - salt: keccak256('based-GHO'), - initCodeHash: keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - address(GHO_TOKEN_IMPL), - MiscBase.PROXY_ADMIN, - abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) - ) - ) - ), - deployer: GovernanceV3Base.EXECUTOR_LVL_1 - }); - assertEq(address(GHO), computedGhoTokenAddress); + assertEq(_getProxyAdmin(address(GHO)).UPGRADE_INTERFACE_VERSION(), '5.0.0'); + assertEq(_getProxyAdmin(address(NEW_TOKEN_POOL)).UPGRADE_INTERFACE_VERSION(), '5.0.0'); } function _assertOnRamp( @@ -222,6 +206,11 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { return address(uint160(uint256(vm.load(proxy, slot)))); } + function _getProxyAdmin(address proxy) internal view returns (ProxyAdmin) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + return ProxyAdmin(address(uint160(uint256(vm.load(proxy, slot))))); + } + function _readInitialized(address proxy) internal view returns (uint8) { return uint8(uint256(vm.load(proxy, bytes32(0)))); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol index 12931f62f..cc379fbac 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol @@ -22,11 +22,11 @@ contract AaveV3Base_GHOBaseListing_20241223 is AaveV3PayloadBase { address public constant EMISSION_ADMIN = 0xac140648435d03f784879cd789130F22Ef588Fcd; // https://basescan.org/address/0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73 address public constant GHO_PRICE_FEED = 0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73; - // predicted address, will be deployed in the launch AIP, https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D - address public constant GHO_TOKEN = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; + // https://basescan.org/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + address public constant GHO_TOKEN = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; uint256 public constant GHO_SEED_AMOUNT = 1e18; - function _preExecute() internal override { + function _preExecute() internal view override { // robot should simulate and only execute if seed amount has been bridged assert(IERC20(GHO_TOKEN).balanceOf(address(this)) >= GHO_SEED_AMOUNT); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index f65f306ef..86683ab28 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -38,20 +38,20 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { address internal constant ROUTER = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; address internal constant RMN_PROXY = 0xC842c69d54F83170C42C4d556B4F6B2ca53Dd3E8; address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; - IGhoToken internal constant GHO_TOKEN = IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + IGhoToken internal constant GHO_TOKEN = IGhoToken(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; address internal constant NEW_REMOTE_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; IGhoAaveSteward internal constant NEW_GHO_AAVE_STEWARD = - IGhoAaveSteward(0x20fd5f3FCac8883a3A0A2bBcD658A2d2c6EFa6B6); + IGhoAaveSteward(0xC5BcC58BE6172769ca1a78B8A45752E3C5059c39); IGhoBucketSteward internal constant NEW_GHO_BUCKET_STEWARD = - IGhoBucketSteward(0xA5Ba213867E175A182a5dd6A9193C6158738105A); + IGhoBucketSteward(0x3c47237479e7569653eF9beC4a7Cd2ee3F78b396); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = - IGhoCcipSteward(0x6e637e1E48025E51315d50ab96d5b3be1971A715); + IGhoCcipSteward(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); IUpgradeableBurnMintTokenPool_1_5_1 internal constant NEW_TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0xDe6539018B095353A40753Dc54C91C68c9487D4E); + IUpgradeableBurnMintTokenPool_1_5_1(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24685477); + vm.createSelectFork(vm.rpcUrl('base'), 24787260); proposal = new AaveV3Base_GHOBaseListing_20241223(); } @@ -88,7 +88,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { function assertEq( IDefaultInterestRateStrategyV2.InterestRateData memory a, IDefaultInterestRateStrategyV2.InterestRateData memory b - ) internal { + ) internal pure { assertEq(a.optimalUsageRatio, b.optimalUsageRatio); assertEq(a.baseVariableBorrowRate, b.baseVariableBorrowRate); assertEq(a.variableRateSlope1, b.variableRateSlope1); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 671d25283..948119b22 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -86,7 +86,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { address internal constant ROUTER_BASE = 0x881e3A65B4d4a04dD529061dd0071cf975F58bCD; address internal constant GHO_TOKEN_IMPL_BASE = 0xb0e1c7830aA781362f79225559Aa068E6bDaF1d1; IGhoToken internal constant GHO_TOKEN_BASE = - IGhoToken(0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D); // predicted address, will be deployed in the AIP + IGhoToken(0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee); uint256 internal constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; uint256 internal constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; @@ -110,7 +110,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { function setUp() public virtual { arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 293345614); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24685477); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24787260); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21581477); arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); @@ -135,7 +135,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { vm.selectFork(base.c.forkId); base.proposal = new AaveV3Base_GHOBaseLaunch_20241223(); base.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1( - 0xDe6539018B095353A40753Dc54C91C68c9487D4E + 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 ); base.c.tokenAdminRegistry = ITokenAdminRegistry(0x6f6C373d09C07425BaAE72317863d7F6bb731e37); base.c.token = GHO_TOKEN_BASE; @@ -301,8 +301,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { _assertSetRateLimit(arb.c, address(arb.tokenPool)); vm.selectFork(base.c.forkId); - assertEq(base.proposal.GHO_TOKEN_IMPL(), _getImplementation(address(base.c.token))); - assertEq(address(base.proposal.GHO_TOKEN_PROXY()), address(base.c.token)); + assertEq(address(base.proposal.GHO_TOKEN()), address(base.c.token)); assertEq(base.c.tokenAdminRegistry.getPool(address(base.c.token)), address(base.tokenPool)); assertEq(base.tokenPool.getSupportedChains()[0], eth.c.chainSelector); assertEq(base.tokenPool.getSupportedChains()[1], arb.c.chainSelector); @@ -346,24 +345,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { abi.encode(address(base.tokenPool)) ); _assertSetRateLimit(eth.c, address(eth.tokenPool)); - } else { - vm.selectFork(base.c.forkId); - // correct gho Token Address - address computedGhoTokenAddress = vm.computeCreate2Address({ - salt: keccak256('based-GHO'), - initCodeHash: keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - address(GHO_TOKEN_IMPL_BASE), - MiscBase.PROXY_ADMIN, - abi.encodeCall(IGhoToken.initialize, (GovernanceV3Base.EXECUTOR_LVL_1)) - ) - ) - ), - deployer: address(GovernanceV3Base.EXECUTOR_LVL_1) - }); - assertEq(address(base.proposal.GHO_TOKEN_PROXY()), computedGhoTokenAddress); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index 203d24b02..c6dea545d 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -18,10 +18,10 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { IUpgradeableLockReleaseTokenPool_1_5_1 public constant TOKEN_POOL = IUpgradeableLockReleaseTokenPool_1_5_1(0x06179f7C1be40863405f374E7f5F8806c728660A); - // https://basescan.org/address/0xDe6539018B095353A40753Dc54C91C68c9487D4E - address public constant REMOTE_TOKEN_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; - // https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D - address public constant REMOTE_GHO_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + // https://basescan.org/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 + address public constant REMOTE_TOKEN_POOL_BASE = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; + // https://basescan.org/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee + address public constant REMOTE_GHO_TOKEN_BASE = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 48f056554..1b85cff7b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -55,9 +55,9 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IEVM2EVMOffRamp_1_5 internal constant BASE_OFF_RAMP = IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); - address public constant NEW_REMOTE_TOKEN_BASE = 0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D; // predicted + address public constant NEW_REMOTE_TOKEN_BASE = 0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee; address internal constant NEW_REMOTE_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; - address internal constant NEW_REMOTE_POOL_BASE = 0xDe6539018B095353A40753Dc54C91C68c9487D4E; + address internal constant NEW_REMOTE_POOL_BASE = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; address internal constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; // common across all chains IRouter internal constant ROUTER = IRouter(0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D); IGhoCcipSteward internal constant NEW_GHO_CCIP_STEWARD = diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 776b69e59..9d48d4f08 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -40,12 +40,12 @@ export const config: ConfigFile = { variableRateSlope1: '12', variableRateSlope2: '65', }, - asset: '0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D', + asset: '0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee', admin: '0xac140648435d03f784879cd789130F22Ef588Fcd', }, ], }, - cache: {blockNumber: 24685477}, + cache: {blockNumber: 24787260}, }, }, }; From 6f36d41e85b351e2c65b9e409a5e562de39cff31 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:33:06 +0530 Subject: [PATCH 100/123] doc: upd md with new token --- ...223_before_AaveV3Base_GHOBaseListing_20241223_after.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md index 392d1217f..54dc91605 100644 --- a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md +++ b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md @@ -2,7 +2,7 @@ ### Reserves added -#### GHO ([0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D](https://basescan.org/address/0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D)) +#### GHO ([0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee](https://basescan.org/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee)) | description | value | | --- | --- | @@ -52,7 +52,7 @@ ```json { "reserves": { - "0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D": { + "0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee": { "from": null, "to": { "aToken": "0xDD5745756C2de109183c6B5bB886F9207bEF114D", @@ -82,7 +82,7 @@ "reserveFactor": 1000, "supplyCap": 2500000, "symbol": "GHO", - "underlying": "0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D", + "underlying": "0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee", "usageAsCollateralEnabled": false, "variableDebtToken": "0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd", "variableDebtTokenImpl": "0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1", @@ -94,7 +94,7 @@ } }, "strategies": { - "0x6F2216CB3Ca97b8756C5fD99bE27986f04CBd81D": { + "0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee": { "from": null, "to": { "address": "0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5", From 0a1655d16cd2ae3fa28bd28bc5f07d084d16e36c Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:01:13 +0530 Subject: [PATCH 101/123] feat: update gho token proxyAdmin --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 13 +++++ ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 57 +++++++++++++++++-- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 2 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 2 +- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 39fc5696d..93b5655fb 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -4,6 +4,10 @@ pragma solidity ^0.8.0; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {ILegacyProxyAdmin, ITransparentUpgradeableProxy} from 'src/interfaces/ILegacyProxyAdmin.sol'; + +import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; /** * @title GHO Base Launch @@ -18,6 +22,9 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); + // https://arbiscan.io/address/0x9f0e4F4c5664888442E459f40f635765BB6265Ec + address public constant NEW_GHO_TOKEN_PROXY_ADMIN = 0x9f0e4F4c5664888442E459f40f635765BB6265Ec; + // https://basescan.org/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 address public constant REMOTE_TOKEN_POOL_BASE = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; // https://basescan.org/address/0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee @@ -29,6 +36,12 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { uint128 public constant CCIP_RATE_LIMIT_REFILL_RATE = 60e18; function execute() external { + // Update ProxyAdmin on GHO + ILegacyProxyAdmin(MiscArbitrum.PROXY_ADMIN).changeProxyAdmin( + ITransparentUpgradeableProxy(AaveV3ArbitrumAssets.GHO_UNDERLYING), + NEW_GHO_TOKEN_PROXY_ADMIN + ); + IRateLimiter.Config memory rateLimiterConfig = IRateLimiter.Config({ isEnabled: true, capacity: CCIP_RATE_LIMIT_CAPACITY, diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 0fc21c4cb..086fec51a 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -20,6 +20,9 @@ import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; +import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; + +import {ProxyAdmin, ITransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; @@ -30,7 +33,7 @@ import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLau * @dev Test for AaveV3Arbitrum_GHOBaseLaunch_20241223 * command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol -vv */ -contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { +contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { struct CCIPSendParams { address sender; uint256 amount; @@ -78,15 +81,12 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error CallerIsNotARampOnRouter(address); error InvalidSourcePoolAddress(bytes); - function setUp() public { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 293345614); + function setUp() public virtual { + vm.createSelectFork(vm.rpcUrl('arbitrum'), 293582704); _upgradeArbTo1_5_1(); proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); _validateConstants(); - - // execute proposal - executePayload(vm, address(proposal)); } function _upgradeArbTo1_5_1() internal { @@ -120,6 +120,10 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN(), AaveV3ArbitrumAssets.GHO_UNDERLYING); assertEq(NEW_GHO_CCIP_STEWARD.GHO_TOKEN_POOL(), address(NEW_TOKEN_POOL)); assertFalse(NEW_GHO_CCIP_STEWARD.BRIDGE_LIMIT_ENABLED()); + + ProxyAdmin newProxyAdmin = ProxyAdmin(proposal.NEW_GHO_TOKEN_PROXY_ADMIN()); + assertEq(newProxyAdmin.owner(), GovernanceV3Arbitrum.EXECUTOR_LVL_1); + assertEq(newProxyAdmin.UPGRADE_INTERFACE_VERSION(), '5.0.0'); } function _assertOnRamp( @@ -197,6 +201,11 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { return address(uint160(uint256(vm.load(proxy, slot)))); } + function _getProxyAdmin(address proxy) internal view returns (address) { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + return address(uint160(uint256(vm.load(proxy, slot)))); + } + function _readInitialized(address proxy) internal view returns (uint8) { return uint8(uint256(vm.load(proxy, bytes32(0)))); } @@ -228,6 +237,42 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { ) internal pure { assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); } +} + +contract AaveV3Arbitrum_GHOBaseLaunch_20241223_PreExecution is + AaveV3Arbitrum_GHOBaseLaunch_20241223_Base +{ + function test_ghoTokenProxyAdminUpgrade() public { + assertEq(_getProxyAdmin(address(GHO)), MiscArbitrum.PROXY_ADMIN); + executePayload(vm, address(proposal)); + assertEq(_getProxyAdmin(address(GHO)), proposal.NEW_GHO_TOKEN_PROXY_ADMIN()); + } + + function test_ghoProxyAdminCanUpgradeImplementation() public { + executePayload(vm, address(proposal)); + address miscImpl = makeAddr('miscImpl'); + vm.etch(miscImpl, hex'602060005260205ff3'); // ret 0x20 + vm.startPrank(GovernanceV3Arbitrum.EXECUTOR_LVL_1); + ProxyAdmin(proposal.NEW_GHO_TOKEN_PROXY_ADMIN()).upgradeAndCall( + ITransparentUpgradeableProxy(address(GHO)), + miscImpl, + '' + ); + assertEq(_getImplementation(address(GHO)), miscImpl); + (bool ok, bytes memory ret) = address(GHO).call(hex''); + assertTrue(ok); + assertEq(abi.decode(ret, (uint8)), 32); + } +} + +contract AaveV3Arbitrum_GHOBaseLaunch_20241223_PostExecution is + AaveV3Arbitrum_GHOBaseLaunch_20241223_Base +{ + function setUp() public override { + super.setUp(); + // execute proposal + executePayload(vm, address(proposal)); + } function test_basePoolConfig() public view { assertEq(NEW_TOKEN_POOL.getSupportedChains().length, 2); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 948119b22..76592c84f 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -109,7 +109,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 293345614); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 293582704); base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24787260); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21581477); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 9d48d4f08..1dd51523c 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -14,7 +14,7 @@ export const config: ConfigFile = { }, poolOptions: { AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21581477}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 293345614}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 293582704}}, AaveV3Base: { configs: { ASSET_LISTING: [ From 86c3cda1d75d98f9a83993012aa5965a6ee01995 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:08:32 +0530 Subject: [PATCH 102/123] test: simplify --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 086fec51a..1cac929df 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -251,7 +251,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_PreExecution is function test_ghoProxyAdminCanUpgradeImplementation() public { executePayload(vm, address(proposal)); address miscImpl = makeAddr('miscImpl'); - vm.etch(miscImpl, hex'602060005260205ff3'); // ret 0x20 + vm.etch(miscImpl, hex'00'); // stop opcode vm.startPrank(GovernanceV3Arbitrum.EXECUTOR_LVL_1); ProxyAdmin(proposal.NEW_GHO_TOKEN_PROXY_ADMIN()).upgradeAndCall( ITransparentUpgradeableProxy(address(GHO)), @@ -259,9 +259,6 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_PreExecution is '' ); assertEq(_getImplementation(address(GHO)), miscImpl); - (bool ok, bytes memory ret) = address(GHO).call(hex''); - assertTrue(ok); - assertEq(abi.decode(ret, (uint8)), 32); } } From cde38c66387816caea57234cd588e3529fe8367f Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:21:09 +0530 Subject: [PATCH 103/123] chore: minor cleanup nits --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 6 +++--- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 5 +++-- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 4 +++- .../AaveV3Base_GHOBaseListing_20241223.sol | 2 +- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 6 +++--- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 9 ++++++--- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index 93b5655fb..ce0dcaf5b 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -49,12 +49,12 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { }); IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[] - memory chains = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](1); + memory chainsToAdd = new IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate[](1); bytes[] memory remotePoolAddresses = new bytes[](1); remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_BASE); - chains[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ + chainsToAdd[0] = IUpgradeableBurnMintTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: BASE_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(REMOTE_GHO_TOKEN_BASE), @@ -64,7 +64,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { TOKEN_POOL.applyChainUpdates({ remoteChainSelectorsToRemove: new uint64[](0), - chainsToAdd: chains + chainsToAdd: chainsToAdd }); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 1cac929df..232520f54 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -235,7 +235,9 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config ) internal pure { - assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + assertEq(bucket.isEnabled, config.isEnabled); + assertEq(bucket.capacity, config.capacity); + assertEq(bucket.rate, config.rate); } } @@ -267,7 +269,6 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_PostExecution is { function setUp() public override { super.setUp(); - // execute proposal executePayload(vm, address(proposal)); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index f2c0889a8..336ec0760 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -240,7 +240,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config ) internal pure { - assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + assertEq(bucket.isEnabled, config.isEnabled); + assertEq(bucket.capacity, config.capacity); + assertEq(bucket.rate, config.rate); } } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol index cc379fbac..fc7259504 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol @@ -27,7 +27,7 @@ contract AaveV3Base_GHOBaseListing_20241223 is AaveV3PayloadBase { uint256 public constant GHO_SEED_AMOUNT = 1e18; function _preExecute() internal view override { - // robot should simulate and only execute if seed amount has been bridged + // robot should simulate and only execute if seed amount has been bridged, redundant check assert(IERC20(GHO_TOKEN).balanceOf(address(this)) >= GHO_SEED_AMOUNT); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 86683ab28..7cffff798 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -107,15 +107,15 @@ contract AaveV3Base_GHOBaseListing_20241223_ListingPreRequisites is } function test_listingFailsPreLaunch() public { - vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // gho token not deployed, reverts on token.decimals() check + vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); } function test_listingFailsWithoutSeedAmount() public { test_listingFailsPreLaunch(); - _executeLaunchAIP(); // deploys gho token, token pool & stewards + _executeLaunchAIP(); // activates CCIP lane - vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // seed amount has not been bridged yet, reverts on _preExecute() + vm.expectRevert(bytes(Errors.FAILED_ACTION_EXECUTION)); // assertion failed on _preExecute() GovernanceV3Base.PAYLOADS_CONTROLLER.executePayload(payloadId); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index c6dea545d..c43ce70ca 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -36,12 +36,12 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { }); IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[] - memory chains = new IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[](1); + memory chainsToAdd = new IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate[](1); bytes[] memory remotePoolAddresses = new bytes[](1); remotePoolAddresses[0] = abi.encode(REMOTE_TOKEN_POOL_BASE); - chains[0] = IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate({ + chainsToAdd[0] = IUpgradeableLockReleaseTokenPool_1_5_1.ChainUpdate({ remoteChainSelector: BASE_CHAIN_SELECTOR, remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(REMOTE_GHO_TOKEN_BASE), @@ -49,6 +49,9 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { inboundRateLimiterConfig: rateLimiterConfig }); - TOKEN_POOL.applyChainUpdates(new uint64[](0), chains); + TOKEN_POOL.applyChainUpdates({ + remoteChainSelectorsToRemove: new uint64[](0), + chainsToAdd: chainsToAdd + }); } } From 1e54a33d6660c4fc376889d652644cb24600344b Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:49:46 +0530 Subject: [PATCH 104/123] chore: resolve conflicts --- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 4 +++- src/interfaces/IGhoToken.sol | 17 ----------------- src/interfaces/ccip/IEVM2EVMOnRamp.sol | 11 ----------- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 1b85cff7b..2428d97da 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -226,7 +226,9 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { IRateLimiter.TokenBucket memory bucket, IRateLimiter.Config memory config ) internal pure { - assertEq(abi.encode(_tokenBucketToConfig(bucket)), abi.encode(config)); + assertEq(bucket.isEnabled, config.isEnabled); + assertEq(bucket.capacity, config.capacity); + assertEq(bucket.rate, config.rate); } function test_basePoolConfig() public view { diff --git a/src/interfaces/IGhoToken.sol b/src/interfaces/IGhoToken.sol index 8bca6b3a4..db432b820 100644 --- a/src/interfaces/IGhoToken.sol +++ b/src/interfaces/IGhoToken.sol @@ -29,23 +29,6 @@ interface IGhoToken is IERC20 { */ function burn(uint256 amount) external; - /** - * @notice Mints the requested amount of tokens to the account address. - * @dev Only facilitators with enough bucket capacity available can mint. - * @dev The bucket level is increased upon minting. - * @param account The address receiving the GHO tokens - * @param amount The amount to mint - */ - function mint(address account, uint256 amount) external; - - /** - * @notice Burns the requested amount of tokens from the account address. - * @dev Only active facilitators (bucket level > 0) can burn. - * @dev The bucket level is decreased upon burning. - * @param amount The amount to burn - */ - function burn(uint256 amount) external; - /** * @notice Add the facilitator passed with the parameters to the facilitators list. * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function diff --git a/src/interfaces/ccip/IEVM2EVMOnRamp.sol b/src/interfaces/ccip/IEVM2EVMOnRamp.sol index 464731755..f4521ff76 100644 --- a/src/interfaces/ccip/IEVM2EVMOnRamp.sol +++ b/src/interfaces/ccip/IEVM2EVMOnRamp.sol @@ -46,17 +46,6 @@ interface IEVM2EVMOnRamp is ITypeAndVersion { bool enforceOutOfOrder; // ──────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. } - struct StaticConfig { - address linkToken; // ────────╮ Link token address - uint64 chainSelector; // ─────╯ Source chainSelector - uint64 destChainSelector; // ─╮ Destination chainSelector - uint64 defaultTxGasLimit; // │ Default gas limit for a tx - uint96 maxNopFeesJuels; // ───╯ Max nop fee balance onramp can have - address prevOnRamp; // Address of previous-version OnRamp - address rmnProxy; // Address of RMN proxy - address tokenAdminRegistry; // Address of the token admin registry - } - /// @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); From 3e6f628f85d0f27743afe31a2bd00753fe917187 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:22:47 +0530 Subject: [PATCH 105/123] fix: update blocks, cleanup on pre-requisites --- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 17 ++--- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 5 +- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 67 ++++--------------- ...aveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 20 ++---- src/20241223_Multi_GHOBaseLaunch/config.ts | 6 +- 6 files changed, 27 insertions(+), 90 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 232520f54..3c1cc9999 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -82,21 +82,14 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 293582704); - _upgradeArbTo1_5_1(); - proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); + vm.createSelectFork(vm.rpcUrl('arbitrum'), 298375852); - _validateConstants(); - } + // pre-requisite, to be removed after execution + executePayload(vm, address(new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209())); - function _upgradeArbTo1_5_1() internal { - AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); - vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Arbitrum.EXECUTOR_LVL_1); - upgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); - vm.stopPrank(); + proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); - executePayload(vm, address(upgradeProposal)); + _validateConstants(); } function _validateConstants() private view { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 336ec0760..22edf8bdd 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -91,7 +91,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24787260); + vm.createSelectFork(vm.rpcUrl('base'), 25415842); proposal = new AaveV3Base_GHOBaseLaunch_20241223(); _performCcipPreReq(); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 7cffff798..69ef16ed3 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -51,14 +51,11 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { IUpgradeableBurnMintTokenPool_1_5_1(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 24787260); + vm.createSelectFork(vm.rpcUrl('base'), 25415842); proposal = new AaveV3Base_GHOBaseListing_20241223(); } function _executeLaunchAIP() internal { - // CLL pre-requisite - vm.prank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO_TOKEN), GovernanceV3Base.EXECUTOR_LVL_1); executePayload(vm, address(new AaveV3Base_GHOBaseLaunch_20241223())); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 76592c84f..f4abbf486 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -20,17 +20,12 @@ import {IGhoAaveSteward} from 'src/interfaces/IGhoAaveSteward.sol'; import {IGhoBucketSteward} from 'src/interfaces/IGhoBucketSteward.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; -import {MiscBase} from 'aave-address-book/MiscBase.sol'; -import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; -import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; -import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; -import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; - import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; @@ -109,23 +104,21 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 293582704); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 24787260); - eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21581477); - - arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); - arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); - eth.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); - eth.c.token = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); - _upgradeEthArbTo1_5_1(); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 298375852); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 25415842); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21686002); arb.c.chainSelector = 4949039107694359620; base.c.chainSelector = 15971525489660198786; eth.c.chainSelector = 5009297550715157269; vm.selectFork(arb.c.forkId); + // pre-requisite, to be removed after execution + executePayload(vm, address(new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209())); arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); + arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); + arb.c.tokenAdminRegistry = ITokenAdminRegistry(0x39AE1032cF4B334a1Ed41cdD0833bdD7c7E7751E); arb.c.router = IRouter(arb.tokenPool.getRouter()); arb.c.baseOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(base.c.chainSelector)); arb.c.ethOnRamp = IEVM2EVMOnRamp(arb.c.router.getOnRamp(eth.c.chainSelector)); @@ -146,59 +139,23 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { base.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0xCA04169671A81E4fB8768cfaD46c347ae65371F1); vm.selectFork(eth.c.forkId); + // pre-requisite, to be removed after execution + executePayload(vm, address(new AaveV3Ethereum_GHOCCIP151Upgrade_20241209())); eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); + eth.c.token = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( 0x06179f7C1be40863405f374E7f5F8806c728660A ); + eth.c.tokenAdminRegistry = ITokenAdminRegistry(0xb22764f98dD05c789929716D677382Df22C05Cb6); eth.c.router = IRouter(eth.tokenPool.getRouter()); eth.c.arbOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(arb.c.chainSelector)); eth.c.baseOnRamp = IEVM2EVMOnRamp(eth.c.router.getOnRamp(base.c.chainSelector)); eth.c.arbOffRamp = IEVM2EVMOffRamp_1_5(0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9); eth.c.baseOffRamp = IEVM2EVMOffRamp_1_5(0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD); - _performCLLPreReq(base.c, GovernanceV3Base.EXECUTOR_LVL_1); - _validateConfig({executed: false}); } - function _upgradeEthArbTo1_5_1() internal returns (address, address) { - vm.selectFork(eth.c.forkId); - - // execute CLL pre-requisites for the proposal - vm.startPrank(eth.c.tokenAdminRegistry.owner()); - AaveV3Ethereum_GHOCCIP151Upgrade_20241209 ethUpgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); - ethUpgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); - eth.c.tokenAdminRegistry.transferAdminRole( - address(eth.c.token), - GovernanceV3Ethereum.EXECUTOR_LVL_1 - ); - vm.stopPrank(); - executePayload(vm, address(ethUpgradeProposal)); - - vm.selectFork(arb.c.forkId); - // execute CLL pre-requisites for the proposal - AaveV3Arbitrum_GHOCCIP151Upgrade_20241209 arbUpgradeProposal = new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209(); - vm.startPrank(arb.c.tokenAdminRegistry.owner()); - arbUpgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Arbitrum.EXECUTOR_LVL_1); - arb.c.tokenAdminRegistry.transferAdminRole( - address(arb.c.token), - GovernanceV3Arbitrum.EXECUTOR_LVL_1 - ); - vm.stopPrank(); - executePayload(vm, address(arbUpgradeProposal)); - } - - function _performCLLPreReq(Common memory c, address newAdmin) internal { - vm.selectFork(c.forkId); - - vm.prank(c.tokenAdminRegistry.owner()); - if (c.forkId == base.c.forkId) { - c.tokenAdminRegistry.proposeAdministrator(address(c.token), newAdmin); - } else { - c.tokenAdminRegistry.transferAdminRole(address(c.token), newAdmin); - } - } - function _getTokenMessage( CCIPSendParams memory params ) internal returns (IClient.EVM2AnyMessage memory, IInternal.EVM2EVMMessage memory) { diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 2428d97da..2271b0c66 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -16,7 +16,6 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {IGhoCcipSteward} from 'src/interfaces/IGhoCcipSteward.sol'; import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; -import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; @@ -79,26 +78,17 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21581477); - _upgradeEthTo1_5_1(); - proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); + vm.createSelectFork(vm.rpcUrl('mainnet'), 21686002); + + // pre-requisite, to be removed after execution + executePayload(vm, address(new AaveV3Ethereum_GHOCCIP151Upgrade_20241209())); + proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); _validateConstants(); - // execute proposal executePayload(vm, address(proposal)); } - function _upgradeEthTo1_5_1() internal { - AaveV3Ethereum_GHOCCIP151Upgrade_20241209 upgradeProposal = new AaveV3Ethereum_GHOCCIP151Upgrade_20241209(); - vm.startPrank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.transferAdminRole(address(GHO), GovernanceV3Ethereum.EXECUTOR_LVL_1); - upgradeProposal.EXISTING_PROXY_POOL().transferOwnership(GovernanceV3Ethereum.EXECUTOR_LVL_1); - vm.stopPrank(); - - executePayload(vm, address(upgradeProposal)); - } - function _validateConstants() private view { assertEq(proposal.BASE_CHAIN_SELECTOR(), BASE_CHAIN_SELECTOR); assertEq(address(proposal.TOKEN_POOL()), address(NEW_TOKEN_POOL)); diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 1dd51523c..bccd88a15 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -13,8 +13,8 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21581477}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 293582704}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21686002}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 298375852}}, AaveV3Base: { configs: { ASSET_LISTING: [ @@ -45,7 +45,7 @@ export const config: ConfigFile = { }, ], }, - cache: {blockNumber: 24787260}, + cache: {blockNumber: 25415842}, }, }, }; From e6b73b8c682ed47ae146af90011b5f16bd8ef6f9 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:25:25 +0530 Subject: [PATCH 106/123] doc: update AIP text --- src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md index 4f077ce26..e330a43a3 100644 --- a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md @@ -6,10 +6,24 @@ discussions: "https://governance.aave.com/t/arfc-launch-gho-on-base-set-aci-as-e ## Simple Summary +This AIP proposes the expansion of GHO, the native asset of the Aave Protocol, to the Base network utilizing the Chainlink Cross-Chain Interoperability Protocol (CCIP) v1.5.1. + +The smart contracts have been refined through multiple stages of design, development, testing, and implementation. Likewise, Certora, the DAO service provider, was engaged to conduct code reviews of the implementation. + ## Motivation +Building on the successful expansion of GHO into Arbitrum, it is now time to expand GHO to other networks. The Base ecosystem will bring a new set of opportunities, allowing access to a wide array of integrations with other protocols and tools and ultimately enriching GHO's utility potential. + ## Specification +This AIP includes a series of actions required to launch GHO on Base: + +1. Configure new Chainlink CCIP lanes between Base and Ethereum/Arbitrum (while retaining existing ones) with a rate limit of 300,000 GHO capacity and 60 GHO per second rate. +2. Update the proxy admin of GHO token on Arbitrum to OpenZeppelin v5.1 Proxy Contract, enabling GHO on Arbitrum to be aligned with Base deployment. +3. Configure and activate GhoAaveSteward and GhoCcipSteward to control GHO listing and CCIP lane. +4. List GHO as a borrowable asset on the Aave Pool, with the risk configuration specified in the ARFC. Then, provide initial liquidity to the pool as a security measure to mitigate potential vulnerabilities and facilitate a stable launch. +5. Set ACI multisig as Emissions Manager for GHO and aGHO rewards, as specified in the ARFC. + The table below illustrates the configured risk parameters for **GHO** | Parameter | Value | From d292658f984636c52bfbf860b0bba88447e1e200 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:09:12 +0530 Subject: [PATCH 107/123] test: 1.5.1 upgrade executed on chain, rm all prerequisites in tests --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 8 +------- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 11 ++--------- .../AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol | 8 +------- src/20241223_Multi_GHOBaseLaunch/config.ts | 4 ++-- 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index 3c1cc9999..deb2064e3 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -26,7 +26,6 @@ import {ProxyAdmin, ITransparentUpgradeableProxy} from 'solidity-utils/contracts import {CCIPUtils} from './utils/CCIPUtils.sol'; -import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; /** @@ -82,13 +81,8 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('arbitrum'), 298375852); - - // pre-requisite, to be removed after execution - executePayload(vm, address(new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209())); - + vm.createSelectFork(vm.rpcUrl('arbitrum'), 300142041); proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); - _validateConstants(); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index f4abbf486..d532aaf31 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -31,9 +31,6 @@ import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLau import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; -import {AaveV3Arbitrum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Arbitrum_GHOCCIP151Upgrade_20241209.sol'; -import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; - /** * @dev Test for AaveV3Base_GHOBaseLaunch_20241223 * command: FOUNDRY_PROFILE=base forge test --match-path=src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol -vv @@ -104,17 +101,15 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { event Minted(address indexed sender, address indexed recipient, uint256 amount); function setUp() public virtual { - arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 298375852); + arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 300142041); base.c.forkId = vm.createFork(vm.rpcUrl('base'), 25415842); - eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21686002); + eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21722753); arb.c.chainSelector = 4949039107694359620; base.c.chainSelector = 15971525489660198786; eth.c.chainSelector = 5009297550715157269; vm.selectFork(arb.c.forkId); - // pre-requisite, to be removed after execution - executePayload(vm, address(new AaveV3Arbitrum_GHOCCIP151Upgrade_20241209())); arb.proposal = new AaveV3Arbitrum_GHOBaseLaunch_20241223(); arb.c.token = IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING); arb.tokenPool = IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); @@ -139,8 +134,6 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { base.c.ethOffRamp = IEVM2EVMOffRamp_1_5(0xCA04169671A81E4fB8768cfaD46c347ae65371F1); vm.selectFork(eth.c.forkId); - // pre-requisite, to be removed after execution - executePayload(vm, address(new AaveV3Ethereum_GHOCCIP151Upgrade_20241209())); eth.proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); eth.c.token = IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING); eth.tokenPool = IUpgradeableLockReleaseTokenPool_1_5_1( diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol index 2271b0c66..3ea443774 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.t.sol @@ -22,7 +22,6 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; -import {AaveV3Ethereum_GHOCCIP151Upgrade_20241209} from '../20241209_Multi_GHOCCIP151Upgrade/AaveV3Ethereum_GHOCCIP151Upgrade_20241209.sol'; import {AaveV3Ethereum_GHOBaseLaunch_20241223} from './AaveV3Ethereum_GHOBaseLaunch_20241223.sol'; /** @@ -78,14 +77,9 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223_Test is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public { - vm.createSelectFork(vm.rpcUrl('mainnet'), 21686002); - - // pre-requisite, to be removed after execution - executePayload(vm, address(new AaveV3Ethereum_GHOCCIP151Upgrade_20241209())); - + vm.createSelectFork(vm.rpcUrl('mainnet'), 21722753); proposal = new AaveV3Ethereum_GHOBaseLaunch_20241223(); _validateConstants(); - executePayload(vm, address(proposal)); } diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index bccd88a15..64b1e5372 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -13,8 +13,8 @@ export const config: ConfigFile = { votingNetwork: 'POLYGON', }, poolOptions: { - AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21686002}}, - AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 298375852}}, + AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21722753}}, + AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 300142041}}, AaveV3Base: { configs: { ASSET_LISTING: [ From c24beb6c258e1800d47d1b8472af292f9f577d69 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 28 Jan 2025 21:28:55 +0530 Subject: [PATCH 108/123] test: upd base block since all pre req are complete --- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 9 +-------- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 2 +- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 2 +- src/20241223_Multi_GHOBaseLaunch/config.ts | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 22edf8bdd..77189afbc 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -91,18 +91,11 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { error InvalidSourcePoolAddress(bytes); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 25415842); + vm.createSelectFork(vm.rpcUrl('base'), 25645172); proposal = new AaveV3Base_GHOBaseLaunch_20241223(); - - _performCcipPreReq(); _validateConstants(); } - function _performCcipPreReq() internal { - vm.prank(TOKEN_ADMIN_REGISTRY.owner()); - TOKEN_ADMIN_REGISTRY.proposeAdministrator(address(GHO), GovernanceV3Base.EXECUTOR_LVL_1); - } - function _validateConstants() private view { assertEq(proposal.ETH_CHAIN_SELECTOR(), ETH_CHAIN_SELECTOR); assertEq(proposal.ARB_CHAIN_SELECTOR(), ARB_CHAIN_SELECTOR); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 69ef16ed3..e9a07ee67 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -51,7 +51,7 @@ contract AaveV3Base_GHOBaseListing_20241223_Base is ProtocolV3TestBase { IUpgradeableBurnMintTokenPool_1_5_1(0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34); function setUp() public virtual { - vm.createSelectFork(vm.rpcUrl('base'), 25415842); + vm.createSelectFork(vm.rpcUrl('base'), 25645172); proposal = new AaveV3Base_GHOBaseListing_20241223(); } diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index d532aaf31..2bff4107e 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -102,7 +102,7 @@ contract AaveV3Base_GHOBaseLaunch_20241223_Base is ProtocolV3TestBase { function setUp() public virtual { arb.c.forkId = vm.createFork(vm.rpcUrl('arbitrum'), 300142041); - base.c.forkId = vm.createFork(vm.rpcUrl('base'), 25415842); + base.c.forkId = vm.createFork(vm.rpcUrl('base'), 25645172); eth.c.forkId = vm.createFork(vm.rpcUrl('mainnet'), 21722753); arb.c.chainSelector = 4949039107694359620; diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 64b1e5372..975d71f47 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -45,7 +45,7 @@ export const config: ConfigFile = { }, ], }, - cache: {blockNumber: 25415842}, + cache: {blockNumber: 25645172}, }, }, }; From 4ae9c77c4dcb6dd54d200ef2720cc0c3a83cbc26 Mon Sep 17 00:00:00 2001 From: dhairya <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:16:21 +0530 Subject: [PATCH 109/123] chore: update spec md Co-authored-by: Ian Flexa <85500650+ianflexa@users.noreply.github.com> --- src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md index e330a43a3..df5d68065 100644 --- a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md @@ -21,8 +21,8 @@ This AIP includes a series of actions required to launch GHO on Base: 1. Configure new Chainlink CCIP lanes between Base and Ethereum/Arbitrum (while retaining existing ones) with a rate limit of 300,000 GHO capacity and 60 GHO per second rate. 2. Update the proxy admin of GHO token on Arbitrum to OpenZeppelin v5.1 Proxy Contract, enabling GHO on Arbitrum to be aligned with Base deployment. 3. Configure and activate GhoAaveSteward and GhoCcipSteward to control GHO listing and CCIP lane. -4. List GHO as a borrowable asset on the Aave Pool, with the risk configuration specified in the ARFC. Then, provide initial liquidity to the pool as a security measure to mitigate potential vulnerabilities and facilitate a stable launch. -5. Set ACI multisig as Emissions Manager for GHO and aGHO rewards, as specified in the ARFC. +4. List GHO as a borrowable asset on the Aave Pool, with the risk configuration specified in the ARFC. Then, initial liquidity will be provided to the pool as a security measure to mitigate potential vulnerabilities and facilitate a stable launch. +5. Set ACI multisig ([0xac140648435d03f784879cd789130F22Ef588Fcd](https://basescan.org/address/0xac140648435d03f784879cd789130F22Ef588Fcd)) as Emission Admin for GHO and aGHO rewards, as specified in the ARFC. The table below illustrates the configured risk parameters for **GHO** @@ -48,7 +48,6 @@ The table below illustrates the configured risk parameters for **GHO** | Borrowable in Isolation | DISABLED | | Oracle | 0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73 | -Additionaly [0xac140648435d03f784879cd789130F22Ef588Fcd](https://basescan.org/address/0xac140648435d03f784879cd789130F22Ef588Fcd) has been set as the emission admin for GHO and the corresponding aToken. ## References From da9865fc2eb08c5fa90310ad73f2719a48744aab Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:27:20 +0530 Subject: [PATCH 110/123] fix: generate diff md again --- ...efore_AaveV3Base_GHOBaseListing_20241223_after.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md index 54dc91605..5d321f2d8 100644 --- a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md +++ b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md @@ -23,9 +23,9 @@ | liquidationBonus | 0 % | | liquidationProtocolFee | 0 % [0] | | reserveFactor | 10 % [1000] | -| aToken | [0xDD5745756C2de109183c6B5bB886F9207bEF114D](https://basescan.org/address/0xDD5745756C2de109183c6B5bB886F9207bEF114D) | +| aToken | [0x067ae75628177FD257c2B1e500993e1a0baBcBd1](https://basescan.org/address/0x067ae75628177FD257c2B1e500993e1a0baBcBd1) | | aTokenImpl | [0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69](https://basescan.org/address/0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69) | -| variableDebtToken | [0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd](https://basescan.org/address/0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd) | +| variableDebtToken | [0x38e59ADE183BbEb94583d44213c8f3297e9933e9](https://basescan.org/address/0x38e59ADE183BbEb94583d44213c8f3297e9933e9) | | variableDebtTokenImpl | [0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1](https://basescan.org/address/0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1) | | borrowingEnabled | true | | isBorrowableInIsolation | false | @@ -33,7 +33,7 @@ | aTokenName | Aave Base GHO | | aTokenSymbol | aBasGHO | | aTokenUnderlyingBalance | 1 GHO [1000000000000000000] | -| id | 7 | +| id | 8 | | isPaused | false | | variableDebtTokenName | Aave Base Variable Debt GHO | | variableDebtTokenSymbol | variableDebtBasGHO | @@ -55,7 +55,7 @@ "0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee": { "from": null, "to": { - "aToken": "0xDD5745756C2de109183c6B5bB886F9207bEF114D", + "aToken": "0x067ae75628177FD257c2B1e500993e1a0baBcBd1", "aTokenImpl": "0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69", "aTokenName": "Aave Base GHO", "aTokenSymbol": "aBasGHO", @@ -64,7 +64,7 @@ "borrowingEnabled": true, "debtCeiling": 0, "decimals": 18, - "id": 7, + "id": 8, "interestRateStrategy": "0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5", "isActive": true, "isBorrowableInIsolation": false, @@ -84,7 +84,7 @@ "symbol": "GHO", "underlying": "0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee", "usageAsCollateralEnabled": false, - "variableDebtToken": "0xbc4f5631f2843488792e4F1660d0A51Ba489bdBd", + "variableDebtToken": "0x38e59ADE183BbEb94583d44213c8f3297e9933e9", "variableDebtTokenImpl": "0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1", "variableDebtTokenName": "Aave Base Variable Debt GHO", "variableDebtTokenSymbol": "variableDebtBasGHO", From 6ce091ed36763db36910af9b07708a026c47c33f Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 6 Dec 2023 03:34:57 +0530 Subject: [PATCH 111/123] 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 --- lib/aave-helpers | 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/lib/aave-helpers b/lib/aave-helpers index b4f5861ab..fe818aa58 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit b4f5861abd9897356205fefd6cae7c7a93bcb805 +Subproject commit fe818aa58585d3525c827f04751b527310e2439a 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 e060c1e4cae285f22190d5591c9416f06abdf359 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 112/123] 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 8368390efcbb4ec6b1dcfcba3f3e99b56355e452 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 113/123] 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 a39d8f2166a8b039150baa441fe204ff9b545a2c 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 114/123] 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 ba873c7f63bc4bb5dc38edf1fac7f37c0f885a4b Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Dec 2023 00:10:52 +0530 Subject: [PATCH 115/123] 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 aa68ef22927343cf2bf543833c2f0e358fb132c7 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 116/123] 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 cf3bd8f590cd4eee524c1e61bb357b529ce6faca 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 117/123] 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 a4b7890f983da3c79314f8de5df2fe173ce8295f 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 118/123] 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 e11e94e371bf7b6e0a6745a5c3e6751a46607f59 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 119/123] 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 c82e8a59cc6e1d0dceb8414c2370ca58ed9f38f4 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:15:10 +0530 Subject: [PATCH 120/123] fix: rebase and update diffs, imports --- ...AaveV3Base_GHOBaseLaunch_20241223_after.md | 256 ++++++++++++++- ...aveV3Base_GHOBaseListing_20241223_after.md | 303 +++++++++++++++++- lib/aave-helpers | 2 +- ...veV3Ethereum_GhoIncidentReport_20231113.md | 27 -- ...3Ethereum_GhoIncidentReport_20231113.s.sol | 55 ---- ...eV3Ethereum_GhoIncidentReport_20231113.sol | 29 -- ...3Ethereum_GhoIncidentReport_20231113.t.sol | 48 --- ...aveV3Arbitrum_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3Base_GHOBaseLaunch_20241223.t.sol | 2 +- .../AaveV3Base_GHOBaseListing_20241223.sol | 4 +- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 2 +- .../AaveV3E2E_GHOBaseLaunch_20241223.t.sol | 4 - 12 files changed, 560 insertions(+), 174 deletions(-) delete mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md delete mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol delete mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol delete mode 100644 src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol diff --git a/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md b/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md index c15d3e2bc..ce43cfac8 100644 --- a/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md +++ b/diffs/AaveV3Base_GHOBaseLaunch_20241223_before_AaveV3Base_GHOBaseLaunch_20241223_after.md @@ -1,5 +1,259 @@ ## Raw diff ```json -{} +{ + "raw": { + "from": null, + "to": { + "0x06179f7c1be40863405f374e7f5f8806c728660a": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x0000000000000000000000000000000000000000000000000000000000000000": { + "previousValue": "0x000000000000000000009390b1735def18560c509e2d0bc090e9d6ba257a0001", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x0000000000000000000000000000000000000000000000000000000000000001": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000009390b1735def18560c509e2d0bc090e9d6ba257a" + }, + "0x0000000000000000000000000000000000000000000000000000000000000005": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + "0x0000000000000000000000000000000000000000000000000000000000000009": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000b94ab28c6869466a46a42aba834ca2b3cecca5eb" + }, + "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000000000000000000000000000045849994fc9c7b15" + }, + "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000000000000000000000000000044ae84d8e9a37444" + }, + "0x1562a759f38dadd687c76a66b280b167a6625aa5c9dc9ab890f26b5ebb953db7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x4022ffcbcc105342b5616796d3f4b6a3b8d846ffa35e402b44080d7804f6f92a" + }, + "0x1b93a487e9618b94b9c2582403f62f37366b935fb16b5662f095ef8d4dc9f2f9": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000041" + }, + "0x2e1d28cbd79909ab3b781a3b6ed36308538ed5e921eff761e217374e33e3d5e1": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x570ba59651bc4978d5dd0af8080856f5a828ccc4c9701178b8e71a42644ae7c5": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000007dff72693f6a4149b17e7c6314655f6a9f7c8b33" + }, + "0x64813f543e9e6d0745c3a3af9a3c60e2498e805c8ed7cfabec0a723971f1cd37": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0xda04a948b3ded5b8c007440e09d0c5fbf733e665881cdda1263ce39a086d3c5c" + }, + "0x785a1cd22288cc8a5ce664c50ca5b8ac546d6bfb4ebed8d76a096d29831fa61b": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000016798fdcb0000000000003f870857a3e0e3800000" + }, + "0x785a1cd22288cc8a5ce664c50ca5b8ac546d6bfb4ebed8d76a096d29831fa61c": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000340aad21b3b7000000000000000003f870857a3e0e3800000" + }, + "0x785a1cd22288cc8a5ce664c50ca5b8ac546d6bfb4ebed8d76a096d29831fa61d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000016798fdcb0000000000003f870857a3e0e3800000" + }, + "0x785a1cd22288cc8a5ce664c50ca5b8ac546d6bfb4ebed8d76a096d29831fa61e": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000340aad21b3b7000000000000000003f870857a3e0e3800000" + }, + "0x785a1cd22288cc8a5ce664c50ca5b8ac546d6bfb4ebed8d76a096d29831fa61f": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000041" + }, + "0x785a1cd22288cc8a5ce664c50ca5b8ac546d6bfb4ebed8d76a096d29831fa620": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x975100a3a7525219458f095aea06e943da1f3a875c175269c7e08b138b296af9": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x9e623807eecacc367291c7c35b49ec61a342551b4603ac4258a7598ad0a02bff": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000041" + }, + "0xc0cc08974de25f30bc8e557411378c89328786c54ed03dc7a3f682c7b56a6013": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000006179f7c1be40863405f374e7f5f8806c728660a" + }, + "0xc43d59e5cc2bf8f1b992795c27c2d5bb31adadefc93354955ac0e2ca9c5be0f7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000016798fdcb0000000000003f870857a3e0e3800000" + }, + "0xc43d59e5cc2bf8f1b992795c27c2d5bb31adadefc93354955ac0e2ca9c5be0f8": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000340aad21b3b7000000000000000003f870857a3e0e3800000" + }, + "0xc43d59e5cc2bf8f1b992795c27c2d5bb31adadefc93354955ac0e2ca9c5be0f9": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000016798fdcb0000000000003f870857a3e0e3800000" + }, + "0xc43d59e5cc2bf8f1b992795c27c2d5bb31adadefc93354955ac0e2ca9c5be0fa": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000340aad21b3b7000000000000000003f870857a3e0e3800000" + }, + "0xc43d59e5cc2bf8f1b992795c27c2d5bb31adadefc93354955ac0e2ca9c5be0fb": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000041" + }, + "0xc43d59e5cc2bf8f1b992795c27c2d5bb31adadefc93354955ac0e2ca9c5be0fc": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0xe08cacc565c769c614e476d4ccf4c6029add84095117a2b614dc884c00913837": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f" + }, + "0xebcbba45421961a613aa8525f049792af76b4a3b9c8cd725fff0451a22d8172d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000b94ab28c6869466a46a42aba834ca2b3cecca5eb" + }, + "0xf293d3be32695610199eb8e41697284defa313df24a10638ab2a31b95a75822b": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0xffac741cc353cc8e05c1f8c328ec18e682b88bec50d99165f3501c0057e802f2": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + } + }, + "0x2dc219e716793fb4b21548c0f009ba3af753ab01": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x319d156ea750b20d5370ef7b348b6ff1ab5d0256": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x308b08755ec965f49e4d58d22ebbf80dc425791b553f8567a173e85e1abb76c3": { + "previousValue": "0x006798fdca000000000002000000000000000000000000000000000000000000", + "newValue": "0x006798fdca000000000003000000000000000000000000000000000000000000" + }, + "0x308b08755ec965f49e4d58d22ebbf80dc425791b553f8567a173e85e1abb76c4": { + "previousValue": "0x000000000000000000093a8000000000000067c7224b00000000000000000000", + "newValue": "0x000000000000000000093a8000000000000067c7224b0000000000006798fdcb" + } + } + }, + "0x3c47237479e7569653ef9bec4a7cd2ee3f78b396": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x0000000000000000000000000000000000000000000000000000000000000003": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x0a36b21564a50b489c7b7dcca93215e2afd0702b503d1a8e3b50c108e8d7839f": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x6f85df03f4fcc3fc7d00f87af334c257c3705343ad81da16f37407378cb7e4ef": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000098217a06721ebf727f2c8d9ad7718ec28b7aae34" + } + } + }, + "0x43955b0899ab7232e3a454cf84aedd22ad46fd33": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x33d6f6460e5ce31939fee460cf887465d577f44ac26a089019dbc2ebf3b03ece": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + } + }, + "0x6bb7a212910682dcfdbd5bcbb3e28fb4e8da10ee": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x6f6c373d09c07425baae72317863d7f6bb731e37": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0xaedb84c47d3cd05c3e68318f98649e7914b45a3b2f4b28a179e397c8798e721d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000009390b1735def18560c509e2d0bc090e9d6ba257a" + }, + "0xaedb84c47d3cd05c3e68318f98649e7914b45a3b2f4b28a179e397c8798e721e": { + "previousValue": "0x0000000000000000000000009390b1735def18560c509e2d0bc090e9d6ba257a", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "0xaedb84c47d3cd05c3e68318f98649e7914b45a3b2f4b28a179e397c8798e721f": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000098217a06721ebf727f2c8d9ad7718ec28b7aae34" + } + } + }, + "0x9390b1735def18560c509e2d0bc090e9d6ba257a": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x98217a06721ebf727f2c8d9ad7718ec28b7aae34": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0xb0e1c7830aa781362f79225559aa068e6bdaf1d1": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x0000000000000000000000000000000000000000000000000000000000000009": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x1ebe9857f999ac76ade61e7ad82fa7307375fd90b4af169ab9379c4e6f15c5d7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x3f0a097792ef532deba2417df261f5eb4dcafb88ed9bd5e0519348fa55de58f0": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000098217a06721ebf727f2c8d9ad7718ec28b7aae34" + }, + "0x83554d8c4502b3f6bc599262032c7cb8ccee1b1cd1e03f03eee240b5daede8f1": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x9979ee02abd3fbf4dbff89812e2c588f68544dc555d1f71b00135932d3287269": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000000000000000000000108b2a2c28029094000000" + }, + "0x9979ee02abd3fbf4dbff89812e2c588f68544dc555d1f71b00135932d328726a": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x4343495020546f6b656e506f6f6c2076312e352e31000000000000000000002a" + }, + "0xb5179edb10a59dba7cb7c41b3485b038dc584e4c944dba95c2dcafc04f33a252": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + } + } + } + } +} ``` \ No newline at end of file diff --git a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md index 5d321f2d8..2ed3c827c 100644 --- a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md +++ b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md @@ -24,9 +24,7 @@ | liquidationProtocolFee | 0 % [0] | | reserveFactor | 10 % [1000] | | aToken | [0x067ae75628177FD257c2B1e500993e1a0baBcBd1](https://basescan.org/address/0x067ae75628177FD257c2B1e500993e1a0baBcBd1) | -| aTokenImpl | [0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69](https://basescan.org/address/0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69) | | variableDebtToken | [0x38e59ADE183BbEb94583d44213c8f3297e9933e9](https://basescan.org/address/0x38e59ADE183BbEb94583d44213c8f3297e9933e9) | -| variableDebtTokenImpl | [0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1](https://basescan.org/address/0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1) | | borrowingEnabled | true | | isBorrowableInIsolation | false | | interestRateStrategy | [0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5](https://basescan.org/address/0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5) | @@ -56,7 +54,6 @@ "from": null, "to": { "aToken": "0x067ae75628177FD257c2B1e500993e1a0baBcBd1", - "aTokenImpl": "0x98F409Fc4A42F34AE3c326c7f48ED01ae8cAeC69", "aTokenName": "Aave Base GHO", "aTokenSymbol": "aBasGHO", "aTokenUnderlyingBalance": "1000000000000000000", @@ -85,7 +82,6 @@ "underlying": "0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee", "usageAsCollateralEnabled": false, "variableDebtToken": "0x38e59ADE183BbEb94583d44213c8f3297e9933e9", - "variableDebtTokenImpl": "0x2425A746911128c2eAA7bEBDc9Bc452eE52208a1", "variableDebtTokenName": "Aave Base Variable Debt GHO", "variableDebtTokenSymbol": "variableDebtBasGHO", "virtualAccountingActive": true, @@ -105,6 +101,305 @@ "variableRateSlope2": "650000000000000000000000000" } } + }, + "raw": { + "from": null, + "to": { + "0x067ae75628177fd257c2b1e500993e1a0babcbd1": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000098f409fc4a42f34ae3c326c7f48ed01ae8caec69" + } + } + }, + "0x2425a746911128c2eaa7bebdc9bc452ee52208a1": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x0000000000000000000000000000000000000000000000000000000000000000": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x0000000000000000000000000000000000000000000000000000000000000001": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "0x0000000000000000000000000000000000000000000000000000000000000035": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0xafadae5f174ce8792f064102d9c7825f700733e1922a8ccc1351982f24441141" + }, + "0x0000000000000000000000000000000000000000000000000000000000000037": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000006bb7a212910682dcfdbd5bcbb3e28fb4e8da10ee" + }, + "0x000000000000000000000000000000000000000000000000000000000000003b": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x416176652042617365205661726961626c6520446562742047484f0000000036" + }, + "0x000000000000000000000000000000000000000000000000000000000000003c": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x7661726961626c654465627442617347484f0000000000000000000000000024" + }, + "0x000000000000000000000000000000000000000000000000000000000000003d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000f9cc4f0d883f1a1eb2c253bdb46c254ca51e1f4412" + } + } + }, + "0x2b22e425c1322fba0dbf17bb1da25d71811ee7ba": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40e": { + "previousValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000", + "newValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40f": { + "previousValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000", + "newValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f416": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000de0b6b3a764000000000000000000000000000000000000" + } + } + }, + "0x2cc0fc26ed4563a5ce5e8bdcfe1a2878676ae156": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0xc982d0ced1f8c746631cfe3f49173ca3ba25fe902be9cce56024300ebb89fd7a": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000fc421ad3c883bf9e7c4f42de845c4e4405799e73" + } + } + }, + "0x2dc219e716793fb4b21548c0f009ba3af753ab01": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x319d156ea750b20d5370ef7b348b6ff1ab5d0256": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0xda4c88cb8422456e6dbc87bdc0d70fdf69c0f9f7d6833899744759615d2d4cc5": { + "previousValue": "0x006798fdca000000000002000000000000000000000000000000000000000000", + "newValue": "0x006798fdca000000000003000000000000000000000000000000000000000000" + }, + "0xda4c88cb8422456e6dbc87bdc0d70fdf69c0f9f7d6833899744759615d2d4cc6": { + "previousValue": "0x000000000000000000093a8000000000000067c7224b00000000000000000000", + "newValue": "0x000000000000000000093a8000000000000067c7224b0000000000006798fdcb" + } + } + }, + "0x38e59ade183bbeb94583d44213c8f3297e9933e9": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000002425a746911128c2eaa7bebdc9bc452ee52208a1" + } + } + }, + "0x3a9c471f13c9ca1ebdf440cf713c8404e498f9c3": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x100000000000000000000000000002625a000022551003e88512000000000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40e": { + "previousValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000", + "newValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40f": { + "previousValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000", + "newValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f410": { + "previousValue": "0x0000000000000000000008000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000008006798fdcb00000000000000000000000000000000" + } + } + }, + "0x43955b0899ab7232e3a454cf84aedd22ad46fd33": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x4816b2c2895f97fb918f1ae7da403750a0ee372e": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x4d0109d509e66df298257ffdd55f94a3814343aa": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x5731a04b1e775f0fdd454bf70f3335886e9a96be": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x6533a273f3ac84df91dcd654d6ebaba73687e246": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x34912faa3b94f6260811dc90a5fcd80ba8bbd27a331cfb3ec427d39ba71b94ab": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000ac140648435d03f784879cd789130f22ef588fcd" + }, + "0xf944e233e6a975ddc399fd33c6934da7dc0e17700dea63dc462b634655557be1": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000ac140648435d03f784879cd789130f22ef588fcd" + } + } + }, + "0x6bb7a212910682dcfdbd5bcbb3e28fb4e8da10ee": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x86ab1c62a8bf868e1b3e1ab87d587aba6fbcbdc5": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0xc982d0ced1f8c746631cfe3f49173ca3ba25fe902be9cce56024300ebb89fd7a": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000000000000000000001964000004b0000000002328" + } + } + }, + "0x9390b1735def18560c509e2d0bc090e9d6ba257a": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0x98f409fc4a42f34ae3c326c7f48ed01ae8caec69": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x0000000000000000000000000000000000000000000000000000000000000000": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x0000000000000000000000000000000000000000000000000000000000000001": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "0x0000000000000000000000000000000000000000000000000000000000000036": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + }, + "0x0000000000000000000000000000000000000000000000000000000000000037": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x4161766520426173652047484f0000000000000000000000000000000000001a" + }, + "0x0000000000000000000000000000000000000000000000000000000000000038": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x6142617347484f0000000000000000000000000000000000000000000000000e" + }, + "0x0000000000000000000000000000000000000000000000000000000000000039": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000f9cc4f0d883f1a1eb2c253bdb46c254ca51e1f4412" + }, + "0x000000000000000000000000000000000000000000000000000000000000003b": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0xd95ff480dfea0a7d204013fdf8d80bacff144fe289b39887d7b8fffc54fa187e" + }, + "0x000000000000000000000000000000000000000000000000000000000000003c": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000ba9424d650a4f5c80a0da641254d1acce2a37057" + }, + "0x000000000000000000000000000000000000000000000000000000000000003d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000006bb7a212910682dcfdbd5bcbb3e28fb4e8da10ee" + }, + "0x2dc2afdad33a5feea586a9545052327b65d28efb10d11fa69e77da986a1031cd": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000033b2e3c9fd0803ce800000000000000000000000de0b6b3a7640000" + } + } + }, + "0xa238dd80c259a72e81d7e4664a9801593f98d1c5": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0xa58fb47be9074828215a173564c0cd10f6f249bf": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x000000000000000000000000000000000000000000000000000000000000003b": { + "previousValue": "0x00000000000000000000000000000000000000000000000800000000000009c4", + "newValue": "0x00000000000000000000000000000000000000000000000900000000000009c4" + }, + "0x05725f7419f52ac606bc65a60e5ab85095522694ed898882d2777964ee382600": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000006bb7a212910682dcfdbd5bcbb3e28fb4e8da10ee" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40e": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f40f": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f410": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000008000000000000000000000000000000000000000000" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f411": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x000000000000000000000000067ae75628177fd257c2b1e500993e1a0babcbd1" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f413": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000038e59ade183bbeb94583d44213c8f3297e9933e9" + }, + "0x3fc949ca89c9af8f3bf977ace52c826b7b79c9f52b6c2a1a960c0b4f1387f414": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x00000000000000000000000086ab1c62a8bf868e1b3e1ab87d587aba6fbcbdc5" + } + } + }, + "0xb0e1c7830aa781362f79225559aa068e6bdaf1d1": { + "label": null, + "balanceDiff": null, + "stateDiff": { + "0x153355011b7d7d042d97174072318f29dbc50882f47ebb07d64ddb67538aea5d": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + }, + "0x618b6524a63db141c6ec50e3099a7bb2a245c9f2f08057a6ca507f1a6edc4b3a": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "0xb80f08d50aa0366243778050783b5dd4d04222561c98abe78842dedaf9ce8580": { + "previousValue": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "0xe20fcbdbffc4dd138ce8b2e6fbb6cb49777ad64d": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + }, + "0xf9cc4f0d883f1a1eb2c253bdb46c254ca51e1f44": { + "label": null, + "balanceDiff": null, + "stateDiff": {} + } + } } } ``` \ No newline at end of file diff --git a/lib/aave-helpers b/lib/aave-helpers index fe818aa58..b4f5861ab 160000 --- a/lib/aave-helpers +++ b/lib/aave-helpers @@ -1 +1 @@ -Subproject commit fe818aa58585d3525c827f04751b527310e2439a +Subproject commit b4f5861abd9897356205fefd6cae7c7a93bcb805 diff --git a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md b/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md deleted file mode 100644 index 2cf269d2a..000000000 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -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 - -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 - -The proposal payload upgrades the implementation of GhoVariableDebtToken. - -## References - -- GhoVariableDebtToken implementation: [GhoVariableDebtToken](https://etherscan.io/address/0x20cb2f303ede313e2cc44549ad8653a5e8c0050e#code) -- Implementation: [Payload](https://etherscan.io/address/0xbc9ffee8d18d75a412474b92192257d3c18471ff#code) -- [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 deleted file mode 100644 index 4345823a2..000000000 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.s.sol +++ /dev/null @@ -1,55 +0,0 @@ -// 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(); - - // 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); - actionsEthereum[0] = GovV3Helpers.buildAction(0xbC9ffee8d18d75a412474B92192257d3c18471FF); - 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 deleted file mode 100644 index 08fc96cec..000000000 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.sol +++ /dev/null @@ -1,29 +0,0 @@ -// 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 constant NEW_VGHO_IMPL = 0x20Cb2f303EDe313e2Cc44549Ad8653a5E8c0050e; - - 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 deleted file mode 100644 index dcbfb4659..000000000 --- a/src/20231207_AaveV3Ethereum_GhoIncidentReport_20231126/AaveV3Ethereum_GhoIncidentReport_20231113.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// 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 {IPoolConfigurator} from 'aave-address-book/AaveV3.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(); - } - - 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, - 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 - ); - } -} diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol index deb2064e3..fea8b4736 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.t.sol @@ -22,7 +22,7 @@ import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; -import {ProxyAdmin, ITransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {ProxyAdmin, ITransparentUpgradeableProxy} from 'openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol index 77189afbc..eccd79d37 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.t.sol @@ -25,7 +25,7 @@ import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; -import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import {ProxyAdmin} from 'openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol'; import {CCIPUtils} from './utils/CCIPUtils.sol'; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol index fc7259504..c498486a0 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol'; -import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {SafeERC20} from 'openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol'; +import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import {IAaveV3ConfigEngine} from 'aave-v3-origin/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol'; import {IEmissionManager} from 'aave-v3-origin/contracts/rewards/interfaces/IEmissionManager.sol'; import {EngineFlags} from 'aave-v3-origin/contracts/extensions/v3-config-engine/EngineFlags.sol'; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index e9a07ee67..4d6868883 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; import {IEmissionManager} from 'aave-v3-origin/contracts/rewards/interfaces/IEmissionManager.sol'; -import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; import {DataTypes, IDefaultInterestRateStrategyV2} from 'aave-address-book/AaveV3.sol'; import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {ITokenAdminRegistry} from 'src/interfaces/ccip/ITokenAdminRegistry.sol'; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol index 2bff4107e..e7ad1ee5f 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3E2E_GHOBaseLaunch_20241223.t.sol @@ -3,8 +3,6 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; - import {IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IUpgradeableBurnMintTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableBurnMintTokenPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; @@ -24,8 +22,6 @@ import {ProtocolV3TestBase} from 'aave-helpers/src/ProtocolV3TestBase.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; -import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; - import {CCIPUtils} from './utils/CCIPUtils.sol'; import {AaveV3Arbitrum_GHOBaseLaunch_20241223} from './AaveV3Arbitrum_GHOBaseLaunch_20241223.sol'; import {AaveV3Base_GHOBaseLaunch_20241223} from './AaveV3Base_GHOBaseLaunch_20241223.sol'; From de7f6f8a4a61bfd9178aa8179e2fc85e8a24c51a Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:24:25 +0530 Subject: [PATCH 121/123] chore: import token pools from address book --- .../AaveV3Arbitrum_GHOBaseLaunch_20241223.sol | 3 ++- .../AaveV3Base_GHOBaseLaunch_20241223.sol | 6 ++++-- .../AaveV3Ethereum_GHOBaseLaunch_20241223.sol | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol index ce0dcaf5b..109c804c1 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol @@ -7,6 +7,7 @@ import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; import {ILegacyProxyAdmin, ITransparentUpgradeableProxy} from 'src/interfaces/ILegacyProxyAdmin.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol'; /** @@ -20,7 +21,7 @@ contract AaveV3Arbitrum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://arbiscan.io/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB IUpgradeableBurnMintTokenPool_1_5_1 public constant TOKEN_POOL = - IUpgradeableBurnMintTokenPool_1_5_1(0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB); + IUpgradeableBurnMintTokenPool_1_5_1(GhoArbitrum.GHO_CCIP_TOKEN_POOL); // https://arbiscan.io/address/0x9f0e4F4c5664888442E459f40f635765BB6265Ec address public constant NEW_GHO_TOKEN_PROXY_ADMIN = 0x9f0e4F4c5664888442E459f40f635765BB6265Ec; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol index 929ba2a3c..020dd68be 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol @@ -11,6 +11,8 @@ import {IGhoToken} from 'src/interfaces/IGhoToken.sol'; import {AaveV3Base} from 'aave-address-book/AaveV3Base.sol'; import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {GhoArbitrum} from 'aave-address-book/GhoArbitrum.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; /** @@ -43,9 +45,9 @@ contract AaveV3Base_GHOBaseLaunch_20241223 is IProposalGenericExecutor { address public constant GHO_CCIP_STEWARD = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A - address public constant REMOTE_TOKEN_POOL_ETH = 0x06179f7C1be40863405f374E7f5F8806c728660A; + address public constant REMOTE_TOKEN_POOL_ETH = GhoEthereum.GHO_CCIP_TOKEN_POOL; // https://arbiscan.io/address/0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB - address public constant REMOTE_TOKEN_POOL_ARB = 0xB94Ab28c6869466a46a42abA834ca2B3cECCA5eB; + address public constant REMOTE_TOKEN_POOL_ARB = GhoArbitrum.GHO_CCIP_TOKEN_POOL; // Token Rate Limit Capacity: 300_000 GHO uint128 public constant CCIP_RATE_LIMIT_CAPACITY = 300_000e18; diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol index c43ce70ca..635869922 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol'; import {IUpgradeableLockReleaseTokenPool_1_5_1} from 'src/interfaces/ccip/tokenPool/IUpgradeableLockReleaseTokenPool.sol'; import {IRateLimiter} from 'src/interfaces/ccip/IRateLimiter.sol'; +import {GhoEthereum} from 'aave-address-book/GhoEthereum.sol'; /** * @title GHO Base Launch @@ -16,7 +17,7 @@ contract AaveV3Ethereum_GHOBaseLaunch_20241223 is IProposalGenericExecutor { // https://etherscan.io/address/0x06179f7C1be40863405f374E7f5F8806c728660A IUpgradeableLockReleaseTokenPool_1_5_1 public constant TOKEN_POOL = - IUpgradeableLockReleaseTokenPool_1_5_1(0x06179f7C1be40863405f374E7f5F8806c728660A); + IUpgradeableLockReleaseTokenPool_1_5_1(GhoEthereum.GHO_CCIP_TOKEN_POOL); // https://basescan.org/address/0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34 address public constant REMOTE_TOKEN_POOL_BASE = 0x98217A06721Ebf727f2C8d9aD7718ec28b7aAe34; From d8994be7a7a42f30a123d1c0e118d9db6d832923 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:05:00 +0530 Subject: [PATCH 122/123] chore: fix lint on spec md --- src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md index df5d68065..9e33d7774 100644 --- a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md @@ -48,7 +48,6 @@ The table below illustrates the configured risk parameters for **GHO** | Borrowable in Isolation | DISABLED | | Oracle | 0xfc421aD3C883Bf9E7C4f42dE845C4e4405799e73 | - ## References - Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Ethereum_GHOBaseLaunch_20241223.sol), [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Arbitrum_GHOBaseLaunch_20241223.sol), [AaveV3BaseLaunch](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseLaunch_20241223.sol), [AaveV3BaseListing](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol) From faac4bcaf97c3a8a5eb3607aa438409ee71d373b Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 4 Feb 2025 22:21:07 +0530 Subject: [PATCH 123/123] fix: update rates based on latest recc --- ...e_AaveV3Base_GHOBaseListing_20241223_after.md | 16 ++++++++-------- .../AaveV3Base_GHOBaseListing_20241223.sol | 4 ++-- .../AaveV3Base_GHOBaseListing_20241223.t.sol | 4 ++-- .../GHOBaseLaunch.md | 4 ++-- src/20241223_Multi_GHOBaseLaunch/config.ts | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md index 2ed3c827c..839c5ee1b 100644 --- a/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md +++ b/diffs/AaveV3Base_GHOBaseListing_20241223_before_AaveV3Base_GHOBaseListing_20241223_after.md @@ -38,11 +38,11 @@ | virtualAccountingActive | true | | virtualBalance | 1 GHO [1000000000000000000] | | optimalUsageRatio | 90 % | -| maxVariableBorrowRate | 77 % | +| maxVariableBorrowRate | 59.5 % | | baseVariableBorrowRate | 0 % | -| variableRateSlope1 | 12 % | -| variableRateSlope2 | 65 % | -| interestRate | ![ir](https://dash.onaave.com/api/static?variableRateSlope1=120000000000000000000000000&variableRateSlope2=650000000000000000000000000&optimalUsageRatio=900000000000000000000000000&baseVariableBorrowRate=0&maxVariableBorrowRate=770000000000000000000000000) | +| variableRateSlope1 | 9.5 % | +| variableRateSlope2 | 50 % | +| interestRate | ![ir](https://dash.onaave.com/api/static?variableRateSlope1=95000000000000000000000000&variableRateSlope2=500000000000000000000000000&optimalUsageRatio=900000000000000000000000000&baseVariableBorrowRate=0&maxVariableBorrowRate=595000000000000000000000000) | ## Raw diff @@ -95,10 +95,10 @@ "to": { "address": "0x86AB1C62A8bf868E1b3E1ab87d587Aba6fbCbDC5", "baseVariableBorrowRate": "0", - "maxVariableBorrowRate": "770000000000000000000000000", + "maxVariableBorrowRate": "595000000000000000000000000", "optimalUsageRatio": "900000000000000000000000000", - "variableRateSlope1": "120000000000000000000000000", - "variableRateSlope2": "650000000000000000000000000" + "variableRateSlope1": "95000000000000000000000000", + "variableRateSlope2": "500000000000000000000000000" } } }, @@ -273,7 +273,7 @@ "stateDiff": { "0xc982d0ced1f8c746631cfe3f49173ca3ba25fe902be9cce56024300ebb89fd7a": { "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newValue": "0x00000000000000000000000000000000000000001964000004b0000000002328" + "newValue": "0x00000000000000000000000000000000000000001388000003b6000000002328" } } }, diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol index c498486a0..273413a37 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.sol @@ -64,8 +64,8 @@ contract AaveV3Base_GHOBaseListing_20241223 is AaveV3PayloadBase { rateStrategyParams: IAaveV3ConfigEngine.InterestRateInputData({ optimalUsageRatio: 90_00, baseVariableBorrowRate: 0, - variableRateSlope1: 12_00, - variableRateSlope2: 65_00 + variableRateSlope1: 9_50, + variableRateSlope2: 50_00 }) }); diff --git a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol index 4d6868883..be1795766 100644 --- a/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol +++ b/src/20241223_Multi_GHOBaseLaunch/AaveV3Base_GHOBaseListing_20241223.t.sol @@ -190,8 +190,8 @@ contract AaveV3Base_GHOBaseListing_20241223_Stewards is AaveV3Base_GHOBaseListin memory currentRateData = IDefaultInterestRateStrategyV2.InterestRateData({ optimalUsageRatio: 90_00, baseVariableBorrowRate: 0, - variableRateSlope1: 12_00, - variableRateSlope2: 65_00 + variableRateSlope1: 9_50, + variableRateSlope2: 50_00 }); assertEq(irStrategy.getInterestRateDataBps(address(GHO_TOKEN)), currentRateData); diff --git a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md index 9e33d7774..a92bbe8d7 100644 --- a/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md +++ b/src/20241223_Multi_GHOBaseLaunch/GHOBaseLaunch.md @@ -40,8 +40,8 @@ The table below illustrates the configured risk parameters for **GHO** | Liquidation Protocol Fee | 0 % | | Reserve Factor | 10 % | | Base Variable Borrow Rate | 0 % | -| Variable Slope 1 | 12 % | -| Variable Slope 2 | 65 % | +| Variable Slope 1 | 9.5 % | +| Variable Slope 2 | 50 % | | Uoptimal | 90 % | | Flashloanable | ENABLED | | Siloed Borrowing | DISABLED | diff --git a/src/20241223_Multi_GHOBaseLaunch/config.ts b/src/20241223_Multi_GHOBaseLaunch/config.ts index 975d71f47..1a6c4208a 100644 --- a/src/20241223_Multi_GHOBaseLaunch/config.ts +++ b/src/20241223_Multi_GHOBaseLaunch/config.ts @@ -37,8 +37,8 @@ export const config: ConfigFile = { rateStrategyParams: { optimalUtilizationRate: '90', baseVariableBorrowRate: '0', - variableRateSlope1: '12', - variableRateSlope2: '65', + variableRateSlope1: '9.5', + variableRateSlope2: '50', }, asset: '0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee', admin: '0xac140648435d03f784879cd789130F22Ef588Fcd',