Skip to content

Commit

Permalink
feat deploy mainnet governance
Browse files Browse the repository at this point in the history
* feat deploy mainnet governance

* update todo

* remove via-ir test fail
  • Loading branch information
GuillaumeNervoXS authored Jan 12, 2024
1 parent 6ae6eeb commit 1d5f908
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 144 deletions.
11 changes: 8 additions & 3 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ via_ir = true
sizes = true
optimizer = true
optimizer_runs = 1000
solc_version = "0.8.20"
solc_version = "0.8.23"
ffi = true

[fuzz]
Expand All @@ -29,9 +29,11 @@ polygon = "${ETH_NODE_URI_POLYGON}"
fork = "${ETH_NODE_URI_FORK}"
avalanche = "${ETH_NODE_URI_AVALANCHE}"
celo = "${ETH_NODE_URI_CELO}"
polygonzkevm = "${ETH_NODE_URI_POLYGONZKEVM}"
polygonzkevm = "${ETH_NODE_URI_POLYGON_ZKEVM}"
bsc = "${ETH_NODE_URI_BSC}"
base = "${ETH_NODE_URI_BASE}"
linea = "${ETH_NODE_URI_LINEA}"


[etherscan]
arbitrum = { key = "${ARBITRUM_ETHERSCAN_API_KEY}" }
Expand All @@ -41,8 +43,11 @@ optimism = { key = "${OPTIMISM_ETHERSCAN_API_KEY}" }
polygon = { key = "${POLYGON_ETHERSCAN_API_KEY}" }
avalanche = { key = "${AVALANCHE_ETHERSCAN_API_KEY}" }
celo = { key = "${CELO_ETHERSCAN_API_KEY}", url = "https://api.celoscan.io/api" }
polygonzkevm = { key = "${POLYGONZKEVM_ETHERSCAN_API_KEY}", url = "https://api-zkevm.polygonscan.com/api" }
polygon-zkevm = { key = "${POLYGONZKEVM_ETHERSCAN_API_KEY}", url = "https://api-zkevm.polygonscan.com/api" }
bsc = { key = "${BSC_ETHERSCAN_API_KEY}"}
base = { key = "${BASE_ETHERSCAN_API_KEY}", url = "https://api.basescan.org/api" }
linea = { key = "${LINEA_ETHERSCAN_API_KEY}" }


