Skip to content
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

feat: mento gov utils scripts #198

Merged
merged 8 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion script/interfaces/IERC20Lite.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma solidity >=0.5.17 <0.9.0;

interface IERC20Lite {
/**
Expand Down
2 changes: 1 addition & 1 deletion script/interfaces/IGovernanceFactory.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma solidity >=0.5.17 <0.9.0;
pragma experimental ABIEncoderV2;

interface IGovernanceFactory {
Expand Down
35 changes: 35 additions & 0 deletions script/interfaces/IGovernor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pragma solidity 0.8.18;

/**
* @dev Interface of the Bravo Compatible Governor.
*/
interface IGovernor {
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) external returns (uint256 proposalId);

/**
* @dev Part of the Governor Bravo's interface: _"Queues a proposal of state succeeded"_.
*/
function queue(uint256 proposalId) external;

/**
* @dev Part of the Governor Bravo's interface: _"Executes a queued proposal if eta has passed"_.
*/
function execute(uint256 proposalId) external;

/**
* @dev Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold.
*/
function cancel(uint256 proposalId) external;

/**
* @dev Cast a vote
*
* Emits a {VoteCast} event.
*/
function castVote(uint256 proposalId, uint8 support) external returns (uint256 balance);
}
2 changes: 1 addition & 1 deletion script/interfaces/IMentoUpgrade.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma solidity >=0.5.17 <0.9.0;
pragma experimental ABIEncoderV2;

import { ICeloGovernance } from "./ICeloGovernance.sol";
Expand Down
2 changes: 1 addition & 1 deletion script/upgrades/MUGOV/interfaces.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma solidity >=0.5.13 <0.9.0;

