Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Launch GHO on Avalanche #519

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
24a3f7d
Add proposal for Gho Incident Report 20231113 (#1)
parth-15 Dec 5, 2023
4aa6143
fix: Make new impl constant (#3)
miguelmtzinf Dec 6, 2023
27dd485
fix: Amend AIP text (#4)
miguelmtzinf Dec 6, 2023
2f242a6
test: Tweak default tests with borrow cap update (#5)
miguelmtzinf Dec 7, 2023
4812d01
fix: lint issue (#6)
parth-15 Dec 7, 2023
43a7687
test: Add diffs from test running (#7)
miguelmtzinf Dec 7, 2023
4c79bb9
fix: Add payload address (#8)
miguelmtzinf Dec 7, 2023
76cd4b6
fix: Fix payload address in script (#9)
miguelmtzinf Dec 7, 2023
120f564
fix: Remove unneeded diff file (#10)
miguelmtzinf Dec 7, 2023
4d6a3d9
Merge branch 'bgd-labs:main' into main
miguelmtzinf Dec 13, 2023
4cb8573
Merge branch 'bgd-labs:main' into main
miguelmtzinf Jan 16, 2024
0e39df3
Merge branch 'bgd-labs:main' into main
miguelmtzinf May 28, 2024
11a6d50
Merge branch 'bgd-labs:main' into main
miguelmtzinf Jun 14, 2024
ea78e25
Merge branch 'bgd-labs:main' into main
miguelmtzinf Jun 17, 2024
b6499dc
Merge branch 'bgd-labs:main' into main
miguelmtzinf Jun 26, 2024
e38aca8
Merge branch 'bgd-labs:main' into main
miguelmtzinf Jul 29, 2024
4c4426f
Merge branch 'bgd-labs:main' into main
miguelmtzinf Jul 30, 2024
3b23dc7
Merge branch 'bgd-labs:main' into main
miguelmtzinf Sep 12, 2024
2a0d25c
Merge branch 'bgd-labs:main' into main
miguelmtzinf Oct 21, 2024
82dfded
Merge branch 'bgd-labs:main' into main
miguelmtzinf Nov 4, 2024
35bddfa
feat: Initial proposal generation
CheyenneAtapour Nov 5, 2024
4ad619a
chore: Add v1.5 token pool dep
CheyenneAtapour Nov 5, 2024
eaddfca
feat: Ethereum proposal
CheyenneAtapour Nov 5, 2024
19ebd60
feat: Arbitrum proposal
CheyenneAtapour Nov 5, 2024
4d3b3a3
feat: Enable Arbitrum lane, add todos
CheyenneAtapour Nov 7, 2024
b17cfa4
feat: Accept token administrator role
CheyenneAtapour Nov 7, 2024
6211627
feat: Link token to pool
CheyenneAtapour Nov 7, 2024
e8e791b
feat: List gho on avax
CheyenneAtapour Nov 7, 2024
be994cc
feat: Generate aip files
CheyenneAtapour Nov 7, 2024
54c4789
chore: Add v1.5 token pool dep
CheyenneAtapour Nov 7, 2024
946660a
merge in ccip-gho-avax
CheyenneAtapour Nov 7, 2024
7e4c7fd
chore: Move existing proposals into new template
CheyenneAtapour Nov 7, 2024
c0dfe64
feat: Arbitrum proposal
CheyenneAtapour Nov 7, 2024
5e07b5a
fix: Remove intermediary utils contract
CheyenneAtapour Nov 8, 2024
70bcdee
fix: Assume pool deployed
CheyenneAtapour Nov 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
[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.git
branch = feat/1_5_token_pool
[submodule "lib/gho-core"]
path = lib/gho-core
url = https://github.com/aave/gho-core.git
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
src = 'src'
test = 'tests'
script = 'scripts'
solc = '0.8.20'
solc = '0.8.24'
out = 'out'
bytecode_hash = 'none'
libs = ['lib']
Expand Down
1 change: 1 addition & 0 deletions lib/ccip
Submodule ccip added at 93b0f9
1 change: 1 addition & 0 deletions lib/gho-core
Submodule gho-core added at 0a6fbd
2 changes: 2 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ 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
ccip/=lib/ccip/contracts/src/v0.8/ccip/
gho-core/=lib/gho-core/src/contracts/
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {UpgradeableBurnMintTokenPool} from 'ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol';
import {UpgradeableTokenPool} from 'ccip/pools/GHO/UpgradeableTokenPool.sol';
import {RateLimiter} from 'ccip/libraries/RateLimiter.sol';
import {TokenAdminRegistry} from 'ccip/tokenAdminRegistry/TokenAdminRegistry.sol';
import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol';
import {AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol';
import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol';
import {IGhoToken} from 'gho-core/gho/interfaces/IGhoToken.sol';

/**
* @title GHOAvaxLaunch
* @author Aave Labs
* - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x2aed7eb8b03cb3f961cbf790bf2e2e1e449f841a4ad8bdbcdd223bb6ac69e719
* - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-avalanche-set-aci-as-emissions-manager-for-rewards/19339
* @dev This payload consists of the following set of actions:
* 1. Accept ownership of CCIP TokenPool
* 2. Configure CCIP TokenPool for Ethereum
* 3. Configure CCIP TokenPool for Avalanche
* 4. Add CCIP TokenPool as GHO Facilitator (allowing burn and mint)
* 5. Accept administrator role from Chainlink token admin registry
* 6. Link token to pool on Chainlink token admin registry
*/
contract AaveV3Arbitrum_GHOAvaxLaunch_20241106 is IProposalGenericExecutor {
address public constant CCIP_RMN_PROXY = 0xC311a21e6fEf769344EB1515588B9d535662a145;
address public constant CCIP_ROUTER = 0x141fa059441E0ca23ce184B6A78bafD2A517DdE8;
// TODO: Wait for token admin registry to be deployed, and get proper address
address public constant CCIP_TOKEN_ADMIN_REGISTRY = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419;
// TODO: Wait until new token pool is deployed on Arbitrum, then use corresponding address
address public constant CCIP_TOKEN_POOL = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419;
uint256 public constant CCIP_BUCKET_CAPACITY = 1_000_000e18; // 1M
uint64 public constant CCIP_ETH_CHAIN_SELECTOR = 5009297550715157269;
uint64 public constant CCIP_AVAX_CHAIN_SELECTOR = 6433500567565415381;

function execute() external {
// 1. Accept TokenPool ownership
UpgradeableBurnMintTokenPool(CCIP_TOKEN_POOL).acceptOwnership();

// 2. Configure CCIP TokenPool for Ethereum
// TODO: Set remote pool and token addresses after deployment?
_configureCcipTokenPool(CCIP_TOKEN_POOL, CCIP_ETH_CHAIN_SELECTOR, address(0), address(0));

// 3. Configure CCIP TokenPool for Avalanche
// TODO: Set remote pool and token addresses after deployment?
_configureCcipTokenPool(CCIP_TOKEN_POOL, CCIP_AVAX_CHAIN_SELECTOR, address(0), address(0));

// 4. Add CCIP TokenPool as GHO Facilitator
IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING).grantRole(
IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING).FACILITATOR_MANAGER_ROLE(),
GovernanceV3Arbitrum.EXECUTOR_LVL_1
);
IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING).grantRole(
IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING).BUCKET_MANAGER_ROLE(),
GovernanceV3Arbitrum.EXECUTOR_LVL_1
);
IGhoToken(AaveV3ArbitrumAssets.GHO_UNDERLYING).addFacilitator(
CCIP_TOKEN_POOL,
'CCIP TokenPool',
uint128(CCIP_BUCKET_CAPACITY)
);

// 5. Accept administrator role from Chainlink token manager
TokenAdminRegistry(CCIP_TOKEN_ADMIN_REGISTRY).acceptAdminRole(
AaveV3ArbitrumAssets.GHO_UNDERLYING
);

// 6. Link token to pool on Chainlink token admin registry
TokenAdminRegistry(CCIP_TOKEN_ADMIN_REGISTRY).setPool(
AaveV3ArbitrumAssets.GHO_UNDERLYING,
CCIP_TOKEN_POOL
);
}

function _configureCcipTokenPool(
address tokenPool,
uint64 chainSelector,
address remotePool,
address remoteToken
) internal {
UpgradeableTokenPool.ChainUpdate[] memory chainUpdates = new UpgradeableTokenPool.ChainUpdate[](
1
);
RateLimiter.Config memory rateConfig = RateLimiter.Config({
isEnabled: false,
capacity: 0,
rate: 0
});
chainUpdates[0] = UpgradeableTokenPool.ChainUpdate({
remoteChainSelector: chainSelector,
allowed: true,
remotePoolAddress: abi.encode(remotePool),
remoteTokenAddress: abi.encode(remoteToken),
outboundRateLimiterConfig: rateConfig,
inboundRateLimiterConfig: rateConfig
});
UpgradeableBurnMintTokenPool(tokenPool).applyChainUpdates(chainUpdates);
}
}
Original file line number Diff line number Diff line change
@@ -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_GHOAvaxLaunch_20241106} from './AaveV3Arbitrum_GHOAvaxLaunch_20241106.sol';

/**
* @dev Test for AaveV3Arbitrum_GHOAvaxLaunch_20241106
* command: FOUNDRY_PROFILE=arbitrum forge test --match-path=src/20241106_Multi_GHOAvaxLaunch/AaveV3Arbitrum_GHOAvaxLaunch_20241106.t.sol -vv
*/
contract AaveV3Arbitrum_GHOAvaxLaunch_20241106_Test is ProtocolV3TestBase {
AaveV3Arbitrum_GHOAvaxLaunch_20241106 internal proposal;

function setUp() public {
vm.createSelectFork(vm.rpcUrl('arbitrum'), 271862002);
proposal = new AaveV3Arbitrum_GHOAvaxLaunch_20241106();
}

/**
* @dev executes the generic test suite including e2e and config snapshots
*/
function test_defaultProposalExecution() public {
defaultTest('AaveV3Arbitrum_GHOAvaxLaunch_20241106', AaveV3Arbitrum.POOL, address(proposal));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol';
import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol';
import {UpgradeableBurnMintTokenPool} from 'ccip/pools/GHO/UpgradeableBurnMintTokenPool.sol';
import {UpgradeableTokenPool} from 'ccip/pools/GHO/UpgradeableTokenPool.sol';
import {RateLimiter} from 'ccip/libraries/RateLimiter.sol';
import {TokenAdminRegistry} from 'ccip/tokenAdminRegistry/TokenAdminRegistry.sol';
import {IProposalGenericExecutor} from 'aave-helpers/src/interfaces/IProposalGenericExecutor.sol';
import {AaveV3PayloadAvalanche} from 'aave-helpers/src/v3-config-engine/AaveV3PayloadAvalanche.sol';
import {AaveV3Avalanche} from 'aave-address-book/AaveV3Avalanche.sol';
import {GovernanceV3Avalanche} from 'aave-address-book/GovernanceV3Avalanche.sol';
import {MiscAvalanche} from 'aave-address-book/MiscAvalanche.sol';
import {EngineFlags} from 'aave-v3-origin/contracts/extensions/v3-config-engine/EngineFlags.sol';
import {IAaveV3ConfigEngine} from 'aave-v3-origin/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol';
import {UpgradeableGhoToken} from 'gho-core/gho/UpgradeableGhoToken.sol';
import {IGhoToken} from 'gho-core/gho/interfaces/IGhoToken.sol';

/**
* @title GHO Avax Launch
* @author Aave Labs
* - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x2aed7eb8b03cb3f961cbf790bf2e2e1e449f841a4ad8bdbcdd223bb6ac69e719
* - Discussion: https://governance.aave.com/t/arfc-launch-gho-on-avalanche-set-aci-as-emissions-manager-for-rewards/19339
* @dev This payload consists of the following set of actions:
* 1. Deploy GHO
* 2. Accept ownership of CCIP TokenPool
* 3. Configure CCIP TokenPool for Ethereum
* 4. Configure CCIP TokenPool for Arbitrum
* 5. Add CCIP TokenPool as GHO Facilitator (allowing burn and mint)
* 6. Accept administrator role from Chainlink token admin registry
* 7. Link token to pool on Chainlink token admin registry
*/
contract AaveV3Avalanche_GHOAvaxLaunch_20241106 is IProposalGenericExecutor {
address public constant CCIP_RMN_PROXY = 0xcBD48A8eB077381c3c4Eb36b402d7283aB2b11Bc;
address public constant CCIP_ROUTER = 0xF4c7E640EdA248ef95972845a62bdC74237805dB;
// TODO: Wait for token admin registry to be deployed, and get proper address
address public constant CCIP_TOKEN_ADMIN_REGISTRY = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419;
// TODO: Wait until new token pool is deployed on Avalanche, then use corresponding address
address public constant CCIP_TOKEN_POOL = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419;
uint256 public constant CCIP_BUCKET_CAPACITY = 25_000_000e18; // 25M
uint64 public constant CCIP_ETH_CHAIN_SELECTOR = 5009297550715157269;
uint64 public constant CCIP_ARB_CHAIN_SELECTOR = 4949039107694359620;

function execute() external {
// 1. Deploy GHO
address ghoToken = _deployGhoToken();

// 2. Accept TokenPool ownership
UpgradeableBurnMintTokenPool(CCIP_TOKEN_POOL).acceptOwnership();

// 3. Configure CCIP TokenPool for Ethereum
// TODO: Set remote pool and token addresses after deployment?
_configureCcipTokenPool(CCIP_TOKEN_POOL, CCIP_ETH_CHAIN_SELECTOR, address(0), address(0));

// 4. Configure CCIP TokenPool for Arbitrum
// TODO: Set remote pool and token addresses after deployment?
_configureCcipTokenPool(CCIP_TOKEN_POOL, CCIP_ARB_CHAIN_SELECTOR, address(0), address(0));

// 5. Add CCIP TokenPool as GHO Facilitator
IGhoToken(ghoToken).grantRole(
IGhoToken(ghoToken).FACILITATOR_MANAGER_ROLE(),
GovernanceV3Avalanche.EXECUTOR_LVL_1
);
IGhoToken(ghoToken).grantRole(
IGhoToken(ghoToken).BUCKET_MANAGER_ROLE(),
GovernanceV3Avalanche.EXECUTOR_LVL_1
);
IGhoToken(ghoToken).addFacilitator(
CCIP_TOKEN_POOL,
'CCIP TokenPool',
uint128(CCIP_BUCKET_CAPACITY)
);

// 6. Accept administrator role from Chainlink token manager
TokenAdminRegistry(CCIP_TOKEN_ADMIN_REGISTRY).acceptAdminRole(ghoToken);

// 7. Link token to pool on Chainlink token admin registry
TokenAdminRegistry(CCIP_TOKEN_ADMIN_REGISTRY).setPool(ghoToken, CCIP_TOKEN_POOL);
}

function _deployGhoToken() internal returns (address) {
address imple = address(new UpgradeableGhoToken());

bytes memory ghoTokenInitParams = abi.encodeWithSignature(
'initialize(address)',
GovernanceV3Avalanche.EXECUTOR_LVL_1 // owner
);
return
address(
new TransparentUpgradeableProxy(imple, MiscAvalanche.PROXY_ADMIN, ghoTokenInitParams)
);
}

function _configureCcipTokenPool(
address tokenPool,
uint64 chainSelector,
address remotePool,
address remoteToken
) internal {
UpgradeableTokenPool.ChainUpdate[] memory chainUpdates = new UpgradeableTokenPool.ChainUpdate[](
1
);
RateLimiter.Config memory rateConfig = RateLimiter.Config({
isEnabled: false,
capacity: 0,
rate: 0
});
chainUpdates[0] = UpgradeableTokenPool.ChainUpdate({
remoteChainSelector: chainSelector,
allowed: true,
remotePoolAddress: abi.encode(remotePool),
remoteTokenAddress: abi.encode(remoteToken),
outboundRateLimiterConfig: rateConfig,
inboundRateLimiterConfig: rateConfig
});
UpgradeableBurnMintTokenPool(tokenPool).applyChainUpdates(chainUpdates);
}
}

// TODO: Determine appropriate procedure to have these 2 as separate payload, same AIP
/*
* @dev This payload consists of the following set of actions:
* 1. List GHO on Avax in separate payload - because there is a delay to activate lane
* 2. Supply GHO to the Aave protocol
*/
contract GhoAvaxListing is AaveV3PayloadAvalanche {
using SafeERC20 for IERC20;

uint256 public constant GHO_SEED_AMOUNT = 1_000_000e18;
address public ghoToken;

constructor(address gho) {
ghoToken = gho;
}

function newListings() public view override returns (IAaveV3ConfigEngine.Listing[] memory) {
IAaveV3ConfigEngine.Listing[] memory listings = new IAaveV3ConfigEngine.Listing[](1);

listings[0] = IAaveV3ConfigEngine.Listing({
asset: ghoToken,
assetSymbol: 'GHO',
priceFeed: 0xB05984aD83C20b3ADE7bf97a9a0Cb539DDE28DBb, // TODO: Correct price feed
enabledToBorrow: EngineFlags.ENABLED,
borrowableInIsolation: EngineFlags.DISABLED,
withSiloedBorrowing: EngineFlags.DISABLED,
flashloanable: EngineFlags.ENABLED,
ltv: 0,
liqThreshold: 0,
liqBonus: 0,
reserveFactor: 10_00,
supplyCap: 5_000_000,
borrowCap: 4_500_000,
debtCeiling: 0,
liqProtocolFee: 0,
rateStrategyParams: IAaveV3ConfigEngine.InterestRateInputData({
optimalUsageRatio: _bpsToRay(90_00),
baseVariableBorrowRate: _bpsToRay(0),
variableRateSlope1: _bpsToRay(12_00),
variableRateSlope2: _bpsToRay(65_00)
})
});

return listings;
}

function _postExecute() internal override {
IERC20(ghoToken).forceApprove(address(AaveV3Avalanche.POOL), GHO_SEED_AMOUNT);
AaveV3Avalanche.POOL.supply(ghoToken, GHO_SEED_AMOUNT, address(0), 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {AaveV3Avalanche} from 'aave-address-book/AaveV3Avalanche.sol';

import 'forge-std/Test.sol';
import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/src/ProtocolV3TestBase.sol';
import {AaveV3Avalanche_GHOAvaxLaunch_20241106} from './AaveV3Avalanche_GHOAvaxLaunch_20241106.sol';

/**
* @dev Test for AaveV3Avalanche_GHOAvaxLaunch_20241106
* command: FOUNDRY_PROFILE=avalanche forge test --match-path=src/20241106_Multi_GHOAvaxLaunch/AaveV3Avalanche_GHOAvaxLaunch_20241106.t.sol -vv
*/
contract AaveV3Avalanche_GHOAvaxLaunch_20241106_Test is ProtocolV3TestBase {
AaveV3Avalanche_GHOAvaxLaunch_20241106 internal proposal;

function setUp() public {
vm.createSelectFork(vm.rpcUrl('avalanche'), 52758592);
proposal = new AaveV3Avalanche_GHOAvaxLaunch_20241106();
}

/**
* @dev executes the generic test suite including e2e and config snapshots
*/
function test_defaultProposalExecution() public {
defaultTest('AaveV3Avalanche_GHOAvaxLaunch_20241106', AaveV3Avalanche.POOL, address(proposal));
}
}
Loading