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 the
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 that was unused. In v3.4, this feature is removed. - The
virtualUnderlyingBalanceslot (previously__deprecatedVirtualUnderlyingBalance) is moved into the storage slot formerly 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
-
Flash Loan 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.3Poolvia_pool.FLASHLOAN_PREMIUM_TO_PROTOCOL()during itsinitializefunction. It emits an event (FlashloanPremiumToProtocolUpdated) if this value 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 the logic needed for subsequent steps (like token updates). Theinitializefunction of this new configurator captures the old flash loan premium. - Upgrade Pool Implementation: The
Poolcontract is updated to the newPoolInstanceWithCustomInitializeimplementation (orL2PoolInstanceWithCustomInitializeon 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):
- Cover existing GHO deficit: Existing
GHOdeficit is covered via the deficit steward. - Update Deficit Steward Allowance: The payload checks for any allowance of the underlying
GHOtoken granted to theDEFICIT_OFFSET_CLINIC_STEWARD. If an allowance exists, it is revoked for the underlyingGHO, and a new approval for the same amount is granted for theGHO AToken(aGHO). This adapts the deficit coverage mechanism to utilize aTokens instead of the underlying GHO. - Grant Facilitator Risk Admin: The
ACL_MANAGERgrants theRISK_ADMINrole to theGhoDirectMintercontract (FACILITATOR). This allowsFACILITATORto callsetSupplyCap. - 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 to 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. This is a 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 in return. - 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. - Check and potentiall remove uni delegation
- Execute Default Upgrade Steps: The
_defaultUpgrade()function is called, performing steps 2, 3, and 4 from the "General Upgrade Sequence" above (Upgrade Pool Implementation, Set New PoolDataProvider, Update AToken/VariableDebtToken Implementations for standard tokens), skipping GHO and AAVE tokens as specified by the overridden_needToUpdateReservefunction. - 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 Flash Loans:
POOL_CONFIGURATOR.setReserveFlashLoaningis called to enable flash loans for the GHO reserve. - Mint GHO to the Pool: The
mintAndSupplyfunction is called once again to mint the remaining (non-borrowed) capacity as supply to the pool. - Add Steward Permissions:
setControlledFacilitatoris called on the bucket facilitator to migrate permissions to the new facilitator.
For non-zksync(shanghai) networks:
FOUNDRY_LIBRARIES=aave-v3-origin/contracts/protocol/libraries/logic/BorrowLogic.sol:BorrowLogic:0x5047AD5e603Ec4a2AB58aaE2321C07D8f4De6a8a,aave-v3-origin/contracts/protocol/libraries/logic/ConfiguratorLogic.sol:ConfiguratorLogic:0x6E2aFD57a161d12f34f416c29619BFeAcAC8AA18,aave-v3-origin/contracts/protocol/libraries/logic/EModeLogic.sol:EModeLogic:0x7fcE69A2bA3e78EeB36798cde2c94C70f3A043af,aave-v3-origin/contracts/protocol/libraries/logic/FlashLoanLogic.sol:FlashLoanLogic:0x4fDB5d360f946CFD25b14F346f748204c0C6a2F4,aave-v3-origin/contracts/protocol/libraries/logic/LiquidationLogic.sol:LiquidationLogic:0x5934b283f7120500253f277CCcF4521528aE34D6,aave-v3-origin/contracts/protocol/libraries/logic/PoolLogic.sol:PoolLogic:0x564c42578A1b270EaE16c25Da39d901245881d1F,aave-v3-origin/contracts/protocol/libraries/logic/SupplyLogic.sol:SupplyLogic:0x1eF34B91afC368174F579067D1DB94325cDC7946
For linea(london):
FOUNDRY_LIBRARIES=aave-v3-origin/contracts/protocol/libraries/logic/BorrowLogic.sol:BorrowLogic:0x24B58926d2Dd490238C6366dc7b36357caBd71b9,aave-v3-origin/contracts/protocol/libraries/logic/ConfiguratorLogic.sol:ConfiguratorLogic:0xD379a9e4A925916cF69c16C34409F401a28d5A52,aave-v3-origin/contracts/protocol/libraries/logic/EModeLogic.sol:EModeLogic:0x23Bde27B7be7C2Eb741c3BcEF95384AAEc4f084c,aave-v3-origin/contracts/protocol/libraries/logic/FlashLoanLogic.sol:FlashLoanLogic:0x001b936869b535B4AF6F77a9be033801B39fcfa6,aave-v3-origin/contracts/protocol/libraries/logic/LiquidationLogic.sol:LiquidationLogic:0xED56ED0316FECBF93E3F5cA5aE70b8eF48ad4535,aave-v3-origin/contracts/protocol/libraries/logic/PoolLogic.sol:PoolLogic:0xca1610aE2820d34EB717b43e3CB1dd33B7eC05FB,aave-v3-origin/contracts/protocol/libraries/logic/SupplyLogic.sol:SupplyLogic:0x8bd15bbd01e987D4b851818b6586AA6E16E65c62
For zksync(cancun):
FOUNDRY_LIBRARIES=aave-v3-origin/contracts/protocol/libraries/logic/BorrowLogic.sol:BorrowLogic:0x3db1dc584758daba133a59f776503b6c5d2dd1db,aave-v3-origin/contracts/protocol/libraries/logic/ConfiguratorLogic.sol:ConfiguratorLogic:0x511eaFe32D70Aad1f0F87BAe560cbC2Ec88B34Db,aave-v3-origin/contracts/protocol/libraries/logic/EModeLogic.sol:EModeLogic:0xcdae69765333cae780e4bf6dcb7db886fae0b5a1,aave-v3-origin/contracts/protocol/libraries/logic/FlashLoanLogic.sol:FlashLoanLogic:0xF8b48c00Ff12dD97F961EFE5240eBe956a3D8687,aave-v3-origin/contracts/protocol/libraries/logic/LiquidationLogic.sol:LiquidationLogic:0x78ca5c313c8a3265a8bf69a645564181970be9c1,aave-v3-origin/contracts/protocol/libraries/logic/PoolLogic.sol:PoolLogic:0x4511b06e1524929a4a90c5dd2aca59c8df728e8a,aave-v3-origin/contracts/protocol/libraries/logic/SupplyLogic.sol:SupplyLogic:0x0095325bb5C5da5b19C92bb6919f80110dcbaEFF