Merge pull request #5 from Instadapp/timelock-v2

Timelock and Governor contract changes
This commit is contained in:
Thrilok kumar 2024-02-24 09:01:31 -05:00 committed by GitHub
commit cb99f3ddb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 7240 additions and 4741 deletions

View File

@ -11,7 +11,7 @@ import { SafeMath } from "./SafeMath.sol";
contract InstaGovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorBravoEvents {
/// @notice The name of this contract
string public constant name = "DSL Governor Bravo";
string public constant name = "INST Governor Bravo";
/// @notice The minimum setable proposal threshold
uint public constant MIN_PROPOSAL_THRESHOLD = 500000e18; // 500,000
@ -20,22 +20,22 @@ contract InstaGovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorB
uint public constant MAX_PROPOSAL_THRESHOLD = 50000000e18; // 5,000,000
/// @notice The minimum setable voting period
uint public constant MIN_VOTING_PERIOD = 5760; // About 24 hours
uint public constant MIN_VOTING_PERIOD = 7200; // About 24 hours, 12s per block
/// @notice The max setable voting period
uint public constant MAX_VOTING_PERIOD = 80640; // About 2 weeks
uint public constant MAX_VOTING_PERIOD = 100800; // About 2 weeks, 12s per block
/// @notice The min setable voting delay
uint public constant MIN_VOTING_DELAY = 1;
/// @notice The max setable voting delay
uint public constant MAX_VOTING_DELAY = 40320; // About 1 week
uint public constant MAX_VOTING_DELAY = 50400; // About 1 week, 12s per block
/// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed
uint public constant quorumVotes = 4000000e18; // 4,000,000
/// @notice The maximum number of actions that can be included in a proposal
uint public constant proposalMaxOperations = 10; // 10 actions
uint public constant proposalMaxOperations = 30; // 30 actions
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
@ -359,6 +359,9 @@ contract InstaGovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorB
// Store admin with value pendingAdmin
admin = pendingAdmin;
// Store timelock with value pendingAdmin
emit NewTimelock(address(timelock), pendingAdmin);
timelock = TimelockInterface(pendingAdmin);
// Clear the pending value
pendingAdmin = address(0);
@ -367,6 +370,15 @@ contract InstaGovernorBravoDelegate is GovernorBravoDelegateStorageV1, GovernorB
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
}
/**
* @notice Accepts transfer of admin rights on timelock contract. msg.sender must be admin of this contract
* @dev Admin function for pending admin to accept role and update admin on timelock contract
*/
function _acceptAdminOnTimelock() external {
require(msg.sender == admin, "GovernorBravo:_acceptAdminOnTimelock: pending admin only");
timelock.acceptAdmin();
}
function getChainIdInternal() internal pure returns (uint) {
uint chainId;

View File

@ -63,6 +63,9 @@ contract GovernorBravoEvents {
/// @notice Emitted when pendingAdmin is accepted, which means admin is updated
event NewAdmin(address oldAdmin, address newAdmin);
/// @notice Emitted when pendingAdmin is accepted, which means timelock is updated
event NewTimelock(address oldTimelock, address newTimelock);
}
contract GovernorBravoDelegatorStorage {

View File

@ -8,27 +8,27 @@ contract InstaTimelock {
event NewAdmin(address indexed newAdmin);
event NewPendingAdmin(address indexed newPendingAdmin);
event NewDelay(uint indexed newDelay);
event NewGuardian(address indexed newGuardian);
event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);
event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);
event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);
uint public constant GRACE_PERIOD = 14 days;
uint public constant MINIMUM_DELAY = 2 days;
uint public constant MINIMUM_DELAY = 1 hours;
uint public constant MAXIMUM_DELAY = 30 days;
address public admin;
address public pendingAdmin;
address public guardian;
uint public delay;
mapping (bytes32 => bool) public queuedTransactions;
constructor(address admin_, uint delay_) {
require(delay_ >= MINIMUM_DELAY, "Timelock::constructor: Delay must exceed minimum delay.");
require(delay_ <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay.");
constructor(address admin_, address guardian_) {
admin = admin_;
delay = delay_;
delay = 0; // delay set to "0"
guardian = guardian_;
}
fallback() external payable { }
@ -42,6 +42,13 @@ contract InstaTimelock {
emit NewDelay(delay);
}
function setGuardian(address guardian_) public {
require(msg.sender == address(this), "Timelock::setGuardian: Call must come from Timelock.");
guardian = guardian_;
emit NewGuardian(guardian_);
}
function acceptAdmin() public {
require(msg.sender == pendingAdmin, "Timelock::acceptAdmin: Call must come from pendingAdmin.");
admin = msg.sender;
@ -59,7 +66,7 @@ contract InstaTimelock {
function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {
require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin.");
require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay.");
require(delay == 0 || eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay.");
bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
queuedTransactions[txHash] = true;
@ -69,7 +76,7 @@ contract InstaTimelock {
}
function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {
require(msg.sender == admin, "Timelock::cancelTransaction: Call must come from admin.");
require(msg.sender == admin || msg.sender == guardian, "Timelock::cancelTransaction: Call must come from admin or guardian.");
bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
queuedTransactions[txHash] = false;
@ -104,6 +111,23 @@ contract InstaTimelock {
return returnData;
}
function executePayload(address target, string memory signature, bytes memory data) public returns (bytes memory) {
require(msg.sender == address(this), "Timelock::executePayload: Call must come from Timelock.");
bytes memory callData;
if (bytes(signature).length == 0) {
callData = data;
} else {
callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);
}
// solium-disable-next-line security/no-call-value
(bool success, bytes memory returnData) = target.delegatecall(callData);
require(success, "Timelock::executePayload: Transaction execution reverted.");
return returnData;
}
function getBlockTimestamp() internal view returns (uint) {
// solium-disable-next-line security/no-block-members
return block.timestamp;

View File

@ -0,0 +1,337 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
interface IGovernorBravo {
function _acceptAdmin() external;
function _setVotingDelay(uint newVotingDelay) external;
function _setVotingPeriod(uint newVotingPeriod) external;
function _acceptAdminOnTimelock() external;
function _setImplementation(address implementation_) external;
function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) external returns (uint);
function admin() external view returns(address);
function pendingAdmin() external view returns(address);
function timelock() external view returns(address);
function votingDelay() external view returns(uint256);
function votingPeriod() external view returns(uint256);
}
interface ITimelock {
function acceptAdmin() external;
function setDelay(uint delay_) external;
function setPendingAdmin(address pendingAdmin_) external;
function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external returns (bytes32);
function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external payable returns (bytes memory);
function pendingAdmin() external view returns(address);
function admin() external view returns(address);
function delay() external view returns(uint256);
}
interface IInstaIndex {
function changeMaster(address _newMaster) external;
function updateMaster() external;
function master() external view returns(address);
}
interface ILite {
function setAdmin(address newAdmin) external;
function getAdmin() external view returns(address);
}
interface IDSAV2 {
function cast(
string[] memory _targetNames,
bytes[] memory _datas,
address _origin
)
external
payable
returns (bytes32);
function isAuth(address user) external view returns (bool);
}
contract PayloadIGP7 {
uint256 public constant PROPOSAL_ID = 7;
address public constant PROPOSER = 0xA45f7bD6A5Ff45D31aaCE6bCD3d426D9328cea01;
IGovernorBravo public constant GOVERNOR = IGovernorBravo(0x0204Cd037B2ec03605CFdFe482D8e257C765fA1B);
ITimelock public constant OLD_TIMELOCK = ITimelock(0xC7Cb1dE2721BFC0E0DA1b9D526bCdC54eF1C0eFC);
ITimelock public immutable TIMELOCK;
address public immutable ADDRESS_THIS;
IInstaIndex public constant INSTAINDEX = IInstaIndex(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723);
ILite public constant LITE = ILite(0xA0D3707c569ff8C87FA923d3823eC5D81c98Be78);
IDSAV2 public constant TREASURY = IDSAV2(0x28849D2b63fA8D361e5fc15cB8aBB13019884d09);
uint256 public constant ONE_DAY_TIME_IN_SECONDS = 1 days; // 1 day in seconds. 86400s
uint256 public constant ONE_DAY_TIME_IN_BLOCKS = 7_200; // 1 day in blocks. 12s per block
uint256 public constant TWO_DAY_TIME_IN_BLOCKS = 14_400; // 2 day in blocks. 12s per block
address public immutable GOVERNOR_IMPLEMENTATION_ADDRESS;
address public constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;
constructor (address governor_, address timelock_) {
TIMELOCK = ITimelock(address(timelock_));
GOVERNOR_IMPLEMENTATION_ADDRESS = address(governor_);
ADDRESS_THIS = address(this);
}
function propose(string memory description) external {
require(msg.sender == PROPOSER, "msg.sender-not-proposer");
uint256 totalActions = 8;
address[] memory targets = new address[](totalActions);
uint256[] memory values = new uint256[](totalActions);
string[] memory signatures = new string[](totalActions);
bytes[] memory calldatas = new bytes[](totalActions);
// Action 1: call cast() - transfer rewards to Team Multisig, add new Timelock as auth & remove old Timelock as auth on Treasury
(targets[0], values[0], signatures[0], calldatas[0]) = action1();
// Action 2: call _setImplementation() - upgrade governor contract to new implementation
(targets[1], values[1], signatures[1], calldatas[1]) = action2();
// Action 3: call changeMaster() - change ownership of DSA to new timelock contract
(targets[2], values[2], signatures[2], calldatas[2]) = action3();
// Action 4: call setAdmin() - change ownership of Lite to new timelock contract
(targets[3], values[3], signatures[3], calldatas[3]) = action4();
// Action 5: call _setPendingAdmin() - on governor contract with new timelock address
(targets[4], values[4], signatures[4], calldatas[4]) = action5();
// Action 6: call setPendingAdmin() - on old timelock to change team multisig
(targets[5], values[5], signatures[5], calldatas[5]) = action6();
// Action 7: call queueTransaction - new timelock contract to queue below payload
(targets[6], values[6], signatures[6], calldatas[6]) = action7();
// Action 8: call executeTransaction - new timelock contract to execute below payload
(targets[7], values[7], signatures[7], calldatas[7]) = action8();
uint256 proposedId = GOVERNOR.propose(
targets,
values,
signatures,
calldatas,
description
);
require(proposedId == PROPOSAL_ID, "PROPOSAL_IS_NOT_SAME");
}
function execute() external {
// Action 1: updateMaster() function on DSA instaIndex
INSTAINDEX.updateMaster();
// Action 2: _acceptAdmin() function on governor contract
GOVERNOR._acceptAdmin();
// Action 3: _setVotingDelay() function on governor contract with 1 days
GOVERNOR._setVotingDelay(ONE_DAY_TIME_IN_BLOCKS);
// Action 4: _setVotingPeriod() function on governor contract with 2 days
GOVERNOR._setVotingPeriod(TWO_DAY_TIME_IN_BLOCKS);
// Action 5: setPendingAdmin() on new timelock contract
TIMELOCK.setPendingAdmin(address(GOVERNOR));
// Action 6: _acceptAdminOnTimelock() on governor contract
GOVERNOR._acceptAdminOnTimelock();
// Action 7: setDelay() on new timelock contract with 1 day
TIMELOCK.setDelay(ONE_DAY_TIME_IN_SECONDS);
// Action 8: call verifyProposal() - on this payload contract to verify proposal execution
PayloadIGP7(ADDRESS_THIS).verifyProposal();
}
function verifyProposal() external view {
// Verify 1 : Verify DSA Master
require(INSTAINDEX.master() == address(TIMELOCK), "InstaIndex-wrong-master");
// Verify 2 : Verify Lite Admin
require(LITE.getAdmin() == address(TIMELOCK), "Lite-wrong-admin");
// Verify 3 : Verify Governor Admin
require(GOVERNOR.admin() == address(TIMELOCK), "Governor-wrong-admin");
// Verify 4 : Verify Governor Timelock
require(GOVERNOR.timelock() == address(TIMELOCK), "Governor-wrong-timelock");
// Verify 5 : Verify Governor Pending Admin
require(GOVERNOR.pendingAdmin() == address(0), "Governor-wrong-pending-admin");
// Verify 6 : Verify Old Timelock Admin
require(OLD_TIMELOCK.admin() == address(GOVERNOR), "Old-timelock-wrong-admin");
// Verify 7 : Verify Old Timelock Pending Admin
require(OLD_TIMELOCK.pendingAdmin() == address(TEAM_MULTISIG), "Old-timelock-wrong-pending-admin");
// Verify 8 : Verify New Timelock Admin
require(TIMELOCK.admin() == address(GOVERNOR), "Timelock-wrong-admin");
// Verify 9 : Verify Timelock Pending Admin
require(TIMELOCK.pendingAdmin() == address(0), "Timelock-wrong-pending-admin");
// Verify 10 : Verify Treasury remove of old timelock
require(TREASURY.isAuth(address(OLD_TIMELOCK)) == false, "Treasury-old-timelock-not-removed");
// Verify 11: Verify Treasury add of new timelock
require(TREASURY.isAuth(address(TIMELOCK)) == true, "Treasury-new-timelock-not-added");
// Verify 12: Verify voting delay
require(GOVERNOR.votingDelay() == ONE_DAY_TIME_IN_BLOCKS, "Voting-delay-not-set-to-one-day");
// Verify 13: Verify voting period
require(GOVERNOR.votingPeriod() == TWO_DAY_TIME_IN_BLOCKS, "Voting-period-not-set-to-two-day");
// Verify 14: Verify queueing period
require(TIMELOCK.delay() == ONE_DAY_TIME_IN_SECONDS, "Timelock-delay-not-set-to-one-day");
}
///////// PROPOSAL ACTIONS - 8 Actions ///////
/// @notice Action 1: call cast() - transfer rewards to Team Multisig, add new Timelock as auth & remove old Timelock as auth on Treasury
function action1() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
string[] memory targets = new string[](7);
bytes[] memory encodedSpells = new bytes[](7);
string memory withdrawSignature = "withdraw(address,uint256,address,uint256,uint256)";
// Spell 1: Transfer wETH
{
address ETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
uint256 ETH_AMOUNT = 230 * 1e18; // 230 ETH
targets[0] = "BASIC-A";
encodedSpells[0] = abi.encodeWithSignature(withdrawSignature, ETH_ADDRESS, ETH_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 2: Transfer USDC
{
address USDC_ADDRESS = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
uint256 USDC_AMOUNT = 247_900 * 1e6; // 247.9k USDC
targets[1] = "BASIC-A";
encodedSpells[1] = abi.encodeWithSignature(withdrawSignature, USDC_ADDRESS, USDC_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 3: Transfer DAI
{
address DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
uint256 DAI_AMOUNT = 59_000 * 1e18; // 59k DAI
targets[2] = "BASIC-A";
encodedSpells[2] = abi.encodeWithSignature(withdrawSignature, DAI_ADDRESS, DAI_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 4: Transfer USDT
{
address USDT_ADDRESS = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
uint256 USDT_AMOUNT = 28_700 * 1e6; // 28.8k USDT
targets[3] = "BASIC-A";
encodedSpells[3] = abi.encodeWithSignature(withdrawSignature, USDT_ADDRESS, USDT_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 5: Transfer stETH
{
address STETH_ADDRESS = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;
uint256 STETH_AMOUNT = 320 * 1e18; // 320 stETH
targets[4] = "BASIC-A";
encodedSpells[4] = abi.encodeWithSignature(withdrawSignature, STETH_ADDRESS, STETH_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 6: Add new Timelock as auth
{
targets[5] = "AUTHORITY-A";
encodedSpells[5] = abi.encodeWithSignature("add(address)", address(TIMELOCK));
}
// Spell 7: Remove old Timelock as auth
{
targets[6] = "AUTHORITY-A";
encodedSpells[6] = abi.encodeWithSignature("remove(address)", address(OLD_TIMELOCK));
}
target = address(TREASURY);
value = 0;
signature = "cast(string[],bytes[],address)";
calldatas = abi.encode(targets, encodedSpells, address(this));
}
/// @notice Action 2: call _setImplementation() - upgrade governor contract to new implementation
function action2() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(GOVERNOR);
value = 0;
signature = "_setImplementation(address)";
calldatas = abi.encode(GOVERNOR_IMPLEMENTATION_ADDRESS);
}
/// @notice Action 3: call changeMaster() - change ownership of DSA to new timelock contract
function action3() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(INSTAINDEX);
value = 0;
signature = "changeMaster(address)";
calldatas = abi.encode(TIMELOCK);
}
/// @notice Action 4: call setAdmin() - change ownership of Lite to new timelock contract
function action4() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(LITE);
value = 0;
signature = "setAdmin(address)";
calldatas = abi.encode(TIMELOCK);
}
/// @notice Action 5: call _setPendingAdmin() - on governor contract with new timelock address
function action5() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(GOVERNOR);
value = 0;
signature = "_setPendingAdmin(address)";
calldatas = abi.encode(TIMELOCK);
}
/// @notice Action 6: call setPendingAdmin() - on old timelock to change team multisig
function action6() public pure returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(OLD_TIMELOCK);
value = 0;
signature = "setPendingAdmin(address)";
calldatas = abi.encode(TEAM_MULTISIG);
}
/// @notice Action 7: call queueTransaction - new timelock contract to queue below payload
function action7() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(TIMELOCK);
value = 0;
signature = "queueTransaction(address,uint256,string,bytes,uint256)";
calldatas = abi.encode(
TIMELOCK,
0,
"executePayload(address,string,bytes)",
abi.encode(
address(this),
"execute()",
abi.encode()
),
block.timestamp
);
}
/// @notice Action 8: call executeTransaction - new timelock contract to execute below payload
function action8() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(TIMELOCK);
value = 0;
signature = "executeTransaction(address,uint256,string,bytes,uint256)";
calldatas = abi.encode(
TIMELOCK,
0,
"executePayload(address,string,bytes)",
abi.encode(
address(this),
"execute()",
abi.encode()
),
block.timestamp
);
}
}

View File

@ -0,0 +1,226 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
interface IGovernorBravo {
function _acceptAdmin() external;
function _setVotingDelay(uint newVotingDelay) external;
function _setVotingPeriod(uint newVotingPeriod) external;
function _acceptAdminOnTimelock() external;
function _setImplementation(address implementation_) external;
function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) external returns (uint);
function admin() external view returns(address);
function pendingAdmin() external view returns(address);
function timelock() external view returns(address);
function votingDelay() external view returns(uint256);
function votingPeriod() external view returns(uint256);
}
interface ITimelock {
function acceptAdmin() external;
function setDelay(uint delay_) external;
function setPendingAdmin(address pendingAdmin_) external;
function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external returns (bytes32);
function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external payable returns (bytes memory);
function pendingAdmin() external view returns(address);
function admin() external view returns(address);
function delay() external view returns(uint256);
}
interface IInstaIndex {
function changeMaster(address _newMaster) external;
function updateMaster() external;
function master() external view returns(address);
}
interface ILite {
function setAdmin(address newAdmin) external;
function getAdmin() external view returns(address);
function updateSecondaryAuth(address secondaryAuth_) external;
}
interface IDSAV2 {
function cast(
string[] memory _targetNames,
bytes[] memory _datas,
address _origin
)
external
payable
returns (bytes32);
function isAuth(address user) external view returns (bool);
}
contract PayloadIGP8Mock {
uint256 public constant PROPOSAL_ID = 8;
IGovernorBravo public constant GOVERNOR = IGovernorBravo(0x0204Cd037B2ec03605CFdFe482D8e257C765fA1B);
IDSAV2 public constant TREASURY = IDSAV2(0x28849D2b63fA8D361e5fc15cB8aBB13019884d09);
IInstaIndex public constant INSTAINDEX = IInstaIndex(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723);
ILite public constant LITE = ILite(0xA0D3707c569ff8C87FA923d3823eC5D81c98Be78);
ITimelock public constant OLD_TIMELOCK = ITimelock(0xC7Cb1dE2721BFC0E0DA1b9D526bCdC54eF1C0eFC);
address public immutable ADDRESS_THIS;
ITimelock public immutable TIMELOCK;
address public immutable GOVERNOR_IMPLEMENTATION_ADDRESS;
address public constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;
uint256 public constant ONE_DAY_TIME_IN_SECONDS = 1 days; // 1 day in seconds. 86400s
uint256 public constant ONE_DAY_TIME_IN_BLOCKS = 7_200; // 1 day in blocks. 12s per block
uint256 public constant TWO_DAY_TIME_IN_BLOCKS = 14_400; // 2 day in blocks. 12s per block
constructor (address governor_, address timelock_) {
TIMELOCK = ITimelock(address(timelock_));
GOVERNOR_IMPLEMENTATION_ADDRESS = address(governor_);
ADDRESS_THIS = address(this);
}
function propose(string memory description) external {
uint256 totalActions = 3;
address[] memory targets = new address[](totalActions);
uint256[] memory values = new uint256[](totalActions);
string[] memory signatures = new string[](totalActions);
bytes[] memory calldatas = new bytes[](totalActions);
(targets[0], values[0], signatures[0], calldatas[0]) = action1();
(targets[1], values[1], signatures[1], calldatas[1]) = action2();
(targets[2], values[2], signatures[2], calldatas[2]) = action3();
uint256 proposedId = GOVERNOR.propose(
targets,
values,
signatures,
calldatas,
description
);
require(proposedId == PROPOSAL_ID, "PROPOSAL_IS_NOT_SAME");
}
function execute() external {
LITE.updateSecondaryAuth(msg.sender);
}
function verifyProposal() external view {
// Verify 1 : Verify DSA Master
require(INSTAINDEX.master() == address(TIMELOCK), "InstaIndex-wrong-master");
// Verify 2 : Verify Lite Admin
require(LITE.getAdmin() == address(TIMELOCK), "Lite-wrong-admin");
// Verify 3 : Verify Governor Admin
require(GOVERNOR.admin() == address(TIMELOCK), "Governor-wrong-admin");
// Verify 4 : Verify Governor Timelock
require(GOVERNOR.timelock() == address(TIMELOCK), "Governor-wrong-timelock");
// Verify 5 : Verify Governor Pending Admin
require(GOVERNOR.pendingAdmin() == address(0), "Governor-wrong-timelock");
// Verify 6 : Verify Old Timelock Admin
require(OLD_TIMELOCK.admin() == address(GOVERNOR), "Old-timelock-wrong-admin");
// Verify 7 : Verify Old Timelock Pending Admin
require(OLD_TIMELOCK.pendingAdmin() == address(TEAM_MULTISIG), "Old-timelock-wrong-pending-admin");
// Verify 8 : Verify New Timelock Admin
require(TIMELOCK.admin() == address(GOVERNOR), "Timelock-wrong-admin");
// Verify 9 : Verify Timelock Pending Admin
require(TIMELOCK.pendingAdmin() == address(0), "Old-timelock-wrong-pending-admin");
// Verify 10 : Verify Treasury remove of old timelock
require(TREASURY.isAuth(address(OLD_TIMELOCK)) == false, "Treasury-old-timelock-not-removed");
// Verify 11: Verify Treasury add of new timelock
require(TREASURY.isAuth(address(TIMELOCK)) == true, "Treasury-new-timelock-not-added");
// Verify 12: Verify voting delay
require(GOVERNOR.votingDelay() == ONE_DAY_TIME_IN_BLOCKS, "Voting-delay-not-set-to-one-day");
// Verify 13: Verify voting period
require(GOVERNOR.votingPeriod() == TWO_DAY_TIME_IN_BLOCKS, "Voting-period-not-set-to-two-day");
// Verify 14: Verify queueing period
require(TIMELOCK.delay() == ONE_DAY_TIME_IN_SECONDS, "Timelock-delay-not-set-to-one-day");
}
///////// PROPOSAL ACTIONS - 8 Actions ///////
/// @notice Action 1: call cast() - transfer rewards to Team Multisig, add new Timelock as auth & remove old Timelock as auth on Treasury
function action1() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
string[] memory targets = new string[](5);
bytes[] memory encodedSpells = new bytes[](5);
string memory withdrawSignature = "withdraw(address,uint256,address,uint256,uint256)";
// Spell 1: Transfer wETH
{
address ETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
uint256 ETH_AMOUNT = 1;
targets[0] = "BASIC-A";
encodedSpells[0] = abi.encodeWithSignature(withdrawSignature, ETH_ADDRESS, ETH_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 2: Transfer USDC
{
address USDC_ADDRESS = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
uint256 USDC_AMOUNT = 100;
targets[1] = "BASIC-A";
encodedSpells[1] = abi.encodeWithSignature(withdrawSignature, USDC_ADDRESS, USDC_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 3: Transfer DAI
{
address DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
uint256 DAI_AMOUNT = 100;
targets[2] = "BASIC-A";
encodedSpells[2] = abi.encodeWithSignature(withdrawSignature, DAI_ADDRESS, DAI_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 4: Transfer USDT
{
address USDT_ADDRESS = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
uint256 USDT_AMOUNT = 100;
targets[3] = "BASIC-A";
encodedSpells[3] = abi.encodeWithSignature(withdrawSignature, USDT_ADDRESS, USDT_AMOUNT, TEAM_MULTISIG, 0, 0);
}
// Spell 5: Transfer stETH
{
address STETH_ADDRESS = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;
uint256 STETH_AMOUNT = 1;
targets[4] = "BASIC-A";
encodedSpells[4] = abi.encodeWithSignature(withdrawSignature, STETH_ADDRESS, STETH_AMOUNT, TEAM_MULTISIG, 0, 0);
}
target = address(TREASURY);
value = 0;
signature = "cast(string[],bytes[],address)";
calldatas = abi.encode(targets, encodedSpells, address(this));
}
function action2() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(TIMELOCK);
value = 0;
signature = "executePayload(address,string,bytes)";
calldatas = abi.encode(
address(this),
"execute()",
abi.encode()
);
}
function action3() public view returns(address target, uint256 value, string memory signature, bytes memory calldatas) {
target = address(this);
value = 0;
signature = "verifyProposal()";
calldatas = abi.encode();
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -26,15 +26,14 @@ module.exports = {
networks: {
hardhat: {
forking: {
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
url: `https://1rpc.io/eth`,
blockNumber: 12308027,
},
blockGasLimit: 12000000,
},
kovan: {
url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_ID}`,
accounts: [`0x${PRIVATE_KEY}`],
gas: 12500000,
mainnet: {
url: `https://1rpc.io/eth`,
accounts: !PRIVATE_KEY ? [] : [ `0x${PRIVATE_KEY}`],
},
},
etherscan: {

11245
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "dsl-governance",
"name": "inst-governance",
"version": "1.0.0",
"description": "",
"main": "index.js",
@ -20,6 +20,7 @@
},
"dependencies": {
"@nomiclabs/hardhat-etherscan": "^2.1.1",
"@tenderly/hardhat-tenderly": "^2.2.1",
"dotenv": "^8.2.0",
"rlp": "^2.2.6"
}

48
scripts/deployIGP7.js Normal file
View File

@ -0,0 +1,48 @@
const hre = require("hardhat");
const { ethers } = hre;
async function main() {
const oldTimelockAddress = "0xC7Cb1dE2721BFC0E0DA1b9D526bCdC54eF1C0eFC"
const guardain = "0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e"
// const Timelock = await ethers.getContractFactory("InstaTimelock")
const timelock = await ethers.getContractAt("InstaTimelock", "0x2386dc45added673317ef068992f19421b481f4c")
// const timelock = await Timelock.deploy(oldTimelockAddress, guardain)
// await timelock.deployed()
// const GovernorDelegate = await ethers.getContractFactory("InstaGovernorBravoDelegate")
const governorDelegate = await ethers.getContractAt("InstaGovernorBravoDelegate", "0x00613f7e762124711c7647f9eab5c8a88632ee47")
// const governorDelegate = await GovernorDelegate.deploy()
// await governorDelegate.deployed()
const PayloadIGP7 = await ethers.getContractFactory("PayloadIGP7")
const payloadIGP7 = await PayloadIGP7.deploy(governorDelegate.address, timelock.address)
await payloadIGP7.deployed()
console.log("PayloadIGP7: ", payloadIGP7.address)
console.log("InstaTimelock: ", timelock.address)
console.log("InstaGovernorBravoDelegate: ", governorDelegate.address)
await hre.run("verify:verify", {
address: timelock.address,
constructorArguments: [oldTimelockAddress, guardain]
})
await hre.run("verify:verify", {
address: governorDelegate.address,
constructorArguments: []
})
await hre.run("verify:verify", {
address: payloadIGP7.address,
constructorArguments: [governorDelegate.address, timelock.address]
})
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

View File

@ -0,0 +1,46 @@
const hre = require("hardhat");
const { ethers } = hre;
async function main() {
const oldTimelockAddress = "0xC7Cb1dE2721BFC0E0DA1b9D526bCdC54eF1C0eFC"
const guardain = "0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e"
const governorDelegate = await ethers.deployContract("InstaGovernorBravoDelegate")
await governorDelegate.waitForDeployment()
console.log(governorDelegate)
const timelock = await ethers.deployContract("InstaTimelock", [oldTimelockAddress, guardain])
await timelock.waitForDeployment()
const payload = await ethers.deployContract("PayloadIGP7", [governorDelegate.target, timelock.target])
await payload.waitForDeployment()
const payload2 = await ethers.deployContract("PayloadIGP8Mock", [governorDelegate.target, timelock.target])
await payload2.waitForDeployment()
console.log("InstaTimelock: ", timelock.target)
console.log("InstaGovernorBravoDelegate: ", governorDelegate.target)
console.log("PayloadIGP7: ", payload.target)
console.log("PayloadIGP8Mock: ", payload2.target)
console.log()
await hre.run("verify:verify", {
address: governorDelegate.target,
constructorArguments: []
})
await hre.run("verify:verify", {
address: timelock.target,
constructorArguments: [oldTimelockAddress, guardain]
})
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});