[profile.dev]
optimizer = true
Expand Down
4 changes: 4 additions & 0 deletions helpers/fork.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ function option_to_uri {
"10")
echo $ETH_NODE_URI_OPTIMISM
;;
"11")
echo $ETH_NODE_URI_LINEA
;;
*)
;;
esac
Expand All @@ -57,6 +60,7 @@ function main {
echo "- 8: Celo"
echo "- 9: Polygon ZkEvm"
echo "- 10: Optimism"
echo "- 11: Linea"

read option

Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
"coverage": "FOUNDRY_PROFILE=dev forge coverage --report lcov && yarn lcov:clean && yarn lcov:generate-html",
"compile": "forge build",
"compile:dev": "FOUNDRY_PROFILE=dev forge build",
"deploy": "forge script --skip test --broadcast --verify --slow -vvvv --rpc-url polygon scripts/interaction/TimelockExecute.s.sol",
"deploy:test": "FOUNDRY_PROFILE=dev forge script --skip test --broadcast --verify --slow -vvvv --rpc-url gnosis scripts/DeployOnChainGovernance.s.sol",
"deploy:fork": "FOUNDRY_PROFILE=dev forge script --skip test --slow --fork-url fork --broadcast scripts/interaction/TimelockExecute.s.sol -vvvv",
"deploy": "forge script --skip test --broadcast --verify --slow -vvvv --rpc-url linea scripts/DeploySideChainGovernance.s.sol",
"deploy:fork": "forge script --skip test --slow --fork-url fork --broadcast scripts/DeploySideChainGovernance.s.sol -vvvv",
"gas": "yarn test --gas-report",
"fork": "bash helpers/fork.sh",
"run": "docker run -it --rm -v $(pwd):/app -w /app ghcr.io/foundry-rs/foundry sh",
Expand All @@ -27,8 +26,10 @@
"lint": "yarn lint:check --fix",
"lint:check": "solhint --max-warnings 20 \"**/*.sol\"",
"verify": "forge verify-contract --chain-id 100 --watch --constructor-args $(cast abi-encode 'constructor(address,address,uint48,uint32,uint256,uint48,uint256,uint256,uint256)' '0xD622c71aba9060F393FEC67D3e2B9335292bf23B' '0x769A713bF0589d495008e5a7c78fABafb9C35F39' 300 3600 100000000000000000000000 60 20 75 60) 0x882dD02d7F2F06B7e968ECb97B1B62Bf51B3af4a AngleGovernor",
"verify:governor": "forge verify-contract --chain-id 100 --watch --constructor-args 0xbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997dd2b8b2d874e19a344cba53b9fb534ea748ef117ed4b75c67569a79486454193000000000000000000000000d622c71aba9060f393fec67d3e2b9335292bf23b000000000000000000000000769a713bf0589d495008e5a7c78fabafb9c35f39000000000000000000000000000000000000000000000000000000000000012c0000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000152d02c7e14af6800000000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000003c 0x882dD02d7F2F06B7e968ECb97B1B62Bf51B3af4a AngleGovernor",
"verify:sender": "forge verify-contract --chain-id 100 --watch --constructor-args $(cast abi-encode 'constructor(address)' '0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4') 0xdE8e46cc73d9D1C94f9b99cE518Cf69A7a7615A3 ProposalSender"
"verify:governor": "forge verify-contract --chain-id 1 --watch --show-standard-json-input > etherscan.json --solc-input --optimizer-runs=1000 --constructor-args 0x0000000000000000000000000c462dbb9ec8cd1630f1728b2cfd2769d09f0dd500000000000000000000000027000546a968aac25e9a709c098f1254e333b1930000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000152d02c7e14af68000000000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000001c20 0xcaAa0114CB9Fe229643B8193375b21f695e6593C AngleGovernor",
"verify:sender": "forge verify-contract --chain-id 1 --watch --constructor-args $(cast abi-encode 'constructor(address)' '0x66a71dcef29a0ffbdbe3c6a460a3b5bc225cd675') 0x71D670A690eF3E0dbD819F63168ce58EE5587f49 ProposalSender",
"verify:timelock": "forge verify-contract --chain-id 59144 --watch --constructor-args $(cast abi-encode 'constructor(uint256,address[],address[],address)' 86400 [] ['0x007475b60d88b02663d6f975927b70bb4335e4b3'] '0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185') 0xd23B51d6F2cB3eC7ca9599D4332a2F10C3CFDF85 TimelockControllerWithCounter",
"verify:receiver": "forge verify-contract --chain-id 59144 --watch --constructor-args $(cast abi-encode 'constructor(address)' '0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7') 0x4A44f77978Daa3E92Eb3D97210bd11645cF935Ab ProposalReceiver"
},
"keywords": [],
"author": "Angle Core Team",
Expand Down
61 changes: 37 additions & 24 deletions scripts/Constants.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,50 @@ pragma solidity ^0.8.9;
import { ILayerZeroEndpoint } from "lz/lzApp/interfaces/ILayerZeroEndpoint.sol";
import { IVotes } from "oz/governance/extensions/GovernorVotes.sol";

/*
enum ContractType {
Timelock,
ProposalSender,
Governor,
ProposalReceiver,
TreasuryAgEUR,
StEUR,
TransmuterAgEUR,
CoreBorrow,
GovernorMultisig,
GuardianMultisig,
ProxyAdmin,
Angle,
veANGLE,
SmartWalletWhitelist,
veBoostProxy,
GaugeController,
AngleDistributor,
AngleMiddleman,
FeeDistributor
}

uint256 constant timelockDelay = 1 days;
uint48 constant initialVotingDelay = 1 days;
uint256 constant initialVotingDelayBlocks = 1 days / 12;
uint32 constant initialVotingPeriod = 4 days;
uint256 constant initialProposalThreshold = 100_000e18;
uint48 constant initialVoteExtension = 3 hours;
*/

uint256 constant timelockDelayTest = 300;
uint48 constant initialVotingDelayTest = 300;
uint256 constant initialVotingDelayBlocksTest = 60;
uint32 constant initialVotingPeriodTest = 3600;
uint256 constant initialProposalThresholdTest = 100_000e18;
uint48 constant initialVoteExtensionTest = 60;

