Skip to content

Commit

Permalink
Add supporting files
Browse files Browse the repository at this point in the history
Co-authored-by: Gary Ghayrat <[email protected]>
  • Loading branch information
wildmolasses and garyghayrat committed Aug 28, 2024
1 parent f180c40 commit c89c349
Show file tree
Hide file tree
Showing 16 changed files with 2,308 additions and 1 deletion.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ARBITRUM_ONE_RPC_URL=
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# when changing optimizer settings, make sure to also change settings in hardhat.config.ts
[profile.default]
src = 'src'
script = 'script'
out = 'out'
libs = ['lib']
optimizer = true
Expand Down
16 changes: 16 additions & 0 deletions script/BaseDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {Script} from "forge-std/Script.sol";

// Basic shared infrastructure for all deploy scripts
contract BaseDeployer is Script {
uint256 deployerPrivateKey;

function setUp() public virtual {
deployerPrivateKey =
vm.envOr("DEPLOYER_PRIVATE_KEY", uint256(0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80));
}
}
46 changes: 46 additions & 0 deletions script/BaseGovernorDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {BaseDeployer} from "script/BaseDeployer.sol";
import {SharedGovernorConstants} from "script/SharedGovernorConstants.sol";
import {L2ArbitrumGovernorV2} from "src/L2ArbitrumGovernorV2.sol";
import {TransparentUpgradeableProxy} from
"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {TimelockControllerUpgradeable} from
"openzeppelin-upgradeable-v5/governance/TimelockControllerUpgradeable.sol";
import {IVotes} from "openzeppelin-v5/governance/utils/IVotes.sol";

// This base deployer contract is meant to be inherited by each concrete script written to deploy a specific governor,
// namely the Treasury Governor and Core Governor. It includes the base deployment logic, shared constants, and
// defines the virtual methods for values which must be provided by each concrete implementation.
abstract contract BaseGovernorDeployer is BaseDeployer, SharedGovernorConstants {
// Virtual methods returning initialization parameters that must be implemented by
// each concrete deploy script.
function NAME() public virtual returns (string memory);
function TIMELOCK_ADDRESS() public virtual returns (address payable);
function QUORUM_NUMERATOR() public virtual returns (uint256);

function run(address _implementation) public virtual returns (L2ArbitrumGovernorV2 _governor) {
vm.startBroadcast(deployerPrivateKey);
bytes memory _initData = abi.encodeCall(
L2ArbitrumGovernorV2.initialize,
(
NAME(),
INITIAL_VOTING_DELAY,
INITIAL_VOTING_PERIOD,
INITIAL_PROPOSAL_THRESHOLD,
IVotes(L2_ARB_TOKEN_ADDRESS),
TimelockControllerUpgradeable(TIMELOCK_ADDRESS()),
QUORUM_NUMERATOR(),
INITIAL_VOTE_EXTENSION,
L2_UPGRADE_EXECUTOR
)
);
TransparentUpgradeableProxy _proxy =
new TransparentUpgradeableProxy(_implementation, L2_PROXY_ADMIN, _initData);
_governor = L2ArbitrumGovernorV2(payable(address(_proxy)));
vm.stopBroadcast();
}
}
25 changes: 25 additions & 0 deletions script/DeployCoreGovernor.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {BaseGovernorDeployer, L2ArbitrumGovernorV2} from "script/BaseGovernorDeployer.sol";

// Concrete deployment script for the Arbitrum L2 Core Governor.
contract DeployCoreGovernor is BaseGovernorDeployer {
function NAME() public pure override returns (string memory) {
return "Core L2ArbitrumGovernor";
}

function TIMELOCK_ADDRESS() public pure override returns (address payable) {
return payable(L2_CORE_GOVERNOR_TIMELOCK);
}

function QUORUM_NUMERATOR() public pure override returns (uint256) {
return 500;
}

function run(address _implementation) public override returns (L2ArbitrumGovernorV2 _governor) {
return super.run(_implementation);
}
}
16 changes: 16 additions & 0 deletions script/DeployImplementation.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {BaseDeployer} from "script/BaseDeployer.sol";
import {L2ArbitrumGovernorV2} from "src/L2ArbitrumGovernorV2.sol";