interface IMentoToken {
function emissionSupply() external view returns (uint256);
Expand Down
2 changes: 1 addition & 1 deletion script/utils/Arrays.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma solidity >=0.5.13 <0.9.0;

library Arrays {
function uints(uint256 e0) internal pure returns (uint256[] memory arr) {
Expand Down
2 changes: 1 addition & 1 deletion script/utils/Config.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// solhint-disable func-name-mixedcase, contract-name-camelcase, function-max-lines, var-name-mixedcase
pragma solidity ^0.5.13;
pragma solidity >=0.5.13 <0.9.0;
pragma experimental ABIEncoderV2;

import { FixidityLib } from "./FixidityLib.sol";
Expand Down
2 changes: 1 addition & 1 deletion script/utils/FixidityLib.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.5.13;
pragma solidity >=0.5.13 <0.9.0;

/**
* @title FixidityLib
Expand Down
97 changes: 97 additions & 0 deletions script/utils/mento/Chain.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.18;

import { Vm } from "forge-std/Vm.sol";

library Chain {
address private constant VM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code")))));
// solhint-disable-next-line const-name-snakecase
Vm public constant vm = Vm(VM_ADDRESS);

uint256 public constant NETWORK_ANVIL = 0;

uint256 public constant NETWORK_CELO_CHAINID = 42220;
string public constant NETWORK_CELO_CHAINID_STRING = "42220";
string public constant NETWORK_CELO_RPC = "celo";
string public constant NETWORK_CELO_PK_ENV_VAR = "MENTO_DEPLOYER_PK";
address public constant GOVERNANCE_FACTORY_CELO = 0xee6CE2dbe788dFC38b8F583Da86cB9caf2C8cF5A;

uint256 public constant NETWORK_BAKLAVA_CHAINID = 62320;
string public constant NETWORK_BAKLAVA_CHAINID_STRING = "62320";
string public constant NETWORK_BAKLAVA_RPC = "baklava";
string public constant NETWORK_BAKLAVA_PK_ENV_VAR = "BAKLAVA_DEPLOYER_PK";
address public constant GOVERNANCE_FACTORY_BAKLAVA = 0xe23A28a92B95c743fC0F09c16a6b2E6D59F234Fa;

uint256 public constant NETWORK_ALFAJORES_CHAINID = 44787;
string public constant NETWORK_ALFAJORES_CHAINID_STRING = "44787";
string public constant NETWORK_ALFAJORES_RPC = "alfajores";
string public constant NETWORK_ALFAJORES_PK_ENV_VAR = "ALFAJORES_DEPLOYER_PK";
address public constant GOVERNANCE_FACTORY_ALFAJORES = 0x96Fe03DBFEc1EB419885a01d2335bE7c1a45e33b;

/**
* @notice Get the current chainId
* @return _chainId the chain id
*/
function id() internal view returns (uint256 _chainId) {
// solhint-disable-next-line no-inline-assembly
assembly {
_chainId := chainid()
}
}

function idString() internal view returns (string memory) {
uint256 _chainId = id();
if (_chainId == NETWORK_CELO_CHAINID) return NETWORK_CELO_CHAINID_STRING;
if (_chainId == NETWORK_BAKLAVA_CHAINID) return NETWORK_BAKLAVA_CHAINID_STRING;
if (_chainId == NETWORK_ALFAJORES_CHAINID) return NETWORK_ALFAJORES_CHAINID_STRING;
revert("unexpected network");
}

function rpcToken() internal view returns (string memory) {
uint256 _chainId = id();
if (_chainId == NETWORK_CELO_CHAINID) return NETWORK_CELO_RPC;
if (_chainId == NETWORK_BAKLAVA_CHAINID) return NETWORK_BAKLAVA_RPC;
if (_chainId == NETWORK_ALFAJORES_CHAINID) return NETWORK_ALFAJORES_RPC;
revert("unexpected network");
}

function deployerPrivateKey() internal view returns (uint256) {
uint256 _chainId = id();
if (_chainId == NETWORK_CELO_CHAINID) return vm.envUint(NETWORK_CELO_PK_ENV_VAR);
if (_chainId == NETWORK_BAKLAVA_CHAINID) return vm.envUint(NETWORK_BAKLAVA_PK_ENV_VAR);
if (_chainId == NETWORK_ALFAJORES_CHAINID) return vm.envUint(NETWORK_ALFAJORES_PK_ENV_VAR);
revert("unexpected network");
}

function governanceFactory() internal view returns (address) {
uint256 _chainId = id();
if (_chainId == NETWORK_CELO_CHAINID) return GOVERNANCE_FACTORY_CELO;
if (_chainId == NETWORK_BAKLAVA_CHAINID) return GOVERNANCE_FACTORY_BAKLAVA;
if (_chainId == NETWORK_ALFAJORES_CHAINID) return GOVERNANCE_FACTORY_ALFAJORES;
revert("unexpected network");
}

function deployerAddr() internal view returns (address payable) {
return payable(address(uint160(vm.addr(deployerPrivateKey()))));
}

/**
* @notice Setup a fork environment for the current chain
*/
function fork() internal {
uint256 forkId = vm.createFork(rpcToken());
vm.selectFork(forkId);
}

function isCelo() internal view returns (bool) {
return id() == NETWORK_CELO_CHAINID;
}

function isBaklava() internal view returns (bool) {
return id() == NETWORK_BAKLAVA_CHAINID;
}

function isAlfajores() internal view returns (bool) {
return id() == NETWORK_ALFAJORES_CHAINID;
}
}
151 changes: 151 additions & 0 deletions script/utils/mento/Contracts.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.18;

import { console } from "forge-std/console.sol";

import { Vm } from "forge-std/Vm.sol";
import { Chain } from "./Chain.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { IRegistry } from "script/interfaces/IRegistry.sol";

library Contracts {
using stdJson for string;

address private constant REGISTRY_ADDRESS = 0x000000000000000000000000000000000000ce10;
// solhint-disable-next-line const-name-snakecase
IRegistry private constant registry = IRegistry(REGISTRY_ADDRESS);

address private constant VM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code")))));
// solhint-disable-next-line const-name-snakecase
Vm private constant vm = Vm(VM_ADDRESS);

bytes32 private constant CREATE_HASH = 0x14feaf0665b390ef0561125746780cd06c1876ebed7339648fad78cd5fb754ed;

struct Cache {
mapping(bytes32 => address) contractAddress;
bool _dependenciesLoaded;
string _dependencies;
}

function loadUpgrade(Cache storage self, string memory upgrade) internal {
load(self, string(abi.encodePacked(upgrade, "-00-Create-Proxies")), "latest");
load(self, string(abi.encodePacked(upgrade, "-01-Create-Nonupgradeable-Contracts")), "latest");
load(self, string(abi.encodePacked(upgrade, "-02-Create-Implementations")), "latest");
}

function load(Cache storage self, string memory script, string memory timestamp) internal {
_load(self, script, timestamp, false);
}

function loadSilent(Cache storage self, string memory script, string memory timestamp) internal {
_load(self, script, timestamp, true);
}

function _load(Cache storage self, string memory script, string memory timestamp, bool silent) internal {
string memory chainId = Chain.idString();
string memory root = vm.projectRoot();
string memory path = string(
abi.encodePacked(root, "/broadcast/", script, ".sol/", chainId, "/", "run-", timestamp, ".json")
);
string memory json = vm.readFile(path);
/**
* note(bogdan): Decoding this isn't straightforwad because we're using
philbow61 marked this conversation as resolved.
Show resolved Hide resolved
* an old solidity version which affects in two ways:
* (a) We can't use the latest forge-std helper scripts
* (b) There's a weird behaviour with decoding nested dynamic types
* In order to counteract this I'm jumping through hoops a bit.
* todo(bogdan): Remove all this once we update solidity.
*/

bytes memory contractAddressesRaw = json.parseRaw(".transactions[*].contractAddress");

address[] memory contractAddresses;
if (contractAddressesRaw.length == 32) {
contractAddresses = new address[](1);
contractAddresses[0] = abi.decode(contractAddressesRaw, (address));
} else {
contractAddresses = abi.decode(contractAddressesRaw, (address[]));
}

for (uint256 i = 0; i < contractAddresses.length; i++) {
string memory stringIndex = uint2str(i);

string memory txType = abi.decode(
json.parseRaw(string(abi.encodePacked(".transactions[", stringIndex, "].transactionType"))),
(string)
);

if (keccak256(bytes(txType)) == keccak256(bytes("CREATE"))) {
string memory contractName = abi.decode(
json.parseRaw(string(abi.encodePacked(".transactions[", stringIndex, "].contractName"))),
(string)
);

// todo(bogdan): think about best way to handle overrides
self.contractAddress[keccak256(bytes(contractName))] = contractAddresses[i];

if (!silent) {
console.log("Loaded contract %s at %s", contractName, contractAddresses[i]);
}
}
}
}

function deployed(Cache storage self, string memory contractName) internal view returns (address payable addr) {
addr = payable(address(uint160(self.contractAddress[keccak256(bytes(contractName))])));
require(
addr != address(0),
string(abi.encodePacked(contractName, ":NotFoundInDeployedCache:Check relevant deployemnt script was loaded"))
);
}

function celoRegistry(Cache storage, string memory contractName) internal view returns (address) {
return registry.getAddressForStringOrDie(contractName);
}

function _loadDependencies(Cache storage self) internal returns (Cache storage) {
string memory root = vm.projectRoot();
string memory path = string(abi.encodePacked(root, "/script/upgrades/dependencies.json"));
self._dependenciesLoaded = true;
self._dependencies = vm.readFile(path);
return self;
}

function dependency(Cache storage self, string memory contractName) internal returns (address) {
if (!self._dependenciesLoaded) _loadDependencies(self);
string memory chainId = Chain.idString();
bytes memory contractAddressRaw = self._dependencies.parseRaw(
// solhint-disable-next-line quotes
string(abi.encodePacked('["', chainId, '"]', '["', contractName, '"]'))
);

require(contractAddressRaw.length == 32, "dependency missing or invalid");
return abi.decode(contractAddressRaw, (address));
}

/// @notice converts number to string
/// @dev source: https://stackoverflow.com/questions/47129173/how-to-convert-uint-to-string-in-solidity
/// @param _i integer to convert
/// @return _uintAsString
function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len;
while (_i != 0) {
k = k - 1;
uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
bytes1 b1 = bytes1(temp);
bstr[k] = b1;
_i /= 10;
}
return string(bstr);
}
}
19 changes: 19 additions & 0 deletions script/utils/mento/ExecuteProposal.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.18;

import { Script } from "./Script.sol";
import { IGovernanceFactory } from "../../interfaces/IGovernanceFactory.sol";
import { IGovernor } from "../../interfaces/IGovernor.sol";
import { Chain } from "./Chain.sol";

contract ExecuteProposal is Script {
function run(uint256 proposalId) public {
address governance = IGovernanceFactory(Chain.governanceFactory()).mentoGovernor();

vm.startBroadcast(vm.envUint("MENTO_DEPLOYER_PK"));
{
IGovernor(governance).execute(proposalId);
}
vm.stopBroadcast();
}
}
Loading
Loading