From 83dcecdeb81f3adabbe22ffacbf1aa6765e7fe8f Mon Sep 17 00:00:00 2001 From: Nicola Miotto Date: Mon, 10 Jul 2023 15:45:56 +0200 Subject: [PATCH] Upgrade Internal Market (#84) - rollback governanceToken to tokenInternal - upgrade internal market --- .openzeppelin/unknown-9001.json | 218 ++++++++++++++++++ README.md | 2 +- contracts/InternalMarket/InternalMarket.sol | 10 +- .../InternalMarket/InternalMarketBase.sol | 24 +- contracts/Voting/Voting.sol | 1 + tasks/upgrade.ts | 2 +- test/InternalMarket.ts | 9 +- 7 files changed, 242 insertions(+), 24 deletions(-) diff --git a/.openzeppelin/unknown-9001.json b/.openzeppelin/unknown-9001.json index a9ce00e..9a30f64 100644 --- a/.openzeppelin/unknown-9001.json +++ b/.openzeppelin/unknown-9001.json @@ -2716,6 +2716,224 @@ } } } + }, + "c73d13ac4ac873d8b92b5d3dffcf795df2ca1358685de9b3bf6f16f6c5a4034e": { + "address": "0xEDDF3b7810ca9DfB32E6a3E275e635987904450e", + "txHash": "0x9b51312c78ab51249241f0ace0ed820bee04a5a96dbd60b63bb0ea27a21bd2de", + "layout": { + "solcVersion": "0.8.19", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_roles", + "offset": 0, + "slot": "51", + "type": "t_contract(DAORoles)13255", + "contract": "HasRole", + "src": "contracts/extensions/HasRole.sol:11" + }, + { + "label": "tokenInternal", + "offset": 0, + "slot": "52", + "type": "t_contract(IGovernanceToken)7303", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:34" + }, + { + "label": "exchangeToken", + "offset": 0, + "slot": "53", + "type": "t_contract(ERC20)4378", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:37" + }, + { + "label": "redemptionController", + "offset": 0, + "slot": "54", + "type": "t_contract(IRedemptionController)8761", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:39" + }, + { + "label": "priceOracle", + "offset": 0, + "slot": "55", + "type": "t_contract(IStdReference)8489", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:40" + }, + { + "label": "_shareholderRegistry", + "offset": 0, + "slot": "56", + "type": "t_contract(IShareholderRegistry)11142", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:41" + }, + { + "label": "reserve", + "offset": 0, + "slot": "57", + "type": "t_address", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:43" + }, + { + "label": "offerDuration", + "offset": 0, + "slot": "58", + "type": "t_uint256", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:44" + }, + { + "label": "_offers", + "offset": 0, + "slot": "59", + "type": "t_mapping(t_address,t_struct(Offers)7625_storage)", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:46" + }, + { + "label": "_vaultContributors", + "offset": 0, + "slot": "60", + "type": "t_mapping(t_address,t_uint256)", + "contract": "InternalMarketBase", + "src": "contracts/InternalMarket/InternalMarketBase.sol:48" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(DAORoles)13255": { + "label": "contract DAORoles", + "numberOfBytes": "20" + }, + "t_contract(ERC20)4378": { + "label": "contract ERC20", + "numberOfBytes": "20" + }, + "t_contract(IGovernanceToken)7303": { + "label": "contract IGovernanceToken", + "numberOfBytes": "20" + }, + "t_contract(IRedemptionController)8761": { + "label": "contract IRedemptionController", + "numberOfBytes": "20" + }, + "t_contract(IShareholderRegistry)11142": { + "label": "contract IShareholderRegistry", + "numberOfBytes": "20" + }, + "t_contract(IStdReference)8489": { + "label": "contract IStdReference", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Offers)7625_storage)": { + "label": "mapping(address => struct InternalMarketBase.Offers)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint128,t_struct(Offer)7615_storage)": { + "label": "mapping(uint128 => struct InternalMarketBase.Offer)", + "numberOfBytes": "32" + }, + "t_struct(Offer)7615_storage": { + "label": "struct InternalMarketBase.Offer", + "members": [ + { + "label": "expiredAt", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "amount", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Offers)7625_storage": { + "label": "struct InternalMarketBase.Offers", + "members": [ + { + "label": "start", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "end", + "type": "t_uint128", + "offset": 16, + "slot": "0" + }, + { + "label": "offer", + "type": "t_mapping(t_uint128,t_struct(Offer)7615_storage)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } } } } diff --git a/README.md b/README.md index 2d7ce05..0ecc7fc 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Neokingdom DAO lives on EVMOS. - [GovernanceToken](https://escan.live/address/0x05d1b2355721903152768F0ec1B105Be1c35BCb4) `0x05d1b2355721903152768F0ec1B105Be1c35BCb4`, impl `0x21bc56fa89902ad945413ed606afc1fd8c22fbe2` - [Voting](https://escan.live/address/0x5DC219C8CaeF7c9ECd0b97372e6Ef4fC5D827975) `0x5DC219C8CaeF7c9ECd0b97372e6Ef4fC5D827975`, impl `0x3d76aaf1e34fcb191018cf8fc76dcc2547c4a59d` - [RedemptionController](https://escan.live/address/0x7045bfaB66B55074C56aBeE34308CDa0916e086C) `0x7045bfaB66B55074C56aBeE34308CDa0916e086C`, impl `0xe961a4bb3e1289215a597cbd14df57f4cd49c091` -- [InternalMarket](https://escan.live/address/0x7687155fB855e24d1416C288CbaC0AFC3B65353c) `0x7687155fB855e24d1416C288CbaC0AFC3B65353c`, impl `0x61e91896a76a1677154081ebb17a9a8183bfd47e` +- [InternalMarket](https://escan.live/address/0x7687155fB855e24d1416C288CbaC0AFC3B65353c) `0x7687155fB855e24d1416C288CbaC0AFC3B65353c`, impl `0xeddf3b7810ca9dfb32e6a3e275e635987904450e` - [ResolutionManager](https://escan.live/address/0xE5714C29b7acE2C6a3A80BE511ED7e5b92594204) `0xE5714C29b7acE2C6a3A80BE511ED7e5b92594204`, impl `0x9f589d09e7760ad46ecf9348353f348aad6b35f4` - [DAORoles](https://escan.live/address/0x6A176C92985430535E738A79749A4137BEC6C4Db) `0x6A176C92985430535E738A79749A4137BEC6C4Db` - [Operator SAFE on EVMOS](https://safe.evmos.org/evmos:0xd232121c41EF9ad4e4d0251BdCbe60b9F3D20758) `0xd232121c41EF9ad4e4d0251BdCbe60b9F3D20758` diff --git a/contracts/InternalMarket/InternalMarket.sol b/contracts/InternalMarket/InternalMarket.sol index 2a2e92d..7121cc5 100644 --- a/contracts/InternalMarket/InternalMarket.sol +++ b/contracts/InternalMarket/InternalMarket.sol @@ -20,13 +20,13 @@ contract InternalMarket is Initializable, HasRole, InternalMarketBase { /** * @dev Initializes the contract with the given roles and internal token. * @param roles DAORoles instance containing custom access control roles. - * @param governanceToken Reference to governance token. + * @param tokenInternal_ Reference to governance token. */ function initialize( DAORoles roles, - IGovernanceToken governanceToken + IGovernanceToken tokenInternal_ ) public initializer { - _initialize(governanceToken, 7 days); + _initialize(tokenInternal_, 7 days); _setRoles(roles); } @@ -91,10 +91,10 @@ contract InternalMarket is Initializable, HasRole, InternalMarketBase { * @dev Set internal token reference. * @param token The address of the internal governance token. */ - function setGovernanceToken( + function setTokenInternal( IGovernanceToken token ) public onlyRole(Roles.RESOLUTION_ROLE) zeroCheck(address(token)) { - _setGovernanceToken(token); + _setTokenInternal(token); } /** diff --git a/contracts/InternalMarket/InternalMarketBase.sol b/contracts/InternalMarket/InternalMarketBase.sol index f739959..225bcbb 100644 --- a/contracts/InternalMarket/InternalMarketBase.sol +++ b/contracts/InternalMarket/InternalMarketBase.sol @@ -31,7 +31,7 @@ contract InternalMarketBase { mapping(uint128 => Offer) offer; } - IGovernanceToken public governanceToken; + IGovernanceToken public tokenInternal; // Cannot use IERC20 here because it lacks `decimals` ERC20 public exchangeToken; @@ -51,7 +51,7 @@ contract InternalMarketBase { IGovernanceToken _governanceToken, uint256 _offerDuration ) internal virtual { - governanceToken = _governanceToken; + tokenInternal = _governanceToken; offerDuration = _offerDuration; } @@ -63,8 +63,8 @@ contract InternalMarketBase { return offers.end++; } - function _setGovernanceToken(IGovernanceToken token) internal virtual { - governanceToken = token; + function _setTokenInternal(IGovernanceToken token) internal virtual { + tokenInternal = token; } function _setShareholderRegistry( @@ -104,7 +104,7 @@ contract InternalMarketBase { emit OfferCreated(id, from, amount, expiredAt); require( - governanceToken.transferFrom(from, address(this), amount), + tokenInternal.transferFrom(from, address(this), amount), "InternalMarketBase: transfer failed" ); redemptionController.afterOffer(from, amount); @@ -180,7 +180,7 @@ contract InternalMarketBase { ) internal virtual { _beforeMatchOffer(from, to, amount); require( - governanceToken.transfer(to, amount), + tokenInternal.transfer(to, amount), "InternalMarketBase: transfer failed" ); require( @@ -201,9 +201,9 @@ contract InternalMarketBase { ) ) { _beforeWithdraw(from, amount); - governanceToken.unwrap(address(this), to, amount); + tokenInternal.unwrap(address(this), to, amount); } else { - governanceToken.unwrap(from, to, amount); + tokenInternal.unwrap(from, to, amount); } } @@ -215,15 +215,15 @@ contract InternalMarketBase { ) ); _beforeWithdraw(from, amount); - governanceToken.burn(address(this), amount); + tokenInternal.burn(address(this), amount); } function _deposit(address to, uint256 amount) internal virtual { - governanceToken.wrap(to, amount); + tokenInternal.wrap(to, amount); } function _finalizeDeposit(address to) internal virtual { - governanceToken.settleTokens(to); + tokenInternal.settleTokens(to); } function _redeem(address from, uint256 amount) internal virtual { @@ -232,7 +232,7 @@ contract InternalMarketBase { uint256 difference = amount - withdrawableBalance; // governanceToken is an address set by the operators of the DAO, hence trustworthy // slither-disable-start reentrancy-no-eth - governanceToken.burn(from, difference); + tokenInternal.burn(from, difference); _burn(from, withdrawableBalance); // slither-disable-end reentrancy-no-eth } else { diff --git a/contracts/Voting/Voting.sol b/contracts/Voting/Voting.sol index d4cb08c..d12cd71 100644 --- a/contracts/Voting/Voting.sol +++ b/contracts/Voting/Voting.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; diff --git a/tasks/upgrade.ts b/tasks/upgrade.ts index d04ef63..ca0f49d 100644 --- a/tasks/upgrade.ts +++ b/tasks/upgrade.ts @@ -39,7 +39,7 @@ task("upgrade:market", "Upgrade Internal Market", async (_, hre) => { const neokingdom = await NeokingdomDAOHardhat.initialize(hre); const contracts = await neokingdom.loadContracts(); - console.log("Upgrade InternalMarket"); + console.log(`Upgrade InternalMarket ${contracts.internalMarket.address}`); console.log(" Network:", hre.network.name); const answer = await question( diff --git a/test/InternalMarket.ts b/test/InternalMarket.ts index 75956ad..c85ac38 100644 --- a/test/InternalMarket.ts +++ b/test/InternalMarket.ts @@ -17,7 +17,6 @@ import { InternalMarket__factory, ShareholderRegistry, } from "../typechain"; -import { governanceToken } from "../typechain/contracts"; import { getEVMTimestamp, mineEVMBlock, setEVMTimestamp } from "./utils/evm"; import { roles } from "./utils/roles"; @@ -137,20 +136,20 @@ describe("InternalMarket", async () => { }); }); - describe("setGovernanceToken", async () => { + describe("setTokenInternal", async () => { it("should allow a resolution to set token and oracle addresses", async () => { // Alice is not a token, but it's a valid address, so we use it to test this function daoRoles.hasRole .whenCalledWith(RESOLUTION_ROLE, deployer.address) .returns(true); - await internalMarket.setGovernanceToken(alice.address); - expect(await internalMarket.governanceToken()).equal(alice.address); + await internalMarket.setTokenInternal(alice.address); + expect(await internalMarket.tokenInternal()).equal(alice.address); }); it("should revert if anyone else tries to set the token address", async () => { // Alice is not a token, but it's a valid address, so we use it to test this function await expect( - internalMarket.connect(alice).setGovernanceToken(alice.address) + internalMarket.connect(alice).setTokenInternal(alice.address) ).revertedWith( `AccessControl: account ${alice.address.toLowerCase()} is missing role ${RESOLUTION_ROLE}` );