// Deploy script for the underlying implementation that will be used by both Governor proxies
contract DeployImplementation is BaseDeployer {
function run() public returns (L2ArbitrumGovernorV2 _implementation) {
vm.startBroadcast(deployerPrivateKey);
_implementation = new L2ArbitrumGovernorV2();
vm.stopBroadcast();
}
}
27 changes: 27 additions & 0 deletions script/DeployTimelockRolesUpgrader.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {BaseDeployer} from "script/BaseDeployer.sol";
import {TimelockRolesUpgrader} from
"src/gov-action-contracts/gov-upgrade-contracts/update-timelock-roles/TimelockRolesUpgrader.sol";
import {SharedGovernorConstants} from "script/SharedGovernorConstants.sol";

contract DeployTimelockRolesUpgrader is BaseDeployer, SharedGovernorConstants {
function run(address _newCoreGovernor, address _newTreasuryGovernor)
public
returns (TimelockRolesUpgrader timelockRolesUpgrader)
{
vm.startBroadcast();
timelockRolesUpgrader = new TimelockRolesUpgrader(
L2_CORE_GOVERNOR_TIMELOCK,
L2_CORE_GOVERNOR,
_newCoreGovernor,
L2_TREASURY_GOVERNOR_TIMELOCK,
L2_TREASURY_GOVERNOR,
_newTreasuryGovernor
);
vm.stopBroadcast();
}
}
25 changes: 25 additions & 0 deletions script/DeployTreasuryGovernor.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {BaseGovernorDeployer, L2ArbitrumGovernorV2} from "script/BaseGovernorDeployer.sol";

// Concrete deployment script for the Arbitrum L2 Core Governor.
contract DeployTreasuryGovernor is BaseGovernorDeployer {
function NAME() public pure override returns (string memory) {
return "Treasury L2ArbitrumGovernor";
}

function TIMELOCK_ADDRESS() public pure override returns (address payable) {
return payable(L2_TREASURY_GOVERNOR_TIMELOCK);
}

function QUORUM_NUMERATOR() public pure override returns (uint256) {
return 300;
}

function run(address _implementation) public override returns (L2ArbitrumGovernorV2 _governor) {
return super.run(_implementation);
}
}
95 changes: 95 additions & 0 deletions script/SharedGovernorConstants.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

// Inheritable extension holding governor deployment constants that are shared between the Core Governor and the
// Treasury Governor. These should be carefully checked and reviewed before final deployment.
contract SharedGovernorConstants {
uint256 constant FORK_BLOCK = 245_608_716; // Arbitrary recent block
address public constant L2_ARB_TOKEN_ADDRESS = 0x912CE59144191C1204E64559FE8253a0e49E6548;

address public constant L2_CORE_GOVERNOR = 0xf07DeD9dC292157749B6Fd268E37DF6EA38395B9;
address public constant L2_CORE_GOVERNOR_TIMELOCK = 0x34d45e99f7D8c45ed05B5cA72D54bbD1fb3F98f0;
address public constant L2_TREASURY_GOVERNOR = 0x789fC99093B09aD01C34DC7251D0C89ce743e5a4;
address public constant L2_TREASURY_GOVERNOR_TIMELOCK =
0xbFc1FECa8B09A5c5D3EFfE7429eBE24b9c09EF58;
address public constant L2_PROXY_ADMIN = 0xdb216562328215E010F819B5aBe947bad4ca961e;

address public constant L2_ARB_SYS = 0x0000000000000000000000000000000000000064;
address public constant L2_ARB_TREASURY_FIXED_DELEGATE =
0xF3FC178157fb3c87548bAA86F9d24BA38E649B58;
address public constant L2_ARB_RETRYABLE_TX = 0x000000000000000000000000000000000000006E;
address public constant L2_SECURITY_COUNCIL_9 = 0x423552c0F05baCCac5Bfa91C6dCF1dc53a0A1641;

address public constant L1_TIMELOCK = 0xE6841D92B0C345144506576eC13ECf5103aC7f49;
uint256 public constant L1_TIMELOCK_MIN_DELAY = 259_200; // TODO: Make sure this is up to date.
address public constant L1_ARB_ONE_DELAYED_INBOX = 0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f;

address public constant L2_CORE_GOVERNOR_ONCHAIN = 0x7796F378B3c56ceD57350B938561D8c52256456b;
address public constant L2_TREASURY_GOVERNOR_ONCHAIN =
0x4fd1216c8b5E72b22785169Ae5C1e8f3b30C19E4;
bool public constant UPGRADE_PROPOSAL_PASSED_ONCHAIN = false; // TODO: Update after the upgrade proposal is passed.

address public constant L2_UPGRADE_EXECUTOR = 0xCF57572261c7c2BCF21ffD220ea7d1a27D40A827;

address public constant RETRYABLE_TICKET_MAGIC = 0xa723C008e76E379c55599D2E4d93879BeaFDa79C;

address public constant EXCLUDE_ADDRESS = address(0xA4b86);
uint256 public constant QUORUM_DENOMINATOR = 10_000;

bytes32 public constant TIMELOCK_PROPOSER_ROLE =
0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1;

uint8 public constant VOTE_TYPE_FRACTIONAL = 255;

// These values match the current production values for both governors. Note that they are expressed in L1 blocks,
// with an assumed 12 second block time, because on Arbitrum, block.number returns the number of the L1.
uint48 public constant INITIAL_VOTING_DELAY = 21_600; // 3 days
uint32 public constant INITIAL_VOTING_PERIOD = 100_800; // 14 days
uint48 public constant INITIAL_VOTE_EXTENSION = 14_400; // 2 days

// This value matches the current production value for both governors. 1M Arb in raw decimals.
uint256 public constant INITIAL_PROPOSAL_THRESHOLD = 1_000_000_000_000_000_000_000_000;

address[] public _majorDelegates;

enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Queued,
Expired,
Executed
}

