-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add proposal to add Guardian to Timelock (#2021)
* Add proposal to add Guardian to Timelock * Update comment * Update deployment and add test script * Remove deployment file * Do a full proposal test * Add one more test * Create proposal * Prettify * Revert forceSkip on buyback
- Loading branch information
1 parent
bbbd918
commit 1d37d30
Showing
6 changed files
with
185 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[{"inputs": [{"internalType": "address[]","name": "proposers","type": "address[]"},{"internalType": "address[]","name": "executors","type": "address[]"}],"stateMutability": "nonpayable","type": "constructor","name": "constructor"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "id","type": "bytes32"},{"indexed": true,"internalType": "uint256","name": "index","type": "uint256"},{"indexed": false,"internalType": "address","name": "target","type": "address"},{"indexed": false,"internalType": "uint256","name": "value","type": "uint256"},{"indexed": false,"internalType": "bytes","name": "data","type": "bytes"}],"name": "CallExecuted","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "id","type": "bytes32"},{"indexed": true,"internalType": "uint256","name": "index","type": "uint256"},{"indexed": false,"internalType": "address","name": "target","type": "address"},{"indexed": false,"internalType": "uint256","name": "value","type": "uint256"},{"indexed": false,"internalType": "bytes","name": "data","type": "bytes"},{"indexed": false,"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"indexed": false,"internalType": "uint256","name": "delay","type": "uint256"}],"name": "CallScheduled","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "Cancelled","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "oldDuration","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "newDuration","type": "uint256"}],"name": "MinDelayChange","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "role","type": "bytes32"},{"indexed": true,"internalType": "bytes32","name": "previousAdminRole","type": "bytes32"},{"indexed": true,"internalType": "bytes32","name": "newAdminRole","type": "bytes32"}],"name": "RoleAdminChanged","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "role","type": "bytes32"},{"indexed": true,"internalType": "address","name": "account","type": "address"},{"indexed": true,"internalType": "address","name": "sender","type": "address"}],"name": "RoleGranted","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "role","type": "bytes32"},{"indexed": true,"internalType": "address","name": "account","type": "address"},{"indexed": true,"internalType": "address","name": "sender","type": "address"}],"name": "RoleRevoked","type": "event"},{"inputs": [],"name": "CANCELLER_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "DEFAULT_ADMIN_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "EXECUTOR_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "PROPOSER_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TIMELOCK_ADMIN_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "cancel","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "target","type": "address"},{"internalType": "uint256","name": "value","type": "uint256"},{"internalType": "bytes","name": "data","type": "bytes"},{"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"internalType": "bytes32","name": "salt","type": "bytes32"}],"name": "execute","outputs": [],"stateMutability": "payable","type": "function"},{"inputs": [{"internalType": "address[]","name": "targets","type": "address[]"},{"internalType": "uint256[]","name": "values","type": "uint256[]"},{"internalType": "bytes[]","name": "payloads","type": "bytes[]"},{"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"internalType": "bytes32","name": "salt","type": "bytes32"}],"name": "executeBatch","outputs": [],"stateMutability": "payable","type": "function"},{"inputs": [],"name": "getMinDelay","outputs": [{"internalType": "uint256","name": "duration","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32"}],"name": "getRoleAdmin","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "getTimestamp","outputs": [{"internalType": "uint256","name": "timestamp","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32"},{"internalType": "address","name": "account","type": "address"}],"name": "grantRole","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32"},{"internalType": "address","name": "account","type": "address"}],"name": "hasRole","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "target","type": "address"},{"internalType": "uint256","name": "value","type": "uint256"},{"internalType": "bytes","name": "data","type": "bytes"},{"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"internalType": "bytes32","name": "salt","type": "bytes32"}],"name": "hashOperation","outputs": [{"internalType": "bytes32","name": "hash","type": "bytes32"}],"stateMutability": "pure","type": "function"},{"inputs": [{"internalType": "address[]","name": "targets","type": "address[]"},{"internalType": "uint256[]","name": "values","type": "uint256[]"},{"internalType": "bytes[]","name": "payloads","type": "bytes[]"},{"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"internalType": "bytes32","name": "salt","type": "bytes32"}],"name": "hashOperationBatch","outputs": [{"internalType": "bytes32","name": "hash","type": "bytes32"}],"stateMutability": "pure","type": "function"},{"inputs": [{"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "isOperation","outputs": [{"internalType": "bool","name": "pending","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "isOperationDone","outputs": [{"internalType": "bool","name": "done","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "isOperationPending","outputs": [{"internalType": "bool","name": "pending","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32","name": "id","type": "bytes32"}],"name": "isOperationReady","outputs": [{"internalType": "bool","name": "ready","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "","type": "address"},{"internalType": "address","name": "","type": "address"},{"internalType": "uint256[]","name": "","type": "uint256[]"},{"internalType": "uint256[]","name": "","type": "uint256[]"},{"internalType": "bytes","name": "","type": "bytes"}],"name": "onERC1155BatchReceived","outputs": [{"internalType": "bytes4","name": "","type": "bytes4"}],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "","type": "address"},{"internalType": "address","name": "","type": "address"},{"internalType": "uint256","name": "","type": "uint256"},{"internalType": "uint256","name": "","type": "uint256"},{"internalType": "bytes","name": "","type": "bytes"}],"name": "onERC1155Received","outputs": [{"internalType": "bytes4","name": "","type": "bytes4"}],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "","type": "address"},{"internalType": "address","name": "","type": "address"},{"internalType": "uint256","name": "","type": "uint256"},{"internalType": "bytes","name": "","type": "bytes"}],"name": "onERC721Received","outputs": [{"internalType": "bytes4","name": "","type": "bytes4"}],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32"},{"internalType": "address","name": "account","type": "address"}],"name": "renounceRole","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32"},{"internalType": "address","name": "account","type": "address"}],"name": "revokeRole","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "target","type": "address"},{"internalType": "uint256","name": "value","type": "uint256"},{"internalType": "bytes","name": "data","type": "bytes"},{"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"internalType": "bytes32","name": "salt","type": "bytes32"},{"internalType": "uint256","name": "delay","type": "uint256"}],"name": "schedule","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "targets","type": "address[]"},{"internalType": "uint256[]","name": "values","type": "uint256[]"},{"internalType": "bytes[]","name": "payloads","type": "bytes[]"},{"internalType": "bytes32","name": "predecessor","type": "bytes32"},{"internalType": "bytes32","name": "salt","type": "bytes32"},{"internalType": "uint256","name": "delay","type": "uint256"}],"name": "scheduleBatch","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "bytes4","name": "interfaceId","type": "bytes4"}],"name": "supportsInterface","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "newDelay","type": "uint256"}],"name": "updateDelay","outputs": [],"stateMutability": "nonpayable","type": "function"},{"stateMutability": "payable","type": "receive"}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from world import * | ||
from brownie import chain | ||
|
||
def main(): | ||
with TemporaryFork(): | ||
calldata = vault_oeth_admin.setRedeemFeeBps.encode_input(0) | ||
|
||
print("Creating a test proposal on Timelock...") | ||
# Check if multisig can create proposals on Timelock | ||
tx = timelock_contract.schedule( | ||
OETH_VAULT, # Target | ||
0, # Value | ||
calldata, | ||
"", | ||
"", | ||
24 * 60 * 60, # delay | ||
{'from': GOV_MULTISIG} | ||
) | ||
tx.info() | ||
|
||
print("Waiting until it's ready for execution...") | ||
# Fast forward to execute | ||
chain.sleep(24 * 60 * 60 + 10) | ||
|
||
print("Executing...") | ||
# Test execution | ||
tx = timelock_contract.execute( | ||
OETH_VAULT, # Target | ||
0, # Value | ||
calldata, | ||
"", | ||
"", | ||
{'from': GOV_MULTISIG} | ||
) | ||
tx.info() | ||
|
||
if vault_oeth_admin.redeemFeeBps() != 0: | ||
raise Exception("Action not updated") | ||
|
||
print("All Good!") | ||
|
||
print("-------------------------------------------") | ||
with TemporaryFork(): | ||
calldata = vault_oeth_admin.setRedeemFeeBps.encode_input(1) | ||
|
||
print("\n\nCreating another test proposal on Timelock...") | ||
tx = timelock_contract.schedule( | ||
OETH_VAULT, # Target | ||
0, # Value | ||
calldata, | ||
"", | ||
"", | ||
24 * 60 * 60, # delay | ||
{'from': GOV_MULTISIG} | ||
) | ||
tx.info() | ||
|
||
action_hash = timelock_contract.hashOperation( | ||
OETH_VAULT, # Target | ||
0, # Value | ||
calldata, | ||
"", | ||
"" | ||
) | ||
|
||
print("Cancelling tx...") | ||
# Make sure the multisig can cancel txs as well | ||
tx = timelock_contract.cancel(action_hash, {'from': GOV_MULTISIG}) | ||
tx.info() | ||
|
||
if timelock_contract.isOperation(action_hash): | ||
raise Exception("Failed to cancel op") | ||
|
||
print("All Good!") | ||
|
||
print("-------------------------------------------") | ||
with TemporaryFork(): | ||
print("\n\nMaking sure that it's possible to grant role...") | ||
calldata = timelock_contract.grantRole.encode_input( | ||
# keccak256("TIMELOCK_ADMIN_ROLE") | ||
"0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", | ||
"0x0000000000000000000000000000000000000011" | ||
) | ||
|
||
print("\n\nCreating another test proposal on Timelock...") | ||
tx = timelock_contract.schedule( | ||
TIMELOCK, # Target | ||
0, # Value | ||
calldata, | ||
"", | ||
"", | ||
24 * 60 * 60, # delay | ||
{'from': GOV_MULTISIG} | ||
) | ||
tx.info() | ||
|
||
print("Waiting until it's ready for execution...") | ||
# Fast forward to execute | ||
chain.sleep(24 * 60 * 60 + 10) | ||
|
||
print("Executing...") | ||
# Test execution | ||
tx = timelock_contract.execute( | ||
TIMELOCK, # Target | ||
0, # Value | ||
calldata, | ||
"", | ||
"", | ||
{'from': GOV_MULTISIG} | ||
) | ||
tx.info() | ||
|
||
if not timelock_contract.hasRole( | ||
"0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", | ||
"0x0000000000000000000000000000000000000011" | ||
): | ||
raise Exception("Failed to grant roles") | ||
|
||
print("All Good!") | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pragma solidity ^0.8.0; | ||
|
||
interface ITimelockController { | ||
function grantRole(bytes32 role, address account) external; | ||
|
||
function revokeRole(bytes32 role, address account) external; | ||
|
||
function renounceRole(bytes32 role, address account) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
const addresses = require("../../utils/addresses"); | ||
const { deploymentWithGovernanceProposal } = require("../../utils/deploy"); | ||
|
||
module.exports = deploymentWithGovernanceProposal( | ||
{ | ||
deployName: "094_add_multisig_to_timelock", | ||
forceDeploy: false, | ||
// forceSkip: true, | ||
// onlyOnFork: true, // this is only executed in forked environment | ||
reduceQueueTime: true, // just to solve the issue of later active proposals failing | ||
proposalId: | ||
"76565349657922140684589379459208028078547529916278436872532296348233972897503", | ||
}, | ||
async ({ ethers }) => { | ||
const PROPOSER_ROLE = | ||
"0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1"; // keccak256("PROPOSER_ROLE"); | ||
const EXECUTOR_ROLE = | ||
"0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63"; // keccak256("EXECUTOR_ROLE"); | ||
const CANCELLER_ROLE = | ||
"0xfd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783"; // keccak256("CANCELLER_ROLE"); | ||
const cTimelock = await ethers.getContractAt( | ||
"ITimelockController", | ||
addresses.mainnet.Timelock | ||
); | ||
|
||
return { | ||
name: "Add Guardian Multisig to Timelock\n\ | ||
\n\ | ||
Part of the OGN/OGV merger. This proposal adds the Origin's 5 of 8 Multisig to the Timelock to provide a backup governance during the transition between governance systems during the token merger. This permission will be revoked once the merger is complete. \ | ||
", | ||
actions: [ | ||
{ | ||
contract: cTimelock, | ||
signature: "grantRole(bytes32,address)", | ||
args: [PROPOSER_ROLE, addresses.mainnet.Guardian], | ||
}, | ||
{ | ||
contract: cTimelock, | ||
signature: "grantRole(bytes32,address)", | ||
args: [EXECUTOR_ROLE, addresses.mainnet.Guardian], | ||
}, | ||
{ | ||
contract: cTimelock, | ||
signature: "grantRole(bytes32,address)", | ||
args: [CANCELLER_ROLE, addresses.mainnet.Guardian], | ||
}, | ||
], | ||
}; | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters