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

feat: collector upgrade #581

Merged
merged 5 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
33 changes: 33 additions & 0 deletions src/20250124_Multi_CollectorUpgrade/CollectorUpgrade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: "Collector upgrade"
author: "BGD Labs @bgdlabs"
discussions: "https://governance.aave.com/t/technical-maintenance-proposals/15274/63"
---

## Simple Summary

This proposal will upgrade the Aave Collector across all networks, to allow **multiple** funds admins.

## Motivation

Currently, the Aave Collector (treasury smart contract of the DAO, one per network) is managed by a single `Funds Admin` role, which across all Aave instances is configured to be the Governance Level 1 Executor (Short).

This setup is overly limiting and does not provide the flexibility needed to support usecases like the [Finance Steward](https://governance.aave.com/t/arfc-aave-finance-steward/17570) contracts proposed by Karpatkey & Tokenlogic.
sakulstra marked this conversation as resolved.
Show resolved Hide resolved

## Specification

The proposal will upgrade all collector contracts to the new version proposed on the aave-origin repository. To account for the differences in the storage layout, a custom initializer is implemented that aligns the storage layout across versions.

As the new version of the Collector implements AccessControl from OZ and removes the existing fundsAdmin role, the proposal will also grant the FUND_ADMIN role to the Level 1 Executor (Short Executor). This way, the setup post-proposal execution will be the same as currently.

## References

- [Implementation](https://github.com/bgd-labs/collector-upgrade-rev6/blob/main/src/CollectorWithCustomImpl.sol), [Linea & Zksync Implementation](https://github.com/bgd-labs/collector-upgrade-rev6/blob/main/src/CollectorWithCustomImplNewLayout.sol)
- [Tests](https://github.com/bgd-labs/collector-upgrade-rev6/tree/main/test)
- [Audit](https://github.com/aave-dao/aave-v3-origin/blob/fbf5c91d7b3f34fff44ac2affdcce5e809889098/audits/2025-01-20_Certora_CollectorRev6.pdf)
- [Upgraded Code](https://github.com/aave-dao/aave-v3-origin/blob/fbf5c91d7b3f34fff44ac2affdcce5e809889098/src/contracts/treasury/Collector.sol), [Code Changes](https://github.com/aave-dao/aave-v3-origin/pull/84)
- [Discussion](https://governance.aave.com/t/technical-maintenance-proposals/15274/63)

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
275 changes: 275 additions & 0 deletions src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
// 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, PolygonScript, AvalancheScript, OptimismScript, ArbitrumScript, MetisScript, BaseScript, GnosisScript, ScrollScript, BNBScript, LineaScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol';
import {Payloads} from './Payloads.sol';

/**
* @dev Deploy Ethereum
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployEthereum chain=mainnet
* verify-command: FOUNDRY_PROFILE=mainnet npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/1/run-latest.json
*/
contract DeployEthereum is EthereumScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.MAINNET);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Polygon
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployPolygon chain=polygon
* verify-command: FOUNDRY_PROFILE=polygon npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/137/run-latest.json
*/
contract DeployPolygon is PolygonScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.POLYGON);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Avalanche
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployAvalanche chain=avalanche
* verify-command: FOUNDRY_PROFILE=avalanche npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/43114/run-latest.json
*/
contract DeployAvalanche is AvalancheScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.AVALANCHE);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Optimism
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployOptimism chain=optimism
* verify-command: FOUNDRY_PROFILE=optimism npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/10/run-latest.json
*/
contract DeployOptimism is OptimismScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.OPTIMISM);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Arbitrum
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployArbitrum chain=arbitrum
* verify-command: FOUNDRY_PROFILE=arbitrum npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/42161/run-latest.json
*/
contract DeployArbitrum is ArbitrumScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.ARBITRUM);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Metis
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployMetis chain=metis
* verify-command: FOUNDRY_PROFILE=metis npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/1088/run-latest.json
*/
contract DeployMetis is MetisScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.METIS);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Base
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployBase chain=base
* verify-command: FOUNDRY_PROFILE=base npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/8453/run-latest.json
*/
contract DeployBase is BaseScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.BASE);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Gnosis
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployGnosis chain=gnosis
* verify-command: FOUNDRY_PROFILE=gnosis npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/100/run-latest.json
*/
contract DeployGnosis is GnosisScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.GNOSIS);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Scroll
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployScroll chain=scroll
* verify-command: FOUNDRY_PROFILE=scroll npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/534352/run-latest.json
*/
contract DeployScroll is ScrollScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.SCROLL);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy BNB
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployBNB chain=bnb
* verify-command: FOUNDRY_PROFILE=bnb npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/56/run-latest.json
*/
contract DeployBNB is BNBScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.BNB);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Linea
* deploy-command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployLinea chain=linea
* verify-command: FOUNDRY_PROFILE=linea npx catapulta-verify -b broadcast/CollectorUpgrade_20250124.s.sol/59144/run-latest.json
*/
contract DeployLinea is LineaScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(Payloads.LINEA);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Create Proposal
* command: make deploy-ledger contract=src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:CreateProposal chain=mainnet
*/
contract CreateProposal is EthereumScript {
function run() external {
// create payloads
PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](12);

// compose actions for validation
IPayloadsControllerCore.ExecutionAction[]
memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1);
actionsEthereum[0] = GovV3Helpers.buildAction(Payloads.MAINNET);
payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum);