enum VoteType {
Against,
For,
Abstain
}

constructor() {
_majorDelegates = new address[](18);
_majorDelegates[0] = 0x1B686eE8E31c5959D9F5BBd8122a58682788eeaD; // L2BEAT
_majorDelegates[1] = 0xF4B0556B9B6F53E00A1FDD2b0478Ce841991D8fA; // olimpio
_majorDelegates[2] = 0x11cd09a0c5B1dc674615783b0772a9bFD53e3A8F; // Gauntlet
_majorDelegates[3] = 0xB933AEe47C438f22DE0747D57fc239FE37878Dd1; // Wintermute
_majorDelegates[4] = 0x0eB5B03c0303f2F47cD81d7BE4275AF8Ed347576; // Treasure
_majorDelegates[5] = 0xF92F185AbD9E00F56cb11B0b709029633d1E37B4; //
_majorDelegates[6] = 0x186e505097BFA1f3cF45c2C9D7a79dE6632C3cdc;
_majorDelegates[7] = 0x5663D01D8109DDFC8aACf09fBE51F2d341bb3643;
_majorDelegates[8] = 0x2ef27b114917dD53f8633440A7C0328fef132e2F; // MUX Protocol
_majorDelegates[9] = 0xE48C655276C23F1534AE2a87A2bf8A8A6585Df70; // ercwl
_majorDelegates[10] = 0x8A3e9846df0CDc723C06e4f0C642ffFF82b54610;
_majorDelegates[11] = 0xAD16ebE6FfC7d96624A380F394cD64395B0C6144; // DK (Premia)
_majorDelegates[12] = 0xA5dF0cf3F95C6cd97d998b9D990a86864095d9b0; // Blockworks Research
_majorDelegates[13] = 0x839395e20bbB182fa440d08F850E6c7A8f6F0780; // Griff Green
_majorDelegates[14] = 0x2e3BEf6830Ae84bb4225D318F9f61B6b88C147bF; // Camelot
_majorDelegates[15] = 0x8F73bE66CA8c79382f72139be03746343Bf5Faa0; // mihal.eth
_majorDelegates[16] = 0xb5B069370Ef24BC67F114e185D185063CE3479f8; // Frisson
_majorDelegates[17] = 0xdb5781a835b60110298fF7205D8ef9678Ff1f800; // yoav.eth
}
}
95 changes: 95 additions & 0 deletions script/SubmitUpgradeProposalScript.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: AGPL-3.0-only
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {Script} from "forge-std/Script.sol";
import {SharedGovernorConstants} from "script/SharedGovernorConstants.sol";
import {GovernorUpgradeable} from "openzeppelin-upgradeable-v5/governance/GovernorUpgradeable.sol";
import {CreateL2ArbSysProposal} from "script/helpers/CreateL2ArbSysProposal.sol";

