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/MU08 #212

Merged
merged 6 commits into from
Aug 30, 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
38 changes: 38 additions & 0 deletions script/upgrades/MU08/MU08.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
### MU08

Transfer ownership of the MentoProtocol contracts to Mento Governance.

Proposal Summary:
This proposal transfers ownership of the MentoProtocol contracts to Mento Governance. This will allow Mento token holders to own and manage the protocol.

Contracts to Transfer Ownership:
philbow61 marked this conversation as resolved.
Show resolved Hide resolved

Tokens:

- StableTokenV2 implementation contract
- cUSDProxy contract
- cEURProxy contract
- cBRLProxy contract
- eXOFProxy contract
- cKESProxy contract
- POSProxy contract

MentoV2 contracts:

- BiPoolManager + BiPoolManagerProxy
- Broker + BrokerProxy
- Reserve + ReserveProxy
- BreakerBox
- MedianDeltaBreaker
- ValueDeltaBreaker

Legacy MentoV1 contracts:

- Exchange + ExchangeProxy
- ExchangeEUR + ExchangeEURProxy
- ExchangeBRL + ExchangeBRLProxy
- GrandaMento + GrandaMentoProxy

Mento Governance contracts:

- GovernanceFactory
201 changes: 201 additions & 0 deletions script/upgrades/MU08/MU08.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
// 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 experimental ABIEncoderV2;

import { GovernanceScript } from "script/utils/Script.sol";
import { console } from "forge-std/console.sol";
import { Contracts } from "script/utils/Contracts.sol";
import { Chain } from "script/utils/Chain.sol";
import { Arrays } from "script/utils/Arrays.sol";

import { IMentoUpgrade, ICeloGovernance } from "script/interfaces/IMentoUpgrade.sol";
import { IGovernanceFactory } from "script/interfaces/IGovernanceFactory.sol";

interface IOwnableLite {
function owner() external view returns (address);

function transferOwnership(address recipient) external;
}

interface IProxyLite {
function _getImplementation() external view returns (address);
}