// TODO: update so we deploy with small values and later increase back up
uint256 constant initialQuorumNumerator = 20;
uint256 constant initialShortCircuitNumerator = 75;
// TODO: increase quorum numbers back up
uint256 constant initialQuorumNumerator = 5;
uint256 constant initialShortCircuitNumerator = 10;
bytes constant nullBytes = hex"";

address constant SAFE_MAINNET = 0xdC4e6DFe07EFCa50a197DF15D9200883eF4Eb1c8;
// This is the guardian for testing purposes
address constant SAFE_GNOSIS = 0xf0A31faec2B4fC6396c65B1aF1F6A71E653f11F0;
address constant SAFE_POLYGON = 0x3b9D32D0822A6351F415BeaB05251c1457FF6f8D;

uint256 constant CHAIN_GNOSIS = 100;
uint256 constant CHAIN_POLYGON = 137;
uint256 constant CHAIN_ETHEREUM = 1;
uint256 constant CHAIN_ARBITRUM = 42161;
uint256 constant CHAIN_AVALANCHE = 43114;
uint256 constant CHAIN_OPTIMISM = 10;

// TODO update when deployed
// address constant proposalSender = address(0x499C86959a330Eb860FdFFf6e87896d4298a4F4E);
address constant proposalReceiverPolygon = address(0x060246eD061999F7e128Fd8355d84467d6726b71);
address constant timelockPolygon = address(0x0d17B69fF7D30F7EC13A9447d1E5624b601a730b);
uint256 constant CHAIN_POLYGON = 137;
uint256 constant CHAIN_GNOSIS = 100;
uint256 constant CHAIN_BNB = 56;
uint256 constant CHAIN_CELO = 42220;
uint256 constant CHAIN_ZKEVMPOLYGON = 1101;
uint256 constant CHAIN_BASE = 8453;
uint256 constant CHAIN_LINEA = 59144;
uint256 constant CHAIN_MANTLE = 5000;
uint256 constant CHAIN_AURORA = 1313161554;
40 changes: 12 additions & 28 deletions scripts/DeployOnChainGovernance.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,51 +36,35 @@ contract DeployOnChainGovernance is Utils {

function run() external {
// TODO can be modified to deploy on any chain
uint256 srcChainId = CHAIN_GNOSIS;
address safeMultiSig = SAFE_GNOSIS;
uint256 srcChainId = CHAIN_ETHEREUM;
// END

uint256 deployerPrivateKey = vm.deriveKey(vm.envString("MNEMONIC_GNOSIS"), "m/44'/60'/0'/0/", 0);
uint256 deployerPrivateKey = vm.deriveKey(vm.envString("MNEMONIC_MAINNET"), "m/44'/60'/0'/0/", 0);
vm.startBroadcast(deployerPrivateKey);
address deployer = vm.addr(deployerPrivateKey);
vm.label(deployer, "Deployer");

/*
// If not already - deploy the voting tokens
vyperDeployer = new VyperDeployer();
vm.allowCheatcodes(address(vyperDeployer));
(address _mockANGLE, , ) = deployMockANGLE();
ANGLE = ERC20(_mockANGLE);
(address _mockVeANGLE, , ) = deployVeANGLE(vyperDeployer, _mockANGLE, safeMultiSig);
veANGLE = IveANGLE(_mockVeANGLE);
// Deploy Governance source chain
address safeMultiSig = _chainToContract(srcChainId, ContractType.GuardianMultisig);
veANGLE = IveANGLE(_chainToContract(srcChainId, ContractType.veANGLE));
token = new VeANGLEVotingDelegation(address(veANGLE), "veANGLE Delegation", "1");
*/
token = VeANGLEVotingDelegation(0xD622c71aba9060F393FEC67D3e2B9335292bf23B);

address[] memory proposers = new address[](2);
address[] memory proposers = new address[](0);
address[] memory executors = new address[](1);
executors[0] = address(0); // Means everyone can execute
proposers[0] = 0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185;
proposers[1] = 0x9d159aEb0b2482D09666A5479A2e426Cb8B5D091;
timelock = new TimelockControllerWithCounter(timelockDelayTest, proposers, executors, address(deployer));
executors[0] = safeMultiSig; // Means everyone can execute
timelock = new TimelockControllerWithCounter(timelockDelay, proposers, executors, address(deployer));
angleGovernor = new AngleGovernor(
token,
address(timelock),
initialVotingDelayTest,
initialVotingPeriodTest,
initialProposalThresholdTest,
initialVoteExtensionTest,
initialVotingDelay,
initialVotingPeriod,
initialProposalThreshold,
initialVoteExtension,
initialQuorumNumerator,
initialShortCircuitNumerator,
initialVotingDelayBlocksTest
initialVotingDelayBlocks
);
timelock.grantRole(timelock.PROPOSER_ROLE(), address(angleGovernor));
timelock.grantRole(timelock.CANCELLER_ROLE(), safeMultiSig);
timelock.grantRole(timelock.CANCELLER_ROLE(), 0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185);
timelock.grantRole(timelock.CANCELLER_ROLE(), 0x9d159aEb0b2482D09666A5479A2e426Cb8B5D091);
timelock.renounceRole(timelock.DEFAULT_ADMIN_ROLE(), address(deployer));
proposalSenderDeployed = new ProposalSender(lzEndPoint(srcChainId));
proposalSenderDeployed.transferOwnership(address(angleGovernor));
Expand Down
21 changes: 11 additions & 10 deletions scripts/DeploySideChainGovernance.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,26 @@ contract DeploySideChainGovernance is Utils {
vm.label(deployer, "Deployer");

// TODO can be modified to deploy on any chain
uint256 srcChainId = CHAIN_GNOSIS;
uint256 destChainId = CHAIN_POLYGON;
address destSafeMultiSig = SAFE_POLYGON;
uint256 srcChainId = CHAIN_ETHEREUM;
uint256 destChainId = CHAIN_LINEA;
// END

address destSafeMultiSig = _chainToContract(destChainId, ContractType.GuardianMultisig);
ProposalSender proposalSender = ProposalSender(_chainToContract(srcChainId, ContractType.ProposalSender));
// Deploy relayer receiver and Timelock on end chain
address[] memory proposers = new address[](2);
address[] memory proposers = new address[](0);
address[] memory executors = new address[](1);
executors[0] = address(0); // Means everyone can execute
proposers[0] = 0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185;
proposers[1] = 0x9d159aEb0b2482D09666A5479A2e426Cb8B5D091;
executors[0] = destSafeMultiSig; // Means everyone can execute

timelock = new TimelockControllerWithCounter(timelockDelayTest, proposers, executors, deployer);
proposalReceiver = new ProposalReceiver(address(lzEndPoint(destChainId)));
// timelock = new TimelockControllerWithCounter(timelockDelay, proposers, executors, deployer);
// proposalReceiver = new ProposalReceiver(address(lzEndPoint(destChainId)));
timelock = TimelockControllerWithCounter(payable(0xd23B51d6F2cB3eC7ca9599D4332a2F10C3CFDF85));
proposalReceiver = ProposalReceiver(payable(0x4A44f77978Daa3E92Eb3D97210bd11645cF935Ab));
timelock.grantRole(timelock.PROPOSER_ROLE(), address(proposalReceiver));
timelock.grantRole(timelock.CANCELLER_ROLE(), destSafeMultiSig);
timelock.renounceRole(timelock.DEFAULT_ADMIN_ROLE(), deployer);

proposalReceiver.setTrustedRemoteAddress(getLZChainId(srcChainId), abi.encodePacked(proposalSender()));
proposalReceiver.setTrustedRemoteAddress(getLZChainId(srcChainId), abi.encodePacked(proposalSender));
proposalReceiver.transferOwnership(address(timelock));

vm.stopBroadcast();
Expand Down
89 changes: 40 additions & 49 deletions scripts/Utils.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,70 +21,61 @@ contract Utils is Script {
return address(new TransparentUpgradeableProxy(implementation, PROXY_ADMIN, data));
}

function timelock(uint256 chainId) public returns (TimelockControllerWithCounter) {
string[] memory cmd = new string[](4);
cmd[0] = "node";
cmd[1] = "utils/contractAddress.js";
cmd[2] = vm.toString(chainId);
cmd[3] = "timelock";

bytes memory res = vm.ffi(cmd);
if (res.length == 0) revert("Chain not supported");
return TimelockControllerWithCounter(payable(address(bytes20(res))));
}
function lzEndPoint(uint256 chainId) public returns (ILayerZeroEndpoint) {
// TODO temporary check if LZ updated their sdk
if (chainId == CHAIN_GNOSIS) {
return ILayerZeroEndpoint(0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4);
} else if (chainId == CHAIN_ZKEVMPOLYGON) {
return ILayerZeroEndpoint(0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4);
} else if (chainId == CHAIN_BASE) {
return ILayerZeroEndpoint(0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7);
} else if (chainId == CHAIN_CELO) {
return ILayerZeroEndpoint(0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9);
} else if (chainId == CHAIN_LINEA) {
return ILayerZeroEndpoint(0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7);
}

function proposalReceiver(uint256 chainId) public returns (ProposalReceiver) {
string[] memory cmd = new string[](4);
string[] memory cmd = new string[](3);
cmd[0] = "node";
cmd[1] = "utils/contractAddress.js";
cmd[1] = "utils/layerZeroEndpoint.js";
cmd[2] = vm.toString(chainId);
cmd[3] = "proposalReceiver";

bytes memory res = vm.ffi(cmd);
if (res.length == 0) revert("Chain not supported");
return ProposalReceiver(payable(address(bytes20(res))));
}

/// TODO Replace with prod chain
function proposalSender() public returns (ProposalSender) {
string[] memory cmd = new string[](4);
cmd[0] = "node";
cmd[1] = "utils/contractAddress.js";
cmd[2] = vm.toString(CHAIN_GNOSIS);
cmd[3] = "proposalSender";

bytes memory res = vm.ffi(cmd);
if (res.length == 0) revert("Chain not supported");
return ProposalSender(payable(address(bytes20(res))));
return ILayerZeroEndpoint(address(bytes20(res)));
}

/// TODO Replace with prod chain
function governor() public returns (AngleGovernor) {
function _chainToContract(uint256 chainId, ContractType name) internal returns (address) {
string[] memory cmd = new string[](4);
cmd[0] = "node";
cmd[1] = "utils/contractAddress.js";
cmd[2] = vm.toString(CHAIN_GNOSIS);
cmd[3] = "governor";

bytes memory res = vm.ffi(cmd);
if (res.length == 0) revert("Chain not supported");
return AngleGovernor(payable(address(bytes20(res))));
}

function lzEndPoint(uint256 chainId) public returns (ILayerZeroEndpoint) {
// TODO temporary check if LZ updated their sdk
if (chainId == CHAIN_GNOSIS) {
return ILayerZeroEndpoint(0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4);
}

string[] memory cmd = new string[](3);
cmd[0] = "node";
cmd[1] = "utils/layerZeroEndpoint.js";
cmd[2] = vm.toString(chainId);

if (name == ContractType.Timelock) cmd[3] = "timelock";
else if (name == ContractType.ProposalReceiver) cmd[3] = "proposalReceiver";
else if (name == ContractType.ProposalSender) cmd[3] = "proposalSender";
else if (name == ContractType.Governor) cmd[3] = "governor";
else if (name == ContractType.GuardianMultisig) cmd[3] = "guardian";
else if (name == ContractType.TreasuryAgEUR) cmd[3] = "treasury";
else if (name == ContractType.StEUR) cmd[3] = "stEUR";
else if (name == ContractType.TransmuterAgEUR) cmd[3] = "transmuterAgEUR";
else if (name == ContractType.CoreBorrow) cmd[3] = "coreBorrow";
else if (name == ContractType.GovernorMultisig) cmd[3] = "governorMultisig";
else if (name == ContractType.ProxyAdmin) cmd[3] = "proxyAdmin";
else if (name == ContractType.Angle) cmd[3] = "angle";
else if (name == ContractType.veANGLE) cmd[3] = "veANGLE";
else if (name == ContractType.SmartWalletWhitelist) cmd[3] = "smartWalletWhitelist";
else if (name == ContractType.veBoostProxy) cmd[3] = "veBoostProxy";
else if (name == ContractType.GaugeController) cmd[3] = "gaugeController";
else if (name == ContractType.AngleDistributor) cmd[3] = "angleDistributor";
else if (name == ContractType.AngleMiddleman) cmd[3] = "angleMiddleman";
else if (name == ContractType.FeeDistributor) cmd[3] = "feeDistributor";
else revert("contract not supported");

bytes memory res = vm.ffi(cmd);
// When process exit code is 1, it will return an empty bytes "0x"
if (res.length == 0) revert("Chain not supported");
return ILayerZeroEndpoint(address(bytes20(res)));
return address(bytes20(res));
}

function stringToUint(string memory s) public pure returns (uint) {
Expand Down
Loading

0 comments on commit 1d5f908

Please sign in to comment.