-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into DanielVF/n-07-state-visibility
- Loading branch information
Showing
14 changed files
with
452 additions
and
177 deletions.
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
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
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,186 @@ | ||
// 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) { | ||
bytes memory proposeData = getProposeCalldata(prop); | ||
|
||
console.log("----------------------------------"); | ||
console.log("Create following tx on Governance:"); | ||
console.log("To:", governanceAddr); | ||
console.log("Data:"); | ||
console.logBytes(proposeData); | ||
console.log("----------------------------------"); | ||
|
||
// Proposal doesn't exists, create it | ||
console.log("Creating proposal on fork..."); | ||
(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); | ||
} | ||
} |
Oops, something went wrong.