This document outlines the technical process for upgrading the Aave V3 protocol from version 3.3 to version 3.4 across various networks.
The upgrade is executed via specialized UpgradePayload contracts deployed on each network. A specific version, UpgradePayloadMainnet, handles additional steps required for the Ethereum Mainnet due to the GHO token migration.
- New Implementations: New implementations for
Pool,PoolConfigurator,AToken,VariableDebtToken, andPoolDataProvidercontracts are deployed. These incorporate the v3.4 features and optimizations. - Custom Initializers: Special logic (
CustomInitialize.sol) is embedded within the newPoolimplementations (PoolInstanceWithCustomInitialize,L2PoolInstanceWithCustomInitialize) to handle storage slot migrations during the upgrade. A customPoolConfigurator(PoolConfiguratorWithCustomInitialize) is used to capture state before the main pool upgrade. - GHO Specific Contracts (Mainnet): Custom implementations for
aGHO(ATokenMainnetInstanceGHO) andvGHO(VariableDebtTokenMainnetInstanceGHO) are used during the Mainnet upgrade to facilitate the GHO facilitator migration and clean up deprecated storage slots. A newGhoDirectMintercontract is deployed to take over GHO facilitation from the oldaGHO. - Upgrade Payloads:
UpgradePayload(for most networks) andUpgradePayloadMainnet(for Ethereum Mainnet) contain the sequenced steps to orchestrate the upgrade. - Deployment Scripts: Forge scripts (
Deploy.s.sol) are used to deterministically deploy all necessary new implementation contracts and the corresponding upgrade payload contract for each network.
Several changes in v3.4 require specific actions during the upgrade process:
-
Storage Slot Migration (
virtualUnderlyingBalance):- In v3.3, reserves had an
unbackedstorage slot which was unused. In v3.4, this feature is removed. - The
virtualUnderlyingBalanceslot (previously__deprecatedVirtualUnderlyingBalance) is moved into the storage slot previously occupied byunbackedfor gas optimization. - Action: The
initializefunction within the newPoolimplementations (PoolInstanceWithCustomInitialize,L2PoolInstanceWithCustomInitialize), using theCustomInitialize._initializelibrary function, iterates through all reserves upon the first initialization after the upgrade. It copies the value from the old__deprecatedVirtualUnderlyingBalanceslot to the newvirtualUnderlyingBalanceslot and zeroes out the old slot.
- In v3.3, reserves had an
-
Flashloan Premium Capture:
- The
FLASHLOAN_PREMIUM_TO_PROTOCOLbecomes a constant (100_00) in the v3.4Poolimplementation. - Action: The
PoolConfiguratorWithCustomInitializeimplementation, which is set before the Pool is upgraded, reads the old dynamic value from the v3.3 Pool via_pool.FLASHLOAN_PREMIUM_TO_PROTOCOL()during itsinitializefunction and emits an event (FlashloanPremiumToProtocolUpdated) if it differs from the new constant value. This ensures the old value is recorded before it becomes inaccessible.
- The
-
Deprecated Storage Cleanup (GHO Tokens on Mainnet):
- The v3.3
aGHOandvGHOcontracts contained specific storage variables (ghoVariableDebtToken,ghoTreasuryin aToken;ghoAToken,discountToken,discountRateStrategyin vToken) that are not present in standard tokens or the v3.4 GHO tokens. - Action:
- The custom
ATokenMainnetInstanceGHOimplementation'sresolveFacilitatorfunction (called during the GHO migration) explicitly deletes the deprecated aToken storage slots. - The custom
VariableDebtTokenMainnetInstanceGHOimplementation'sinitializefunction explicitly deletes the deprecated vToken storage slots. - This cleanup prevents potential storage collisions if future Aave versions add new variables at these storage slots for standard tokens.
- The custom
- The v3.3
This sequence applies to most networks (Polygon, Optimism, Arbitrum, etc.).
- Upgrade PoolConfigurator Implementation: The
PoolConfiguratorcontract is updated to the newPoolConfiguratorWithCustomInitializeimplementation. This is done first to ensure compatibility with v3.4 interfaces and logic needed for subsequent steps (like token updates). Theinitializefunction of this new configurator captures the old flashloan premium. - Upgrade Pool Implementation: The
Poolcontract is updated to the newPoolInstanceWithCustomInitializeimplementation (orL2PoolInstanceWithCustomInitializein L2 networks). Theinitializefunction of this new pool handles thevirtualUnderlyingBalancestorage migration. - Set New PoolDataProvider: The
PoolAddressesProvideris updated to point to the newAaveProtocolDataProviderimplementation. - Update AToken/VariableDebtToken Implementations: The payload iterates through all reserves listed in the Pool:
- For each reserve, it calls
POOL_CONFIGURATOR.updateATokento upgrade the reserve's AToken proxy to the new standardATokenInstanceimplementation (A_TOKEN_IMPL). - It then calls
POOL_CONFIGURATOR.updateVariableDebtTokento upgrade the reserve's VariableDebtToken proxy to the new standardVariableDebtTokenInstanceimplementation (V_TOKEN_IMPL).
- For each reserve, it calls
This sequence includes the general steps plus specific GHO migration steps, executed in a precise order after the UpgradePayloadMainnet contract is deployed.
Pre-Execution Step (Payload Constructor):
- Deploy and Initialize New Facilitator: The new
GhoDirectMinterproxy contract (FACILITATOR) is deployed and initialized using theTransparentProxyFactorywithin theconstructorof theUpgradePayloadMainnetcontract. Its implementation, admin, owner (Executor LVL 1), and council are set during this deployment process.
Execution Steps (Inside execute() function):
- Grant Facilitator Risk Admin: The
ACL_MANAGERgrants theRISK_ADMINrole to theGhoDirectMintercontract (FACILITATOR). This allows it to callsetSupplyCapby theGhoDirectMintercontract. - Add New Facilitator to GhoToken:
- The current GHO bucket capacity and level of the old
aGHOfacilitator are fetched from theGhoToken. - The new
GhoDirectMinter(FACILITATOR) is added as a GHO facilitator in theGhoTokencontract (IGhoToken(...).addFacilitator(...)) using the fetched capacity.
- The current GHO bucket capacity and level of the old
- Distribute Old aGHO Fees:
IOldATokenMainnetInstanceGHO(AaveV3EthereumAssets.GHO_A_TOKEN).distributeFeesToTreasury()is called to send any accumulated GHO fees in the old aToken contract to the treasury. It is required step to make the balance of theGHO_A_TOKENequal to zero. - Upgrade PoolConfigurator Implementation: The
PoolConfiguratorcontract is updated to the newPoolConfiguratorWithCustomInitializeimplementation. - Upgrade aGHO to Custom Intermediate Implementation:
POOL_CONFIGURATOR.updateATokenis called for the GHO asset, setting its implementation to the customATokenMainnetInstanceGHO(A_TOKEN_GHO_IMPL). This implementation includes theresolveFacilitatorfunction and storage cleanup logic. - Mint and Supply by New Facilitator: The
mintAndSupplyfunction of the newGhoDirectMinter(FACILITATOR) is called, minting GHO equal to the oldaGHOfacilitator'sleveland supplying it to the Aave pool, receivingaGHOtokens. - Resolve Old Facilitator:
IATokenMainnetInstanceGHO(AaveV3EthereumAssets.GHO_A_TOKEN).resolveFacilitator(level)is called. This function on the customaGHOimplementation burns the underlying GHO token amount equal tolevel(balancing the mint in step 6) and clears the deprecated storage slots within theaGHOcontract proxy's storage. - Remove Old Facilitator:
IGhoToken(AaveV3EthereumAssets.GHO_UNDERLYING).removeFacilitator(AaveV3EthereumAssets.GHO_A_TOKEN)is called. Since its level is now 0 (due to the burn in step 7), the oldaGHOcontract is successfully removed as a facilitator from theGhoToken. - Set GHO Reserve Factor:
POOL_CONFIGURATOR.setReserveFactorsets GHO's reserve factor to 100% (10000). - Set GHO Supply Cap:
POOL_CONFIGURATOR.setSupplyCapsets GHO's supply cap to 1 wei, effectively preventing user GHO deposits. - Execute Default Upgrade Steps: The
_defaultUpgrade()function is called, performing steps 2, 3, and 4 from the "General Upgrade Sequence" above (Upgrade Pool Impl, Set Data Provider, Update standard A/V Tokens), skipping GHO and AAVE tokens as specified by the overridden_needToUpdateReserve. - Upgrade vGHO to Custom Implementation:
POOL_CONFIGURATOR.updateVariableDebtTokenis called for GHO, setting its implementation to the customVariableDebtTokenMainnetInstanceGHO(V_TOKEN_GHO_IMPL). This version includes storage cleanup and a no-opupdateDiscountDistributionfunction for compatibility. - Upgrade aAAVE Implementation:
POOL_CONFIGURATOR.updateATokenupdates the AAVE AToken to theATokenWithDelegationInstance(A_TOKEN_WITH_DELEGATION_IMPL). - Upgrade vAAVE Implementation:
POOL_CONFIGURATOR.updateVariableDebtTokenupdates the AAVE VariableDebtToken to the standardVariableDebtTokenInstance(V_TOKEN_IMPL). - Enable GHO Flashloaning:
POOL_CONFIGURATOR.setReserveFlashLoaningenables flash loans for the GHO reserve. - Mint GHO to the pool: Calling the
mintAndSupplyfunction once again to mint the remaining(non borrowed) capacity as supply on the pool. - Add stewards permissions: Calling
setControlledFacilitatoron the bucket facilitator migrate permissions to the new facilitator.