IPayloadsControllerCore.ExecutionAction[]
memory actionsPolygon = new IPayloadsControllerCore.ExecutionAction[](1);
actionsPolygon[0] = GovV3Helpers.buildAction(Payloads.POLYGON);
payloads[1] = GovV3Helpers.buildPolygonPayload(vm, actionsPolygon);

IPayloadsControllerCore.ExecutionAction[]
memory actionsAvalanche = new IPayloadsControllerCore.ExecutionAction[](1);
actionsAvalanche[0] = GovV3Helpers.buildAction(Payloads.AVALANCHE);
payloads[2] = GovV3Helpers.buildAvalanchePayload(vm, actionsAvalanche);

IPayloadsControllerCore.ExecutionAction[]
memory actionsOptimism = new IPayloadsControllerCore.ExecutionAction[](1);
actionsOptimism[0] = GovV3Helpers.buildAction(Payloads.OPTIMISM);
payloads[3] = GovV3Helpers.buildOptimismPayload(vm, actionsOptimism);

IPayloadsControllerCore.ExecutionAction[]
memory actionsArbitrum = new IPayloadsControllerCore.ExecutionAction[](1);
actionsArbitrum[0] = GovV3Helpers.buildAction(Payloads.ARBITRUM);
payloads[4] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum);

IPayloadsControllerCore.ExecutionAction[]
memory actionsMetis = new IPayloadsControllerCore.ExecutionAction[](1);
actionsMetis[0] = GovV3Helpers.buildAction(Payloads.METIS);
payloads[5] = GovV3Helpers.buildMetisPayload(vm, actionsMetis);

IPayloadsControllerCore.ExecutionAction[]
memory actionsBase = new IPayloadsControllerCore.ExecutionAction[](1);
actionsBase[0] = GovV3Helpers.buildAction(Payloads.BASE);
payloads[6] = GovV3Helpers.buildBasePayload(vm, actionsBase);

IPayloadsControllerCore.ExecutionAction[]
memory actionsGnosis = new IPayloadsControllerCore.ExecutionAction[](1);
actionsGnosis[0] = GovV3Helpers.buildAction(Payloads.GNOSIS);
payloads[7] = GovV3Helpers.buildGnosisPayload(vm, actionsGnosis);

IPayloadsControllerCore.ExecutionAction[]
memory actionsScroll = new IPayloadsControllerCore.ExecutionAction[](1);
actionsScroll[0] = GovV3Helpers.buildAction(Payloads.SCROLL);
payloads[8] = GovV3Helpers.buildScrollPayload(vm, actionsScroll);

IPayloadsControllerCore.ExecutionAction[]
memory actionsBNB = new IPayloadsControllerCore.ExecutionAction[](1);
actionsBNB[0] = GovV3Helpers.buildAction(Payloads.BNB);
payloads[9] = GovV3Helpers.buildBNBPayload(vm, actionsBNB);

IPayloadsControllerCore.ExecutionAction[]
memory actionsZkSync = new IPayloadsControllerCore.ExecutionAction[](1);
actionsZkSync[0] = GovV3Helpers.buildAction(Payloads.ZKSYNC);
payloads[10] = GovV3Helpers.buildZkSyncPayload(vm, actionsZkSync);

IPayloadsControllerCore.ExecutionAction[]
memory actionsLinea = new IPayloadsControllerCore.ExecutionAction[](1);
actionsLinea[0] = GovV3Helpers.buildAction(Payloads.LINEA);
payloads[11] = GovV3Helpers.buildLineaPayload(vm, actionsLinea);