contract SubmitUpgradeProposalScript is Script, SharedGovernorConstants, CreateL2ArbSysProposal {
// TODO: Update `PROPOSER` to script msg.sender who will submit the proposal.
address PROPOSER = 0x1B686eE8E31c5959D9F5BBd8122a58682788eeaD; // L2Beat
// TODO: Update `minDelay` to latest getMinDelay() from L1Timelock.
uint256 minDelay = 259_200;

function run(address _timelockRolesUpgrader)
public
returns (
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description,
uint256 _proposalId
)
{
return proposeUpgrade(_timelockRolesUpgrader);
}

function proposeUpgrade(address _timelockRolesUpgrader)
internal
returns (
address[] memory _targets,
uint256[] memory _values,
bytes[] memory _calldatas,
string memory _description,
uint256 _proposalId
)
{
// TODO: Before deployment update `_description` with the new governor contract addresses.
_description =
"# Proposal to Upgrade Governor Contracts \
\
### **Abstract** \
This proposal will transfer the proposer and canceller roles from the current Arbitrum Core Governor and Arbitrum Treasury Governor to newly deployed Governor contracts. This roles transfer is a crucial step in upgrading the Arbitrum DAO's governance infrastructure. \
\
### Motivation \
This upgrade to the Arbitrum DAO's governance system was initially discussed as part of the 'Expand Tally Support for the Arbitrum DAO' proposal https://forum.arbitrum.foundation/t/expand-tally-support-for-the-arbitrum-dao/22387. The community recognized the need for enhanced governance features, including proposal cancellation and flexible voting mechanisms. \
\
As a result of these discussions, new Governor contracts have been developed and deployed with these improvements. To activate these enhancements and complete the upgrade process, we now need to transfer the proposer role to these new contracts. \
\
### **Specifications** \
This proposal will: \
\
1. Grant the newly deployed Core Governor and Treasury Governor contracts the 'PROPOSER_ROLE' and 'CANCELLER_ROLE' on the timelock contract. \
2. Revoke the current Core Governor and Treasury Governor contracts' 'PROPOSER_ROLE' and 'CANCELLER_ROLE' on the timelock contract. \
\
### **Technical Details** \
- The new Governor contracts have been deployed on Arbitrum One at the following addresses: \
TODO: [Insert new Core Governor address] \
TODO: [Insert new Treasury Governor address] \
\
- These new contracts include the following enhancements: \
1. Proposal Cancellation: Allows the delegate who submitted a proposal to cancel it during the delay phase, before voting begins. \
2. Flexible Voting: Enables delegates to cast rolling, fractional votes, supporting future innovations like voting from Orbit chains and more. \
\
- The new Governors maintain all existing features of the current Governors, including custom relay functionality and fractional quorum calculations. \
\
### **Rationale** \
The rationale for upgrading the Governors by granting and revoking roles on the Timelock contract instead of using the proxy upgradeable contract pattern is discussed in this forum post: https://forum.arbitrum.foundation/t/arbitrum-governance-smart-contract-upgrade-technical-details/24642 \
\
### **Security Considerations** \
- The new Governor contracts have been tested and audited by OpenZeppelin. \
- This transfer does not move any funds or change permissions on the Timelock contracts. \
- Historical governance actions will remain visible and valid. \
\
### **Post-Transfer Actions** \
- Immediately after this transfer executes, Tally will update to interface with the new Governor contracts. \
- Delegates should use the new Governor contracts for all future proposal submissions. \
- The old Governor contracts will remain on-chain but will no longer have the ability to execute proposals. \
\
### **Timeline** \
If this proposal passes, the transfer will be executed immediately after the Timelock delay. \
\
By approving this proposal, the Arbitrum DAO will upgrade its governance infrastructure, enabling new features and improvements in the governance process. \
";
(_targets, _values, _calldatas) =
createL2ArbSysProposal(_description, _timelockRolesUpgrader, minDelay);
vm.startBroadcast(PROPOSER);
_proposalId = GovernorUpgradeable(payable(L2_CORE_GOVERNOR)).propose(
_targets, _values, _calldatas, _description
);
vm.stopBroadcast();
}
}
Loading

0 comments on commit c89c349

Please sign in to comment.