contract MU08 is IMentoUpgrade, GovernanceScript {
using Contracts for Contracts.Cache;

bool public hasChecks = true;
ICeloGovernance.Transaction[] private transactions;

// Celo Governance:
address private celoGovernance;

// Mento contracts:

//Tokens:
address private cUSDProxy;
address private cEURProxy;
address private cBRLProxy;
address private eXOFProxy;
address private cKESProxy;

// MentoV2 contracts:
address private brokerProxy;
address private biPoolManagerProxy;
address private reserveProxy;
address private breakerBox;
address private medianDeltaBreaker;
address private valueDeltaBreaker;

// MentoV1 contracts:
address private exchangeProxy;
address private exchangeEURProxy;
address private exchangeBRLProxy;
address private grandaMentoProxy;

// MentoGovernance contracts:
address private governanceFactory;
address private timelockProxy;

function prepare() public {
loadDeployedContracts();
setAddresses();
}

/**
* @dev Loads the deployed contracts from previous deployments
*/
function loadDeployedContracts() public {
contracts.loadSilent("MU01-00-Create-Proxies", "latest");
contracts.loadSilent("MU01-01-Create-Nonupgradeable-Contracts", "latest");
contracts.loadSilent("MU03-01-Create-Nonupgradeable-Contracts", "latest");
contracts.loadSilent("eXOF-00-Create-Proxies", "latest");
contracts.loadSilent("cKES-00-Create-Proxies", "latest");
contracts.loadSilent("MUGOV-00-Create-Factory", "latest");
}

/**
* @dev Sets the addresses of the various contracts needed for the proposal.
*/
function setAddresses() public {
// Celo Governance:
celoGovernance = contracts.celoRegistry("Governance");

// Tokens:
cUSDProxy = address(uint160(contracts.celoRegistry("StableToken")));
cEURProxy = address(uint160(contracts.celoRegistry("StableTokenEUR")));
cBRLProxy = address(uint160(contracts.celoRegistry("StableTokenBRL")));
eXOFProxy = address(uint160(contracts.deployed("StableTokenXOFProxy")));
cKESProxy = address(uint160(contracts.deployed("StableTokenKESProxy")));

// MentoV2 contracts:
brokerProxy = address(uint160(contracts.deployed("BrokerProxy")));
biPoolManagerProxy = address(uint160(contracts.deployed("BiPoolManagerProxy")));
reserveProxy = address(uint160(contracts.celoRegistry("Reserve")));
breakerBox = address(uint160(contracts.deployed("BreakerBox")));
medianDeltaBreaker = address(uint160(contracts.deployed("MedianDeltaBreaker")));
valueDeltaBreaker = address(uint160(contracts.deployed("ValueDeltaBreaker")));

// MentoV1 contracts:
exchangeProxy = contracts.dependency("Exchange");
exchangeEURProxy = contracts.dependency("ExchangeEUR");
exchangeBRLProxy = contracts.dependency("ExchangeBRL");
grandaMentoProxy = contracts.dependency("GrandaMento");

// MentoGovernance contracts:
governanceFactory = contracts.deployed("GovernanceFactory");
timelockProxy = IGovernanceFactory(governanceFactory).governanceTimelock();
}

function run() public {
prepare();

ICeloGovernance.Transaction[] memory _transactions = buildProposal();

vm.startBroadcast(Chain.deployerPrivateKey());
{
createProposal(_transactions, "https://TODO", celoGovernance);
}
vm.stopBroadcast();
}

function buildProposal() public returns (ICeloGovernance.Transaction[] memory) {
require(transactions.length == 0, "buildProposal() should only be called once");

proposal_transferTokenOwnership();
proposal_transferMentoV2Ownership();
proposal_transferMentoV1Ownership();
proposal_transferGovFactoryOwnership();

return transactions;
}

function proposal_transferTokenOwnership() public {
address[] memory tokenProxies = Arrays.addresses(cUSDProxy, cEURProxy, cBRLProxy, eXOFProxy, cKESProxy);
for (uint i = 0; i < tokenProxies.length; i++) {
transferOwnership(tokenProxies[i]);
}

// All the token proxies are pointing to the same StableTokenV2 implementation (cUSD)
// so we only need to transfer ownership of that single contract.
address sharedImplementation = IProxyLite(cUSDProxy)._getImplementation();
for (uint i = 0; i < tokenProxies.length; i++) {
require(
IProxyLite(tokenProxies[i])._getImplementation() == sharedImplementation,
"Token proxies not poiting to cUSD implementation"
);
}
transferOwnership(sharedImplementation);
}

function proposal_transferMentoV2Ownership() public {
address[] memory mentoV2Proxies = Arrays.addresses(brokerProxy, biPoolManagerProxy, reserveProxy);
for (uint i = 0; i < mentoV2Proxies.length; i++) {
transferOwnership(mentoV2Proxies[i]);
address implementation = IProxyLite(mentoV2Proxies[i])._getImplementation();
transferOwnership(implementation);
}

address[] memory mentoV2NonupgradeableContracts = Arrays.addresses(
breakerBox,
medianDeltaBreaker,
valueDeltaBreaker
);
for (uint i = 0; i < mentoV2NonupgradeableContracts.length; i++) {
transferOwnership(mentoV2NonupgradeableContracts[i]);
}
}

function proposal_transferMentoV1Ownership() public {
// For some reason Mento V1 implementation contracts were not transferred to Celo Governance and are
// owned by the original deployer address. Therefore we can only transfer ownership of the proxies.
address[] memory mentoV1Proxies = Arrays.addresses(
exchangeProxy,
exchangeEURProxy,
exchangeBRLProxy,
grandaMentoProxy
);
for (uint i = 0; i < mentoV1Proxies.length; i++) {
transferOwnership(mentoV1Proxies[i]);
address implementation = IProxyLite(mentoV1Proxies[i])._getImplementation();
}
}

function proposal_transferGovFactoryOwnership() public {
transferOwnership(governanceFactory);
}

function transferOwnership(address contractAddr) internal {
address contractOwner = IOwnableLite(contractAddr).owner();
if (contractOwner != timelockProxy && contractOwner == celoGovernance) {
transactions.push(
ICeloGovernance.Transaction({
value: 0,
destination: contractAddr,
data: abi.encodeWithSelector(IOwnableLite(0).transferOwnership.selector, timelockProxy)
})
);
}
}
}
Loading
Loading