Skip to content

Commit

Permalink
build: init gov (#47)
Browse files Browse the repository at this point in the history
* build: init gov

* test: init gov

* chore: addy

* fix: scripts

* chore: fix scripts
  • Loading branch information
Schlagonia authored Sep 24, 2024
1 parent d732e91 commit 3ab01eb
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 36 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,15 @@ Deployment of periphery contracts such as the [Apr Oracle](https://github.com/ye

This can be done permissionlessly if the most recent contract has not yet been deployed on a chain you would like to use it on.

1. Add your deployers Private key under PRIVATE_KEY in your .env file.
- NOTE: make sure to add `0x` to the beginning of the key.
1. If you have not added a keystore private key to foundry before add your address to use

```shell
$ cast wallet import --interactive <wallet_name>
```

2. Run the deployment script for the contract you want to deploy.
```sh
forge script script/DeployContractName.s.sol:DeployContractName --broadcast --rpc-url YOUR_RPC_URL
forge script script/DeployContractName.s.sol:DeployContractName --broadcast --rpc-url YOUR_RPC_URL --account ACCOUNT_NAME
```
- You can do a dry run before officially deploying by removing the `--broadcast` flag.
- For chains that don't support 1559 tx's you may need to add a `--legacy` flag.
Expand Down
28 changes: 28 additions & 0 deletions script/BaseScript.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import "forge-std/Script.sol";

interface Deployer {
event ContractCreation(address indexed newContract, bytes32 indexed salt);

function deployCreate3(
bytes32 salt,
bytes memory initCode
) external payable returns (address newContract);

function deployCreate2(
bytes32 salt,
bytes memory initCode
) external payable returns (address newContract);
}

// Deploy a contract to a deterministic address with create2
abstract contract BaseScript is Script {

Deployer public deployer = Deployer(0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed);

address public v3Safe = 0x33333333D5eFb92f19a5F94a43456b3cec2797AE;

address public initGov;
}
20 changes: 4 additions & 16 deletions script/DeployAprOracle.s.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import "forge-std/Script.sol";
import "./BaseScript.s.sol";

// Deploy a contract to a deterministic address with create2
contract DeployAprOracle is Script {

Deployer public deployer = Deployer(0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed);
contract DeployAprOracle is BaseScript {

function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
vm.startBroadcast();

// Encode constructor arguments
bytes memory construct = abi.encode(0x33333333D5eFb92f19a5F94a43456b3cec2797AE);
bytes memory construct = abi.encode(v3Safe);

// Get the bytecode
bytes memory bytecode = abi.encodePacked(vm.getCode("AprOracle.sol:AprOracle"), construct);
Expand All @@ -27,13 +24,4 @@ contract DeployAprOracle is Script {

vm.stopBroadcast();
}
}

contract Deployer {
event ContractCreation(address indexed newContract, bytes32 indexed salt);

function deployCreate2(
bytes32 salt,
bytes memory initCode
) public payable returns (address newContract) {}
}
18 changes: 3 additions & 15 deletions script/DeployAuctionFactory.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import "forge-std/Script.sol";
import "./BaseScript.s.sol";

// Deploy a contract to a deterministic address with create2
contract DeployAuctionFactory is Script {

Deployer public deployer = Deployer(0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed);
contract DeployAuctionFactory is BaseScript {

function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
vm.startBroadcast();

// Get the bytecode
bytes memory bytecode = abi.encodePacked(vm.getCode("AuctionFactory.sol:AuctionFactory"));
Expand All @@ -24,13 +21,4 @@ contract DeployAuctionFactory is Script {

vm.stopBroadcast();
}
}

interface Deployer {
event ContractCreation(address indexed newContract, bytes32 indexed salt);

function deployCreate3(
bytes32 salt,
bytes memory initCode
) external payable returns (address newContract);
}
3 changes: 1 addition & 2 deletions script/DeployCommonTrigger.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ contract DeployCommonTrigger is Script {
Deployer public deployer = Deployer(0x8D85e7c9A4e369E53Acc8d5426aE1568198b0112);

function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
vm.startBroadcast();

// Encode constructor arguments
bytes memory construct = abi.encode(0x33333333D5eFb92f19a5F94a43456b3cec2797AE);
Expand Down
24 changes: 24 additions & 0 deletions script/DeployInitGov.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import "./BaseScript.s.sol";

// Deploy a contract to a deterministic address with create2
contract DeployInitGov is BaseScript {

function run() external {
vm.startBroadcast();

// Get the bytecode
bytes memory bytecode = abi.encodePacked(vm.getCode("InitGov.sol:InitGov"));

// Pick an unique salt
bytes32 salt = keccak256("Init Gov");

address contractAddress = deployer.deployCreate2(salt, bytecode);

console.log("Address is ", contractAddress);

vm.stopBroadcast();
}
}
130 changes: 130 additions & 0 deletions src/test/InitGov.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import "forge-std/console.sol";
import {Setup, IStrategy, SafeERC20, ERC20} from "./utils/Setup.sol";

import {AprOracle} from "../AprOracle/AprOracle.sol";
import {InitGov} from "../utils/InitGov.sol";

contract InitGovTest is Setup {
address safe = 0x33333333D5eFb92f19a5F94a43456b3cec2797AE;

address public constant SIGNER_ONE =
0x6d2b80BA79871281Be7F70b079996a052B8D62F4;
address public constant SIGNER_TWO =
0x305af52AC31d3F9Daa1EC6231bA7b36Bb40f42f4;
address public constant SIGNER_THREE =
0xa05c4256ff0dd38697e63D48dF146e6e2FE7fe4A;
address public constant SIGNER_FOUR =
0x623d4A04e19328244924D1dee48252987C02fC0a;
address public constant SIGNER_FIVE =
0x5C166A5919cC07d785837d8Cc1261c67229d271D;
address public constant SIGNER_SIX =
0x80f751EdcB3012d5AF5530AFE97d5dC6EE176Bc0;

InitGov public initGov;

function setUp() public override {
super.setUp();

initGov = new InitGov();

assertTrue(initGov.isSigner(SIGNER_ONE));
assertTrue(initGov.isSigner(SIGNER_TWO));
assertTrue(initGov.isSigner(SIGNER_THREE));
assertTrue(initGov.isSigner(SIGNER_FOUR));
assertTrue(initGov.isSigner(SIGNER_FIVE));
assertTrue(initGov.isSigner(SIGNER_SIX));
}

function test_transferGov_withSafe() public {
AprOracle oracle = new AprOracle(address(initGov));

assertEq(oracle.governance(), address(initGov));

vm.expectRevert("!safe");
initGov.transferGovernance(address(oracle), user);

assertEq(oracle.governance(), address(initGov));

vm.expectRevert("!safe");
vm.prank(SIGNER_ONE);
initGov.transferGovernance(address(oracle), user);

assertEq(oracle.governance(), address(initGov));

vm.prank(safe);
initGov.transferGovernance(address(oracle), user);

assertEq(oracle.governance(), user);
}

function test_transferGov_signers() public {
AprOracle oracle = new AprOracle(address(initGov));

assertEq(oracle.governance(), address(initGov));

bytes32 id = initGov.getTxnId(address(oracle), user);

assertEq(initGov.numberSigned(id), 0);
assertFalse(initGov.signed(SIGNER_ONE, id));
assertFalse(initGov.signed(SIGNER_TWO, id));
assertFalse(initGov.signed(SIGNER_THREE, id));
assertFalse(initGov.signed(SIGNER_FOUR, id));
assertFalse(initGov.signed(SIGNER_FIVE, id));
assertFalse(initGov.signed(SIGNER_SIX, id));

vm.expectRevert("!signer");
initGov.signTxn(address(oracle), user);

vm.prank(SIGNER_ONE);
initGov.signTxn(address(oracle), user);

assertEq(oracle.governance(), address(initGov));
assertEq(initGov.numberSigned(id), 1);
assertTrue(initGov.signed(SIGNER_ONE, id));
assertFalse(initGov.signed(SIGNER_TWO, id));
assertFalse(initGov.signed(SIGNER_THREE, id));
assertFalse(initGov.signed(SIGNER_FOUR, id));
assertFalse(initGov.signed(SIGNER_FIVE, id));
assertFalse(initGov.signed(SIGNER_SIX, id));

vm.expectRevert("already signed");
vm.prank(SIGNER_ONE);
initGov.signTxn(address(oracle), user);

assertEq(oracle.governance(), address(initGov));
assertEq(initGov.numberSigned(id), 1);
assertTrue(initGov.signed(SIGNER_ONE, id));
assertFalse(initGov.signed(SIGNER_TWO, id));
assertFalse(initGov.signed(SIGNER_THREE, id));
assertFalse(initGov.signed(SIGNER_FOUR, id));
assertFalse(initGov.signed(SIGNER_FIVE, id));
assertFalse(initGov.signed(SIGNER_SIX, id));

vm.prank(SIGNER_FOUR);
initGov.signTxn(address(oracle), user);

assertEq(oracle.governance(), address(initGov));
assertEq(initGov.numberSigned(id), 2);
assertTrue(initGov.signed(SIGNER_ONE, id));
assertFalse(initGov.signed(SIGNER_TWO, id));
assertFalse(initGov.signed(SIGNER_THREE, id));
assertTrue(initGov.signed(SIGNER_FOUR, id));
assertFalse(initGov.signed(SIGNER_FIVE, id));
assertFalse(initGov.signed(SIGNER_SIX, id));

vm.prank(SIGNER_TWO);
initGov.signTxn(address(oracle), user);

assertEq(oracle.governance(), user);
assertEq(initGov.numberSigned(id), 3);
assertTrue(initGov.signed(SIGNER_ONE, id));
assertTrue(initGov.signed(SIGNER_TWO, id));
assertFalse(initGov.signed(SIGNER_THREE, id));
assertTrue(initGov.signed(SIGNER_FOUR, id));
assertFalse(initGov.signed(SIGNER_FIVE, id));
assertFalse(initGov.signed(SIGNER_SIX, id));
}
}
76 changes: 76 additions & 0 deletions src/utils/InitGov.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.18;

import {Governance} from "./Governance.sol";

/// @notice Multi chain contract to be the initial governance for contracts on deployment.
contract InitGov {
address public constant SAFE = 0x33333333D5eFb92f19a5F94a43456b3cec2797AE;

address public constant SIGNER_ONE =
0x6d2b80BA79871281Be7F70b079996a052B8D62F4;
address public constant SIGNER_TWO =
0x305af52AC31d3F9Daa1EC6231bA7b36Bb40f42f4;
address public constant SIGNER_THREE =
0xa05c4256ff0dd38697e63D48dF146e6e2FE7fe4A;
address public constant SIGNER_FOUR =
0x623d4A04e19328244924D1dee48252987C02fC0a;
address public constant SIGNER_FIVE =
0x5C166A5919cC07d785837d8Cc1261c67229d271D;
address public constant SIGNER_SIX =
0x80f751EdcB3012d5AF5530AFE97d5dC6EE176Bc0;

uint256 public constant THRESHOLD = 3;

mapping(address => bool) public isSigner;

mapping(bytes32 => uint256) public numberSigned;

mapping(address => mapping(bytes32 => bool)) public signed;

constructor() {
isSigner[SIGNER_ONE] = true;
isSigner[SIGNER_TWO] = true;
isSigner[SIGNER_THREE] = true;
isSigner[SIGNER_FOUR] = true;
isSigner[SIGNER_FIVE] = true;
isSigner[SIGNER_SIX] = true;
}

/// @notice To sign a txn from an eoa.
function signTxn(address _contract, address _newGovernance) external {
require(isSigner[msg.sender], "!signer");
bytes32 id = getTxnId(_contract, _newGovernance);
require(!signed[msg.sender][id], "already signed");

signed[msg.sender][id] = true;
numberSigned[id] += 1;

// Execute if we have reached the threshold.
if (numberSigned[id] == THRESHOLD)
_transferGovernance(_contract, _newGovernance);
}

/// @notice Can only be called by safe
function transferGovernance(
address _contract,
address _newGovernance
) external {
require(msg.sender == SAFE, "!safe");
_transferGovernance(_contract, _newGovernance);
}

function _transferGovernance(
address _contract,
address _newGovernance
) internal {
Governance(_contract).transferGovernance(_newGovernance);
}

function getTxnId(
address _contract,
address _newGovernance
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(_contract, _newGovernance));
}
}

0 comments on commit 3ab01eb

Please sign in to comment.