-
Notifications
You must be signed in to change notification settings - Fork 4
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
Do Governance Proposals with Signatures #429
Merged
Merged
Changes from 4 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
b1e68dd
Deployment with Governance proposal
shahthepro 3b16c03
Fix launch date
shahthepro eb4ad03
Split proposal
shahthepro f3dc69a
Full proposal execution flow
shahthepro d9d2e2e
Get rid of hardcoded timestamps
shahthepro 1d1f425
Update readme
shahthepro 1043bff
Tweaks
shahthepro 4bc93ff
Fix rewards fork test
shahthepro 085389c
Round up
shahthepro bb98b61
Fix tests
shahthepro 109ee47
Make proposal desc more detailed
shahthepro 8a3d9e8
Do governance proposals using plain text signatures
DanielVF c3e49c9
Merge branch 'master' into DanielVF/propose-with-sigs
shahthepro 8859c9f
Handle vote casting
shahthepro d2e1045
Fix syntax
shahthepro f7f3374
Prettify
shahthepro 545d2a6
Merge branch 'master' into DanielVF/propose-with-sigs
shahthepro a42ee93
Merge branch 'master' into DanielVF/propose-with-sigs
shahthepro cb731a0
Merge branch 'master' into DanielVF/propose-with-sigs
shahthepro 200a18a
Merge branch 'master' into DanielVF/propose-with-sigs
shahthepro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,178 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity 0.8.10; | ||
|
||
import {Addresses} from "contracts/utils/Addresses.sol"; | ||
import "forge-std/console.sol"; | ||
|
||
import "OpenZeppelin/[email protected]/contracts/utils/Strings.sol"; | ||
import {IGovernor} from "OpenZeppelin/[email protected]/contracts/governance/IGovernor.sol"; | ||
import {Governance} from "../Governance.sol"; | ||
|
||
import "contracts/utils/VmHelper.sol"; | ||
|
||
struct GovAction { | ||
address target; | ||
uint256 value; | ||
string fullsig; | ||
bytes data; | ||
} | ||
|
||
struct GovProposal { | ||
string description; | ||
GovAction[] actions; | ||
} | ||
|
||
library GovProposalHelper { | ||
using VmHelper for Vm; | ||
|
||
function id(GovProposal memory prop) internal view returns (uint256 proposalId) { | ||
bytes32 descriptionHash = keccak256(bytes(prop.description)); | ||
(address[] memory targets, uint256[] memory values, bytes[] memory calldatas) = getParams(prop); | ||
|
||
proposalId = uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash))); | ||
} | ||
|
||
function getParams(GovProposal memory prop) | ||
internal | ||
view | ||
returns (address[] memory targets, uint256[] memory values, bytes[] memory calldatas) | ||
{ | ||
uint256 actionLen = prop.actions.length; | ||
targets = new address[](actionLen); | ||
values = new uint256[](actionLen); | ||
|
||
string[] memory sigs = new string[](actionLen); | ||
bytes[] memory data = new bytes[](actionLen); | ||
|
||
for (uint256 i = 0; i < actionLen; ++i) { | ||
targets[i] = prop.actions[i].target; | ||
sigs[i] = prop.actions[i].fullsig; | ||
data[i] = prop.actions[i].data; | ||
values[i] = prop.actions[i].value; | ||
} | ||
|
||
calldatas = _encodeCalldata(sigs, data); | ||
} | ||
|
||
function _encodeCalldata(string[] memory signatures, bytes[] memory calldatas) | ||
private | ||
pure | ||
returns (bytes[] memory) | ||
{ | ||
bytes[] memory fullcalldatas = new bytes[](calldatas.length); | ||
|
||
for (uint256 i = 0; i < signatures.length; ++i) { | ||
fullcalldatas[i] = bytes(signatures[i]).length == 0 | ||
? calldatas[i] | ||
: abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), calldatas[i]); | ||
} | ||
|
||
return fullcalldatas; | ||
} | ||
|
||
function setDescription(GovProposal storage prop, string memory description) internal { | ||
prop.description = description; | ||
} | ||
|
||
function action(GovProposal storage prop, address target, string memory fullsig, bytes memory data) internal { | ||
prop.actions.push(GovAction({target: target, fullsig: fullsig, data: data, value: 0})); | ||
} | ||
|
||
function getProposeCalldata(GovProposal memory prop) internal view returns (bytes memory proposeCalldata) { | ||
(address[] memory targets, uint256[] memory values, bytes[] memory calldatas) = getParams(prop); | ||
|
||
proposeCalldata = abi.encodeWithSignature( | ||
"propose(address[],uint256[],bytes[],string)", targets, values, calldatas, prop.description | ||
); | ||
} | ||
|
||
function impersonateAndSimulate(GovProposal memory prop) internal { | ||
address VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); | ||
Vm vm = Vm(VM_ADDRESS); | ||
console.log("Impersonating timelock to simulate governance proposal..."); | ||
vm.startPrank(Addresses.TIMELOCK); | ||
for (uint256 i = 0; i < prop.actions.length; i++) { | ||
GovAction memory propAction = prop.actions[i]; | ||
bytes memory sig = abi.encodePacked(bytes4(keccak256(bytes(propAction.fullsig)))); | ||
(bool success, bytes memory data) = propAction.target.call(abi.encodePacked(sig, propAction.data)); | ||
if (!success) { | ||
console.log(propAction.fullsig); | ||
revert("Governance action failed"); | ||
} | ||
} | ||
vm.stopPrank(); | ||
console.log("Governance proposal simulation complete"); | ||
} | ||
|
||
function simulate(GovProposal memory prop, address governanceAddr) internal { | ||
address VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); | ||
Vm vm = Vm(VM_ADDRESS); | ||
|
||
uint256 proposalId = id(prop); | ||
|
||
Governance governance = Governance(payable(governanceAddr)); | ||
|
||
vm.startPrank(Addresses.GOV_MULTISIG); | ||
|
||
uint256 snapshot = governance.proposalSnapshot(proposalId); | ||
|
||
if (snapshot == 0) { | ||
// Proposal doesn't exists, create it | ||
console.log("Creating proposal..."); | ||
bytes memory proposeData = getProposeCalldata(prop); | ||
(bool success, bytes memory data) = governanceAddr.call(proposeData); | ||
} | ||
|
||
IGovernor.ProposalState state = governance.state(proposalId); | ||
|
||
if (state == IGovernor.ProposalState.Executed) { | ||
// Skipping executed proposal | ||
return; | ||
} | ||
|
||
if (state == IGovernor.ProposalState.Pending) { | ||
console.log("Waiting for voting period..."); | ||
// Wait for voting to start | ||
vm.roll(block.number + 10); | ||
vm.warp(block.timestamp + 10 minutes); | ||
|
||
state = governance.state(proposalId); | ||
} | ||
|
||
if (state == IGovernor.ProposalState.Active) { | ||
console.log("Voting on proposal..."); | ||
// Vote on proposal | ||
governance.castVote(proposalId, 1); | ||
// Wait for voting to end | ||
vm.roll(governance.proposalDeadline(proposalId) + 20); | ||
vm.warp(block.timestamp + 2 days); | ||
|
||
state = governance.state(proposalId); | ||
} | ||
|
||
if (state == IGovernor.ProposalState.Succeeded) { | ||
console.log("Queuing proposal..."); | ||
governance.queue(proposalId); | ||
|
||
state = governance.state(proposalId); | ||
} | ||
|
||
if (state == IGovernor.ProposalState.Queued) { | ||
console.log("Executing proposal"); | ||
// Wait for timelock | ||
vm.roll(governance.proposalEta(proposalId) + 20); | ||
vm.warp(block.timestamp + 2 days); | ||
|
||
governance.execute(proposalId); | ||
|
||
state = governance.state(proposalId); | ||
} | ||
|
||
if (state != IGovernor.ProposalState.Executed) { | ||
revert("Unexpected proposal state"); | ||
} | ||
|
||
vm.stopPrank(); | ||
} | ||
} |
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,21 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity 0.8.10; | ||
|
||
import "forge-std/Vm.sol"; | ||
|
||
library VmHelper { | ||
function getVM() internal view returns (Vm vm) { | ||
address VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); | ||
vm = Vm(VM_ADDRESS); | ||
} | ||
|
||
function isForkEnv(Vm vm) public view returns (bool) { | ||
return vm.isContext(VmSafe.ForgeContext.ScriptDryRun) || vm.isContext(VmSafe.ForgeContext.Test) | ||
|| vm.isContext(VmSafe.ForgeContext.TestGroup); | ||
} | ||
|
||
function isTestEnv(Vm vm) public view returns (bool) { | ||
return vm.isContext(VmSafe.ForgeContext.Test) || vm.isContext(VmSafe.ForgeContext.TestGroup); | ||
} | ||
} |
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 |
---|---|---|
|
@@ -5,6 +5,7 @@ remappings = [ | |
"contracts/=./contracts", | ||
"script/=./script", | ||
"tests/=./tests", | ||
"utils/=./contracts/utils", | ||
"OpenZeppelin/openzeppelin-contracts@02fcc75bb7f35376c22def91b0fb9bc7a50b9458/=./lib/openzeppelin-contracts", | ||
"OpenZeppelin/openzeppelin-contracts-upgradeable@a16f26a063cd018c4c986832c3df332a131f53b9/=./lib/openzeppelin-contracts-upgradeable", | ||
"OpenZeppelin/[email protected]/=./lib/openzeppelin-contracts", | ||
|
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,31 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity 0.8.10; | ||
|
||
import "forge-std/Script.sol"; | ||
import {Addresses} from "contracts/utils/Addresses.sol"; | ||
import {IMintableERC20} from "contracts/interfaces/IMintableERC20.sol"; | ||
import {RewardsSource} from "contracts/RewardsSource.sol"; | ||
|
||
contract ExtraOGNForMigration is Script { | ||
uint256 constant OGN_EPOCH = 1717041600; // May 30, 2024 GMT | ||
|
||
// Ref: https://snapshot.org/#/origingov.eth/proposal/0x741893a4d9838c0b69fac03650756e21fe00ec35b5309626bb0d6b816f861f9b | ||
uint256 public constant OGN_MINTED = 409_664_846 ether; | ||
|
||
function run() external { | ||
vm.warp(OGN_EPOCH); | ||
|
||
IMintableERC20 ogv = IMintableERC20(Addresses.OGV); | ||
|
||
uint256 rewards = RewardsSource(Addresses.OGV_REWARDS_PROXY).previewRewards(); | ||
|
||
uint256 ogvSupply = ogv.totalSupply(); | ||
uint256 maxOgnNeeded = ((ogvSupply + rewards) * 0.09137 ether) / 1 ether; | ||
|
||
console.log("OGV Supply", ogvSupply / 1 ether); | ||
console.log("Pending OGV Rewards", rewards / 1 ether); | ||
console.log("Max OGN Needed", maxOgnNeeded / 1 ether); | ||
console.log("OGN from Treasury", (maxOgnNeeded - OGN_MINTED) / 1 ether); | ||
} | ||
} |
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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to add the description for the functions and parameters