From 00e90fe10eba5319d32ef45efe7aefb3c9c3a690 Mon Sep 17 00:00:00 2001 From: Carl Farterson Date: Mon, 8 Nov 2021 18:01:22 -0800 Subject: [PATCH 1/3] fix(meTokenRegistry): events, natspec --- contracts/Foundry.sol | 122 +++++++++++----------- contracts/interfaces/IMeTokenRegistry.sol | 110 +++++++++++-------- contracts/registries/MeTokenRegistry.sol | 79 ++++++++++---- 3 files changed, 186 insertions(+), 125 deletions(-) diff --git a/contracts/Foundry.sol b/contracts/Foundry.sol index 14244357..98ee3712 100644 --- a/contracts/Foundry.sol +++ b/contracts/Foundry.sol @@ -228,6 +228,67 @@ contract Foundry is IFoundry, Ownable, Initializable { IERC20(_asset).approve(_vault, type(uint256).max); } + function viewBurn( + address _sender, + address _meToken, + uint256 _meTokensBurned + ) external view returns (uint256 actualtokensReturned) { + Details.MeToken memory meToken_ = meTokenRegistry.getDetails(_meToken); + Details.Hub memory hub_ = hub.getDetails(meToken_.hubId); + + // Calculate how many tokens tokens are returned + uint256 tokensReturned = calculateBurnReturn(_meToken, _meTokensBurned); + + uint256 feeRate; + uint256 actualTokensReturned; + // If msg.sender == owner, give owner the sell rate. - all of tokens returned plus a % + // of balancePooled based on how much % of supply will be burned + // If msg.sender != owner, give msg.sender the burn rate + if (_sender == meToken_.owner) { + feeRate = fees.burnOwnerFee(); + actualTokensReturned = + tokensReturned + + (((PRECISION * _meTokensBurned) / + IERC20(_meToken).totalSupply()) * meToken_.balanceLocked) / + PRECISION; + } else { + feeRate = fees.burnBuyerFee(); + if (hub_.targetRefundRatio == 0 && meToken_.targetHubId == 0) { + // Not updating targetRefundRatio or resubscribing + actualTokensReturned = + (tokensReturned * hub_.refundRatio) / + MAX_REFUND_RATIO; + } else { + if (hub_.targetRefundRatio > 0) { + // Hub is updating + actualTokensReturned = + (tokensReturned * + WeightedAverage.calculate( + hub_.refundRatio, + hub_.targetRefundRatio, + hub_.startTime, + hub_.endTime + )) / + MAX_REFUND_RATIO; + } else { + // meToken is resubscribing + Details.Hub memory targetHub_ = hub.getDetails( + meToken_.targetHubId + ); + actualTokensReturned = + (tokensReturned * + WeightedAverage.calculate( + hub_.refundRatio, + targetHub_.refundRatio, + meToken_.startTime, + meToken_.endTime + )) / + MAX_REFUND_RATIO; + } + } + } + } + // NOTE: for now this does not include fees function calculateMintReturn(address _meToken, uint256 _tokensDeposited) public @@ -296,67 +357,6 @@ contract Foundry is IFoundry, Ownable, Initializable { } } - function viewBurn( - address _sender, - address _meToken, - uint256 _meTokensBurned - ) external view returns (uint256 actualtokensReturned) { - Details.MeToken memory meToken_ = meTokenRegistry.getDetails(_meToken); - Details.Hub memory hub_ = hub.getDetails(meToken_.hubId); - - // Calculate how many tokens tokens are returned - uint256 tokensReturned = calculateBurnReturn(_meToken, _meTokensBurned); - - uint256 feeRate; - uint256 actualTokensReturned; - // If msg.sender == owner, give owner the sell rate. - all of tokens returned plus a % - // of balancePooled based on how much % of supply will be burned - // If msg.sender != owner, give msg.sender the burn rate - if (_sender == meToken_.owner) { - feeRate = fees.burnOwnerFee(); - actualTokensReturned = - tokensReturned + - (((PRECISION * _meTokensBurned) / - IERC20(_meToken).totalSupply()) * meToken_.balanceLocked) / - PRECISION; - } else { - feeRate = fees.burnBuyerFee(); - if (hub_.targetRefundRatio == 0 && meToken_.targetHubId == 0) { - // Not updating targetRefundRatio or resubscribing - actualTokensReturned = - (tokensReturned * hub_.refundRatio) / - MAX_REFUND_RATIO; - } else { - if (hub_.targetRefundRatio > 0) { - // Hub is updating - actualTokensReturned = - (tokensReturned * - WeightedAverage.calculate( - hub_.refundRatio, - hub_.targetRefundRatio, - hub_.startTime, - hub_.endTime - )) / - MAX_REFUND_RATIO; - } else { - // meToken is resubscribing - Details.Hub memory targetHub_ = hub.getDetails( - meToken_.targetHubId - ); - actualTokensReturned = - (tokensReturned * - WeightedAverage.calculate( - hub_.refundRatio, - targetHub_.refundRatio, - meToken_.startTime, - meToken_.endTime - )) / - MAX_REFUND_RATIO; - } - } - } - } - function calculateBurnReturn(address _meToken, uint256 _meTokensBurned) public view diff --git a/contracts/interfaces/IMeTokenRegistry.sol b/contracts/interfaces/IMeTokenRegistry.sol index 62dcafba..cb136843 100644 --- a/contracts/interfaces/IMeTokenRegistry.sol +++ b/contracts/interfaces/IMeTokenRegistry.sol @@ -4,76 +4,104 @@ pragma solidity ^0.8.0; import "../libs/Details.sol"; interface IMeTokenRegistry { - event Register( - address indexed meToken, - address indexed owner, - string name, - string symbol, - uint256 hubId + event Subscribe( + address indexed _meToken, + address indexed _owner, + string _name, + string _symbol, + uint256 _hubId ); - event TransferMeTokenOwnership(address from, address to, address meToken); - event UpdateBalancePooled(bool add, address meToken, uint256 amount); - event UpdateBalanceLocked(bool add, address meToken, uint256 amount); - - function updateBalances(address _meToken, uint256 _newBalance) external; - - function initResubscribe( - address _meToken, + event InitResubscribe( + address indexed _meToken, uint256 _targetHubId, - address _migration - ) external; - - function finishResubscribe(address _meToken) - external - returns (Details.MeToken memory); + address _migration, + bytes _encodedMigrationArgs + ); + event FinishResubscribe(address indexed _meToken); + event UpdateBalances(address _meToken, uint256 _newBalance); + event TransferMeTokenOwnership( + address _from, + address _to, + address _meToken + ); + event UpdateBalancePooled(bool add, address _meToken, uint256 _amount); + event UpdateBalanceLocked(bool add, address _meToken, uint256 _amount); /// @notice TODO /// @param _name TODO /// @param _symbol TODO /// @param _hubId TODO - /// @param _tokensDeposited TODO + /// @param _assetsDeposited TODO function subscribe( string calldata _name, string calldata _symbol, uint256 _hubId, - uint256 _tokensDeposited + uint256 _assetsDeposited ) external; - // /// @notice TODO - // /// @return TODO - // function toggleUpdating() external returns (bool); - /// @notice TODO - /// @param _owner TODO - /// @return TODO - function isOwner(address _owner) external view returns (bool); + /// @param _meToken TODO + /// @param _targetHubId TODO + /// @param _migration TODO + /// @param _encodedMigrationArgs TODO + function initResubscribe( + address _meToken, + uint256 _targetHubId, + address _migration, + bytes memory _encodedMigrationArgs + ) external; /// @notice TODO - /// @param _owner TODO + /// @param _meToken TODO /// @return TODO - function getOwnerMeToken(address _owner) external view returns (address); - - /// @notice TODO - /// @param meToken Address of meToken queried - /// @return meToken_ details of the meToken - function getDetails(address meToken) + function finishResubscribe(address _meToken) external - view - returns (Details.MeToken memory meToken_); - - function transferMeTokenOwnership(address _newOwner) external; + returns (Details.MeToken memory); - // function updateBalances(address _meToken) external; + /// @notice TODO + /// @param _meToken TODO + /// @param _newBalance TODO + function updateBalances(address _meToken, uint256 _newBalance) external; + /// @notice TODO + /// @param add TODO + /// @param _meToken TODO + /// @param _amount TODO function updateBalancePooled( bool add, address _meToken, uint256 _amount ) external; + /// @notice TODO + /// @param add TODO + /// @param _meToken TODO + /// @param _amount TODO function updateBalanceLocked( bool add, address _meToken, uint256 _amount ) external; + + /// @notice TODO + /// @param _newOwner TODO + function transferMeTokenOwnership(address _newOwner) external; + + /// @notice TODO + /// @param _owner TODO + /// @return TODO + function getOwnerMeToken(address _owner) external view returns (address); + + /// @notice TODO + /// @param meToken Address of meToken queried + /// @return meToken_ details of the meToken + function getDetails(address meToken) + external + view + returns (Details.MeToken memory meToken_); + + /// @notice TODO + /// @param _owner TODO + /// @return TODO + function isOwner(address _owner) external view returns (bool); } diff --git a/contracts/registries/MeTokenRegistry.sol b/contracts/registries/MeTokenRegistry.sol index 8362814c..39900290 100644 --- a/contracts/registries/MeTokenRegistry.sol +++ b/contracts/registries/MeTokenRegistry.sol @@ -19,7 +19,7 @@ import "../libs/Details.sol"; /// @title meToken registry /// @author Carl Farterson (@carlfarterson) /// @notice This contract tracks basic information about all meTokens -contract MeTokenRegistry is Ownable { +contract MeTokenRegistry is Ownable, IMeTokenRegistry { uint256 public constant PRECISION = 10**18; uint256 private _warmup; uint256 private _duration; @@ -45,12 +45,13 @@ contract MeTokenRegistry is Ownable { migrationRegistry = _migrationRegistry; } + /// @inheritdoc IMeTokenRegistry function subscribe( string calldata _name, string calldata _symbol, uint256 _hubId, uint256 _assetsDeposited - ) external { + ) external override { // TODO: access control require(!isOwner(msg.sender), "msg.sender already owns a meToken"); Details.Hub memory hub_ = hub.getDetails(_hubId); @@ -91,15 +92,16 @@ contract MeTokenRegistry is Ownable { meToken_.hubId = _hubId; meToken_.balancePooled = _assetsDeposited; - // emit Register(meTokenAddr, msg.sender, _name, _symbol, _hubId); + emit Subscribe(meTokenAddr, msg.sender, _name, _symbol, _hubId); } + /// @inheritdoc IMeTokenRegistry function initResubscribe( address _meToken, uint256 _targetHubId, address _migration, bytes memory _encodedMigrationArgs - ) external { + ) external override { Details.MeToken storage meToken_ = _meTokens[_meToken]; Details.Hub memory hub_ = hub.getDetails(meToken_.hubId); Details.Hub memory targetHub_ = hub.getDetails(_targetHubId); @@ -144,10 +146,19 @@ contract MeTokenRegistry is Ownable { _cooldown; meToken_.targetHubId = _targetHubId; meToken_.migration = _migration; + + emit InitResubscribe( + _meToken, + _targetHubId, + _migration, + _encodedMigrationArgs + ); } + /// @inheritdoc IMeTokenRegistry function finishResubscribe(address _meToken) external + override returns (Details.MeToken memory) { Details.MeToken storage meToken_ = _meTokens[_meToken]; @@ -169,10 +180,16 @@ contract MeTokenRegistry is Ownable { meToken_.hubId = meToken_.targetHubId; meToken_.targetHubId = 0; meToken_.migration = address(0); + + emit FinishResubscribe(_meToken); return meToken_; } - function updateBalances(address _meToken, uint256 _newBalance) external { + /// @inheritdoc IMeTokenRegistry + function updateBalances(address _meToken, uint256 _newBalance) + external + override + { Details.MeToken storage meToken_ = _meTokens[_meToken]; require(msg.sender == meToken_.migration, "!migration"); @@ -185,26 +202,16 @@ contract MeTokenRegistry is Ownable { (PRECISION * _newBalance) / oldBalance / PRECISION; - } - - function transferMeTokenOwnership(address _newOwner) external { - require(!isOwner(_newOwner), "_newOwner already owns a meToken"); - address _meToken = _owners[msg.sender]; - - require(_meToken != address(0), "!meToken"); - Details.MeToken storage meToken_ = _meTokens[_meToken]; - meToken_.owner = _newOwner; - _owners[msg.sender] = address(0); - _owners[_newOwner] = _meToken; - // emit TransferMeTokenOwnership(msg.sender, _newOwner, meToken); + emit UpdateBalances(_meToken, _newBalance); } + /// @inheritdoc IMeTokenRegistry function updateBalancePooled( bool add, address _meToken, uint256 _amount - ) external { + ) external override { require(msg.sender == foundry, "!foundry"); Details.MeToken storage meToken_ = _meTokens[_meToken]; if (add) { @@ -213,14 +220,15 @@ contract MeTokenRegistry is Ownable { meToken_.balancePooled -= _amount; } - // emit IncrementBalancePooled(add, _meToken, _amount); + emit UpdateBalancePooled(add, _meToken, _amount); } + /// @inheritdoc IMeTokenRegistry function updateBalanceLocked( bool add, address _meToken, uint256 _amount - ) external { + ) external override { require(msg.sender == foundry, "!foundry"); Details.MeToken storage meToken_ = _meTokens[_meToken]; @@ -230,7 +238,23 @@ contract MeTokenRegistry is Ownable { meToken_.balanceLocked -= _amount; } - // emit UpdateBalanceLocked(add, _meToken, _amount); + emit UpdateBalanceLocked(add, _meToken, _amount); + } + + /// @inheritdoc IMeTokenRegistry + function transferMeTokenOwnership(address _newOwner) external override { + require(!isOwner(_newOwner), "_newOwner already owns a meToken"); + + // TODO: what happens if multiple people want to revoke ownership to 0 address? + address _meToken = _owners[msg.sender]; + + require(_meToken != address(0), "!meToken"); + Details.MeToken storage meToken_ = _meTokens[_meToken]; + meToken_.owner = _newOwner; + _owners[msg.sender] = address(0); + _owners[_newOwner] = _meToken; + + emit TransferMeTokenOwnership(msg.sender, _newOwner, _meToken); } function setWarmup(uint256 warmup_) external onlyOwner { @@ -250,13 +274,21 @@ contract MeTokenRegistry is Ownable { _cooldown = cooldown_; } - function getOwnerMeToken(address _owner) external view returns (address) { + /// @inheritdoc IMeTokenRegistry + function getOwnerMeToken(address _owner) + external + view + override + returns (address) + { return _owners[_owner]; } + /// @inheritdoc IMeTokenRegistry function getDetails(address _meToken) external view + override returns (Details.MeToken memory meToken_) { meToken_ = _meTokens[_meToken]; @@ -274,7 +306,8 @@ contract MeTokenRegistry is Ownable { return _cooldown; } - function isOwner(address _owner) public view returns (bool) { + /// @inheritdoc IMeTokenRegistry + function isOwner(address _owner) public view override returns (bool) { return _owners[_owner] != address(0); } } From ad7f30e0f6a14ef4ce5358cbbb841800f5fac7d6 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 9 Nov 2021 14:30:14 +0100 Subject: [PATCH 2/3] fix(deploy): fix single asset vault verification --- deployment/script-rinkeby.json | 24 ++++++++++++------------ scripts/deploy.ts | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deployment/script-rinkeby.json b/deployment/script-rinkeby.json index 2777d948..b2404783 100644 --- a/deployment/script-rinkeby.json +++ b/deployment/script-rinkeby.json @@ -1,15 +1,15 @@ { "network": "rinkeby", - "Hub Contract Address": "0x05D6C7B5460eF728a068A4a8fE2A921df2c52CF6", - "VaultRegistry Contract Address": "0xCA82C0B535aaD7b26FE6feFE0B3D243ACf180D93", - "SingleAssetVault Contract Address": "0x1a96C7bB64070f6129a64F981CFCb544D78e7842", - "SingleAsset Vault Contract Address": "0x1a96C7bB64070f6129a64F981CFCb544D78e7842", - "Fee Contract Address": "0x889356A0325cF68Ea7aAE3554baa003E0297f963", - "Curve Registry Contract Address": "0xB8b36dcF76bE040dB276f5353e7cb23C51798811", - "Bancor Curve Contract Address": "0x6551A593a18586baeF221355886697cb39410587", - "Foundry Contract Address": "0x14435948a3f606baeF7e3893f59c10a3A67d9D97", - "MeToken Factory Contract Address": "0xf4a2AacCB5C9dCa49E6F65d497dED9616d127B92", - "MeToken Registry Contract Address": "0x745E3643C8B9f68184825e60bC4a0B8498cCEe87", - "WeightedAverage Contract Address": "0x13e7bF4A65822fC846b07fbad3e806eD1D094b59", - "Block Number": "9556651" + "Hub Contract Address": "0x3E0171E154Ebd6B07E78289Bf71c707E67486aEc", + "VaultRegistry Contract Address": "0x1871B0EbD230f79d32Cba92128841DDbC456a5e8", + "SingleAssetVault Contract Address": "0x061e6bF95094c06628722B81dAAa7b6067f125E0", + "SingleAsset Vault Contract Address": "0x061e6bF95094c06628722B81dAAa7b6067f125E0", + "Fee Contract Address": "0xA095A2f719b33BFA8D46c8ED7393F50Dd6922055", + "Curve Registry Contract Address": "0x400e78A8c45152de1Bb22ffD328bcB7eA80Bd6Cc", + "Bancor Curve Contract Address": "0xB8276f6b65b98f61c80ae8BDa0509a0d725DcF4F", + "Foundry Contract Address": "0x5b5b0F3b1dF3fFc25D859C7FA1472CCCd8Db9572", + "MeToken Factory Contract Address": "0x39DE2C7613513515634C1631ca2F8e4e090829Ec", + "MeToken Registry Contract Address": "0x7Fe7f9CaD8F0F23d93ffE60c54b216B3c9453111", + "WeightedAverage Contract Address": "0x27e4BD49898F3BfA3870E9c2219941C5e3fC9B7e", + "Block Number": "9612133" } diff --git a/scripts/deploy.ts b/scripts/deploy.ts index 54af4292..d165b340 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -210,7 +210,7 @@ async function main() { await run(TASK_VERIFY, { address: singleAssetVault.address, constructorArgsParams: [ - DAO, // DAO + DAO.address, // DAO foundry.address, // foundry hub.address, // hub meTokenRegistry.address, //IMeTokenRegistry @@ -249,7 +249,7 @@ async function main() { network: network.name, "Hub Contract Address": hub.address, "VaultRegistry Contract Address": vaultRegistry.address, - "SingleAssetVault Contract Address": singleAssetVault.address, + "Migration Registry Contract Address": migrationRegistry.address, "SingleAsset Vault Contract Address": singleAssetVault.address, "Fee Contract Address": fees.address, "Curve Registry Contract Address": curveRegistry.address, From 9410b9fd3685d47ab7aba277450d0226bbe03148 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 9 Nov 2021 18:17:22 +0100 Subject: [PATCH 3/3] fix(hint): max lines pushed up --- .solhintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.solhintrc.js b/.solhintrc.js index 15a14015..736888ef 100644 --- a/.solhintrc.js +++ b/.solhintrc.js @@ -6,7 +6,7 @@ module.exports = { rules: { "prettier/prettier": "error", "code-complexity": ["error", 10], - "function-max-lines": ["error", 100], + "function-max-lines": ["error", 110], "max-line-length": ["error", 140], "max-states-count": ["error", 20], "no-empty-blocks": "off",