// create proposal
vm.startBroadcast();
GovV3Helpers.createProposal(
vm,
payloads,
GovernanceV3Ethereum.VOTING_PORTAL_ETH_POL,
GovV3Helpers.ipfsHashFile(vm, 'src/20250124_Multi_CollectorUpgrade/CollectorUpgrade.md')
);
}
}
17 changes: 17 additions & 0 deletions src/20250124_Multi_CollectorUpgrade/Payloads.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Payloads {
address constant MAINNET = 0x0743A8976FC251d0C5b7327ed1F004788F2eB0aF;
address constant SCROLL = 0x8b8bf083fD1837486c141681E10Ea61D0f3cD692;
address constant OPTIMISM = 0xf1e6d4347105138B51E2bacA9A22fA228309ebB1;
address constant ARBITRUM = 0x13F331258205f948cb6a148Afe990145079a9B18;
address constant GNOSIS = 0xbCb167bDCF14a8F791d6f4A6EDd964aed2F8813B;
address constant POLYGON = 0x318FE302B7cb1045547ECA7C847f87AB1Db122Cf;
address constant AVALANCHE = 0x55c09b4Df32606667dBdF7dc846417bFb4Cec776;
address constant BASE = 0x6b4E260b765B3cA1514e618C0215A6B7839fF93e;
address constant METIS = 0x04a8D477eE202aDCE1682F5902e1160455205b12;
address constant BNB = 0x8b8bf083fD1837486c141681E10Ea61D0f3cD692;
address constant LINEA = 0xd91d1331db4F436DaF47Ec9Dd86deCb8EEF946B4;
address constant ZKSYNC = 0xA1900dD73e46Ad013fA87f5f70072c472D8f4770;
}
40 changes: 40 additions & 0 deletions src/20250124_Multi_CollectorUpgrade/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {ConfigFile} from '../../generator/types';
export const config: ConfigFile = {
rootOptions: {
author: 'BGD Labs @bgdlabs',
pools: [
'AaveV3Ethereum',
'AaveV3Polygon',
'AaveV3Avalanche',
'AaveV3Optimism',
'AaveV3Arbitrum',
'AaveV3Metis',
'AaveV3Base',
'AaveV3Gnosis',
'AaveV3Scroll',
'AaveV3BNB',
'AaveV3ZkSync',
'AaveV3Linea',
],
title: 'Collector upgrade',
shortName: 'CollectorUpgrade',
date: '20250124',
discussion: 'https://governance.aave.com/t/technical-maintenance-proposals/15274/63',
snapshot: '',
votingNetwork: 'POLYGON',
},
poolOptions: {
AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 21693718}},
AaveV3Polygon: {configs: {OTHERS: {}}, cache: {blockNumber: 67083310}},
AaveV3Avalanche: {configs: {OTHERS: {}}, cache: {blockNumber: 56282481}},
AaveV3Optimism: {configs: {OTHERS: {}}, cache: {blockNumber: 131057593}},
AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 298749428}},
AaveV3Metis: {configs: {OTHERS: {}}, cache: {blockNumber: 19553469}},
AaveV3Base: {configs: {OTHERS: {}}, cache: {blockNumber: 25462310}},
AaveV3Gnosis: {configs: {OTHERS: {}}, cache: {blockNumber: 38202526}},
AaveV3Scroll: {configs: {OTHERS: {}}, cache: {blockNumber: 12931198}},
AaveV3BNB: {configs: {OTHERS: {}}, cache: {blockNumber: 46044224}},
AaveV3ZkSync: {configs: {OTHERS: {}}, cache: {blockNumber: 54433709}},
AaveV3Linea: {configs: {OTHERS: {}}, cache: {blockNumber: 14978552}},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {GovV3Helpers, IPayloadsControllerCore} from 'aave-helpers/src/GovV3Helpers.sol';
import {ZkSyncScript} from 'solidity-utils/contracts/utils/ScriptUtils.sol';

/**
* @dev Deploy ZkSync
* deploy-command: make deploy-pk FOUNDRY_PROFILE=contract=zksync/src/20250124_Multi_CollectorUpgrade/CollectorUpgrade_20250124.s.sol:DeployZkSync chain=zksync
*/
contract DeployZkSync is ZkSyncScript {
function run() external broadcast {
// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(0xA1900dD73e46Ad013fA87f5f70072c472D8f4770);

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}
Loading