-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3ed27c3
commit e5dd3d8
Showing
9 changed files
with
380 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.23; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
|
||
import {DeployInput} from "script/DeployInput.sol"; | ||
import {GovernorBravoDelegate} from "script/interfaces/GovernorBravoInterfaces.sol"; | ||
|
||
// 1. Get Uniswap governor | ||
// 2. Pick suitable proposer | ||
// 3. Switch v3 factory owner | ||
// 4. Then enable fee amount and set protocol fee for a specific pool | ||
contract Propose is Script, DeployInput { | ||
// TODO: Make a more specific interface | ||
GovernorBravoDelegate constant GOVERNOR = | ||
GovernorBravoDelegate(0x408ED6354d4973f66138C91495F2f2FCbd8724C3); // Mainnet governor | ||
address PROPOSER = 0xe7925D190aea9279400cD9a005E33CEB9389Cc2b; // TODO: jessewldn | ||
|
||
function propose(address _v3FactoryOwner) internal returns (uint256 _proposalId) { | ||
address[] memory _targets = new address[](4); | ||
uint256[] memory _values = new uint256[](4); | ||
string[] memory _signatures = new string[](4); | ||
bytes[] memory _calldatas = new bytes[](4); | ||
|
||
_targets[0] = UNISWAP_V3_FACTORY_ADDRESS; | ||
_values[0] = 0; | ||
_signatures[0] = "setOwner(address)"; | ||
_calldatas[0] = abi.encode(address(_v3FactoryOwner)); | ||
|
||
// Set fees for the couple pools | ||
// dai-usdc | ||
// dai-weth | ||
// wbtc-weth | ||
_targets[1] = _v3FactoryOwner; | ||
_values[1] = 0; | ||
_signatures[1] = "setFeeProtocol(address,uint8,uint8)"; | ||
// TODO: placeholder fees | ||
// wbtc-weth 0.3% | ||
_calldatas[1] = abi.encode(WBTC_WETH_3000_POOL, uint8(10), uint8(10)); | ||
|
||
_targets[2] = _v3FactoryOwner; | ||
_values[2] = 0; | ||
_signatures[2] = "setFeeProtocol(address,uint8,uint8)"; | ||
// TODO: placeholder fees | ||
// dai-weth 0.3% | ||
_calldatas[2] = abi.encode(DAI_WETH_3000_POOL, 10, 10); | ||
|
||
_targets[3] = _v3FactoryOwner; | ||
_values[3] = 0; | ||
_signatures[3] = "setFeeProtocol(address,uint8,uint8)"; | ||
// TODO: placeholder fees | ||
// dai-usdc 0.01% | ||
_calldatas[3] = abi.encode(DAI_USDC_100_POOL, 10, 10); | ||
|
||
return GOVERNOR.propose( | ||
_targets, | ||
_values, | ||
_signatures, | ||
_calldatas, | ||
"Change Uniswap V3 factory owner and set pool protocol fees" | ||
); | ||
} | ||
|
||
/// @dev After the new Governor is deployed on mainnet, this can move from a parameter to a const | ||
function run(address v3FactoryOwner) public returns (uint256 _proposalId) { | ||
// The expectation is the key loaded here corresponds to the address of the `proposer` above. | ||
// When running as a script, broadcast will fail if the key is not correct. | ||
uint256 _proposerKey = vm.envOr( | ||
"PROPOSER_PRIVATE_KEY", | ||
uint256(0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d) | ||
); | ||
vm.rememberKey(_proposerKey); | ||
|
||
vm.startBroadcast(PROPOSER); | ||
_proposalId = propose(v3FactoryOwner); | ||
vm.stopBroadcast(); | ||
return _proposalId; | ||
} | ||
} |
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,115 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.23; | ||
|
||
// Constracts were taken from | ||
// https://etherscan.io/address/0x53a328f4086d7c0f1fa19e594c9b842125263026#code#F2#L182 | ||
// Taken from the address | ||
|
||
interface GovernorBravoDelegate { | ||
type ProposalState is uint8; | ||
|
||
struct Receipt { | ||
bool hasVoted; | ||
uint8 support; | ||
uint96 votes; | ||
} | ||
|
||
event NewAdmin(address oldAdmin, address newAdmin); | ||
event NewImplementation(address oldImplementation, address newImplementation); | ||
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); | ||
event ProposalCanceled(uint256 id); | ||
event ProposalCreated( | ||
uint256 id, | ||
address proposer, | ||
address[] targets, | ||
uint256[] values, | ||
string[] signatures, | ||
bytes[] calldatas, | ||
uint256 startBlock, | ||
uint256 endBlock, | ||
string description | ||
); | ||
event ProposalExecuted(uint256 id); | ||
event ProposalQueued(uint256 id, uint256 eta); | ||
event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold); | ||
event VoteCast( | ||
address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason | ||
); | ||
event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay); | ||
event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod); | ||
|
||
function BALLOT_TYPEHASH() external view returns (bytes32); | ||
function DOMAIN_TYPEHASH() external view returns (bytes32); | ||
function MAX_PROPOSAL_THRESHOLD() external view returns (uint256); | ||
function MAX_VOTING_DELAY() external view returns (uint256); | ||
function MAX_VOTING_PERIOD() external view returns (uint256); | ||
function MIN_PROPOSAL_THRESHOLD() external view returns (uint256); | ||
function MIN_VOTING_DELAY() external view returns (uint256); | ||
function MIN_VOTING_PERIOD() external view returns (uint256); | ||
function _acceptAdmin() external; | ||
function _initiate(uint256 proposalCount) external; | ||
function _setPendingAdmin(address newPendingAdmin) external; | ||
function _setProposalThreshold(uint256 newProposalThreshold) external; | ||
function _setVotingDelay(uint256 newVotingDelay) external; | ||
function _setVotingPeriod(uint256 newVotingPeriod) external; | ||
function admin() external view returns (address); | ||
function cancel(uint256 proposalId) external; | ||
function castVote(uint256 proposalId, uint8 support) external; | ||
function castVoteBySig(uint256 proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) external; | ||
function castVoteWithReason(uint256 proposalId, uint8 support, string memory reason) external; | ||
function execute(uint256 proposalId) external payable; | ||
function getActions(uint256 proposalId) | ||
external | ||
view | ||
returns ( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
string[] memory signatures, | ||
bytes[] memory calldatas | ||
); | ||
function getReceipt(uint256 proposalId, address voter) external view returns (Receipt memory); | ||
function implementation() external view returns (address); | ||
function initialProposalId() external view returns (uint256); | ||
function initialize( | ||
address timelock_, | ||
address uni_, | ||
uint256 votingPeriod_, | ||
uint256 votingDelay_, | ||
uint256 proposalThreshold_ | ||
) external; | ||
function latestProposalIds(address) external view returns (uint256); | ||
function name() external view returns (string memory); | ||
function pendingAdmin() external view returns (address); | ||
function proposalCount() external view returns (uint256); | ||
function proposalMaxOperations() external view returns (uint256); | ||
function proposalThreshold() external view returns (uint256); | ||
function proposals(uint256) | ||
external | ||
view | ||
returns ( | ||
uint256 id, | ||
address proposer, | ||
uint256 eta, | ||
uint256 startBlock, | ||
uint256 endBlock, | ||
uint256 forVotes, | ||
uint256 againstVotes, | ||
uint256 abstainVotes, | ||
bool canceled, | ||
bool executed | ||
); | ||
function propose( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
string[] memory signatures, | ||
bytes[] memory calldatas, | ||
string memory description | ||
) external returns (uint256); | ||
function queue(uint256 proposalId) external; | ||
function quorumVotes() external view returns (uint256); | ||
function state(uint256 proposalId) external view returns (ProposalState); | ||
function timelock() external view returns (address); | ||
function uni() external view returns (address); | ||
function votingDelay() external view returns (uint256); | ||
function votingPeriod() external view returns (uint256); | ||
} |
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,6 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.23; | ||
|
||
contract Constants { | ||
address constant UNISWAP_GOVERNOR_ADDRESS = 0x408ED6354d4973f66138C91495F2f2FCbd8724C3; | ||
} |
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,120 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.23; | ||
|
||
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; | ||
import {IGovernor} from "@openzeppelin/contracts/governance/IGovernor.sol"; | ||
import {Test} from "forge-std/Test.sol"; | ||
|
||
import {Deploy} from "script/Deploy.s.sol"; | ||
import {DeployInput} from "script/DeployInput.sol"; | ||
import {Propose} from "script/Propose.s.sol"; | ||
import {Constants} from "test/helpers/Constants.sol"; | ||
import {GovernorBravoDelegate} from "script/interfaces/GovernorBravoInterfaces.sol"; | ||
import {V3FactoryOwner} from "src/V3FactoryOwner.sol"; | ||
import {UniStaker} from "src/UniStaker.sol"; | ||
|
||
// 1. help vote on proposal and move it forward | ||
abstract contract ProposalTest is Test, DeployInput, Constants { | ||
//----------------- State and Setup ----------- // | ||
uint256 uniswapProposalId; | ||
address[] delegates; | ||
UniStaker uniStaker; | ||
V3FactoryOwner v3FactoryOwner; | ||
GovernorBravoDelegate governor = GovernorBravoDelegate(UNISWAP_GOVERNOR_ADDRESS); | ||
|
||
function setUp() public virtual { | ||
//initialProposalCount = governor.proposalCount(); | ||
|
||
uint256 _forkBlock = 17_927_962; | ||
vm.createSelectFork(vm.rpcUrl("mainnet"), _forkBlock); | ||
|
||
address[] memory _delegates = new address[](6); | ||
// Taken from https://www.tally.xyz/gov/pooltogether/delegates?sort=voting_power_desc. | ||
// If you update these delegates (including updating order in the array), | ||
// make sure to update any tests that reference specific delegates. The last delegate is the | ||
// proposer and lower in the voting power than the above link. | ||
_delegates[0] = 0x76f54Eeb0D33a2A2c5CCb72FE12542A56f35d67C; | ||
_delegates[1] = 0x8E4ED221fa034245F14205f781E0b13C5bd6a42E; | ||
_delegates[2] = 0xe7925D190aea9279400cD9a005E33CEB9389Cc2b; | ||
_delegates[3] = 0x1d8F369F05343F5A642a78BD65fF0da136016452; | ||
_delegates[4] = 0xe02457a1459b6C49469Bf658d4Fe345C636326bF; | ||
_delegates[5] = 0x8962285fAac45a7CBc75380c484523Bb7c32d429; | ||
for (uint256 i; i < _delegates.length; i++) { | ||
address _delegate = _delegates[i]; | ||
delegates.push(_delegate); | ||
} | ||
|
||
Propose _proposeScript = new Propose(); | ||
// We override the deployer to use an alternate delegate, because in this context, | ||
// lonser.eth already has a live proposal | ||
//_proposeScript.overrideProposerForTests(0xFFb032E27b70DfAD518753BAAa77040F64df9840); | ||
// | ||
// Pass in deployed factory owner | ||
Deploy _deployScript = new Deploy(); | ||
_deployScript.setUp(); | ||
(v3FactoryOwner, uniStaker) = _deployScript.run(); | ||
uniswapProposalId = _proposeScript.run(address(v3FactoryOwner)); | ||
} | ||
//--------------- HELPERS ---------------// | ||
|
||
function _uniswapProposalStartBlock() internal view returns (uint256) { | ||
(,,, uint256 _startBlock,,,,,,) = governor.proposals(uniswapProposalId); | ||
return _startBlock; | ||
} | ||
|
||
function _uniswapProposalEndBlock() internal view returns (uint256) { | ||
(,,,, uint256 _endBlock,,,,,) = governor.proposals(uniswapProposalId); | ||
return _endBlock; | ||
} | ||
|
||
function _uniswapProposalEta() internal view returns (uint256) { | ||
(,, uint256 _eta,,,,,,,) = governor.proposals(uniswapProposalId); | ||
return _eta; | ||
} | ||
|
||
function _jumpToActiveUniswapProposal() internal { | ||
vm.roll(_uniswapProposalStartBlock() + 1); | ||
} | ||
|
||
function _jumpToUniswapVoteComplete() internal { | ||
vm.roll(_uniswapProposalEndBlock() + 1); | ||
} | ||
|
||
function _jumpPastProposalEta() internal { | ||
vm.roll(block.number + 1); // move up one block so we're not in the same block as when queued | ||
vm.warp(_uniswapProposalEta() + 1); // jump past the eta timestamp | ||
} | ||
|
||
function _delegatesVoteOnUniswapProposal(bool _support) internal { | ||
for (uint256 _index = 0; _index < delegates.length; _index++) { | ||
vm.prank(delegates[_index]); | ||
governor.castVote(uniswapProposalId, 1); | ||
} | ||
} | ||
|
||
function _passUniswapProposal() internal { | ||
_jumpToActiveUniswapProposal(); | ||
_delegatesVoteOnUniswapProposal(true); | ||
_jumpToUniswapVoteComplete(); | ||
} | ||
|
||
function _defeatUniswapProposal() internal { | ||
_jumpToActiveUniswapProposal(); | ||
_delegatesVoteOnUniswapProposal(false); | ||
_jumpToUniswapVoteComplete(); | ||
} | ||
|
||
function _passAndQueueUniswapProposal() internal { | ||
_passUniswapProposal(); | ||
governor.queue(uniswapProposalId); | ||
} | ||
|
||
function _executeProposal() internal { | ||
_jumpPastProposalEta(); | ||
governor.execute(uniswapProposalId); | ||
} | ||
|
||
function assertEq(IGovernor.ProposalState _actual, IGovernor.ProposalState _expected) internal { | ||
assertEq(uint8(_actual), uint8(_expected)); | ||
} | ||
} |
Oops, something went wrong.