From 056e8b8ece8598b2bbe509015b1d7006dd8b1090 Mon Sep 17 00:00:00 2001 From: owen05 Date: Wed, 19 May 2021 19:13:46 +0800 Subject: [PATCH] update --- .../MysteryBoxV2/BaseMysteryBox.sol | 39 +++++----- .../MysteryBoxV2/MysteryBoxERC1155.sol | 10 ++- .../MysteryBoxV2/MysteryBoxERC721.sol | 8 ++- .../MysteryBoxV2/MysteryBoxFeeModel.sol | 71 +++++++++++++++++++ .../proxies/DODOMysteryBoxProxy.sol | 20 ++---- 5 files changed, 112 insertions(+), 36 deletions(-) create mode 100644 contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxFeeModel.sol diff --git a/contracts/DODOMysteryBox/MysteryBoxV2/BaseMysteryBox.sol b/contracts/DODOMysteryBox/MysteryBoxV2/BaseMysteryBox.sol index 1d8258a..06b882e 100644 --- a/contracts/DODOMysteryBox/MysteryBoxV2/BaseMysteryBox.sol +++ b/contracts/DODOMysteryBox/MysteryBoxV2/BaseMysteryBox.sol @@ -6,7 +6,6 @@ pragma solidity 0.6.9; pragma experimental ABIEncoderV2; import {IERC20} from "../../intf/IERC20.sol"; -import {DecimalMath} from "../../lib/DecimalMath.sol"; import {UniversalERC20} from "../../SmartRoute/lib/UniversalERC20.sol"; import {SafeMath} from "../../lib/SafeMath.sol"; import {Address} from "../../external/utils/Address.sol"; @@ -15,7 +14,7 @@ import {IRandomGenerator} from "../../lib/RandomGenerator.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; import {InitializableERC20} from "../../external/ERC20/InitializableERC20.sol"; -interface IMysteryBoxPay { +interface IMysteryBoxFeeModel { function getPayAmount(address mysteryBox, address user, uint256 originalPrice, uint256 ticketAmount) external view returns (uint256, uint256); } @@ -34,7 +33,7 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG address public _BUY_TOKEN_; uint256 public _BUY_RESERVE_; - address public _FEE_MODEL_; + address public _DEFAULT_FEE_MODEL_; address payable public _DEFAULT_MAINTAINER_; address public _NFT_TOKEN_; @@ -46,9 +45,9 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG uint256 public _REDEEM_ALLOWED_TIME_; uint256[] public _BOX_INTERVAL_; // index => Interval probability (For ProbMode) index => tokenId (For FixedAmount mode) - uint256[][] public _TOKEN_ID_SET_; // Interval index => tokenIds (For ProbMode) + uint256[][] public _TOKEN_ID_SET_; // Interval index => tokenIds (Only For ProbMode) - bool public _IS_PROB_MODE; // false FixedAmount true ProbMode + bool public _IS_PROB_MODE; // false = FixedAmount mode, true = ProbMode bool public _IS_REVEAL_MODE_; uint256 public _REVEAL_RNG_ = 0; address public _RANDOM_GENERATOR_; @@ -75,13 +74,13 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG event SetPriceInterval(); event SetBoxInterval(); - event SetTokenIds(); - event SetTokenIdByIndex(uint256 index); + event SetTokenIds(); // only for ProbMode + event SetTokenIdByIndex(uint256 index); // only for ProbMode function init( - address[] memory contractList, //0 owner, 1 buyToken, 2 feeModel, 3 defaultMaintainer 4 randomGenerator 5 nftToken - uint256[][] memory priceList, //0 priceTimeInterval, 1 priceSet, 2 sellAmount + address[] memory addrList, //0 owner, 1 buyToken, 2 feeModel, 3 defaultMaintainer 4 randomGenerator 5 nftToken + uint256[][] memory priceSetList, //0 priceTimeInterval, 1 priceSet, 2 sellAmount uint256[] memory boxIntervals, uint256[][] memory tokenIds, uint256 redeemAllowedTime, @@ -89,15 +88,15 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG bool isProbMode, uint256 totalTickets ) public { - initOwner(contractList[0]); - _BUY_TOKEN_ = contractList[1]; - _FEE_MODEL_ = contractList[2]; - _DEFAULT_MAINTAINER_ = payable(contractList[3]); - _RANDOM_GENERATOR_ = contractList[4]; - _NFT_TOKEN_ = contractList[5]; + initOwner(addrList[0]); + _BUY_TOKEN_ = addrList[1]; + _DEFAULT_FEE_MODEL_ = addrList[2]; + _DEFAULT_MAINTAINER_ = payable(addrList[3]); + _RANDOM_GENERATOR_ = addrList[4]; + _NFT_TOKEN_ = addrList[5]; _REDEEM_ALLOWED_TIME_ = redeemAllowedTime; - if(priceList.length > 0) _setPrice(priceList[0], priceList[1], priceList[2]); + if(priceSetList.length > 0) _setPrice(priceSetList[0], priceSetList[1], priceSetList[2]); _IS_REVEAL_MODE_ = isRevealMode; _IS_PROB_MODE = isProbMode; @@ -116,7 +115,7 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG (uint256 curPrice, uint256 sellAmount, uint256 index) = getPriceAndSellAmount(); require(curPrice > 0 && sellAmount > 0, "CAN_NOT_BUY"); require(ticketAmount <= sellAmount, "TICKETS_NOT_ENOUGH"); - (uint256 payAmount, uint256 feeAmount) = IMysteryBoxPay(_FEE_MODEL_).getPayAmount(address(this), assetTo, curPrice, ticketAmount); + (uint256 payAmount, uint256 feeAmount) = IMysteryBoxFeeModel(_DEFAULT_FEE_MODEL_).getPayAmount(address(this), assetTo, curPrice, ticketAmount); require(payAmount > 0, "UnQualified"); uint256 baseBalance = IERC20(_BUY_TOKEN_).universalBalanceOf(address(this)); @@ -189,8 +188,8 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG require(priceIntervals.length == prices.length && prices.length == amounts.length, "PARAM_NOT_INVALID"); for (uint256 i = 0; i < priceIntervals.length - 1; i++) { require(priceIntervals[i] < priceIntervals[i + 1], "INTERVAL_INVALID"); - require(prices[i] != 0, "INTERVAL_INVALID"); - require(amounts[i] != 0, "INTERVAL_INVALID"); + require(prices[i] != 0, "PRICE_INVALID"); + require(amounts[i] != 0, "SELL_AMOUNT_INVALID"); } _PRICE_TIME_INTERVAL_ = priceIntervals; _PRICE_SET_ = prices; @@ -292,8 +291,8 @@ contract BaseMysteryBox is InitializableERC20, InitializableOwnable, ReentrancyG break; } } - sellAmount = _SELLING_AMOUNT_SET_[i-1]; curPrice = _PRICE_SET_[i-1]; + sellAmount = _SELLING_AMOUNT_SET_[i-1]; index = i - 1; } } diff --git a/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC1155.sol b/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC1155.sol index 6df4a87..cc2ed30 100644 --- a/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC1155.sol +++ b/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC1155.sol @@ -1,6 +1,6 @@ /* - Copyright 2020 DODO ZOO. + Copyright 2021 DODO ZOO. SPDX-License-Identifier: Apache-2.0 */ @@ -10,15 +10,21 @@ pragma solidity 0.6.9; import {ERC1155} from "../../external/ERC1155/ERC1155.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; -contract MysteryBoxERC1155 is ERC1155,InitializableOwnable { +contract MysteryBoxERC1155 is ERC1155, InitializableOwnable { mapping (address => bool) public _IS_ALLOWED_MINT_; + // ============ Event ============= + event addMinter(address account); + event removeMinter(address account); + function addMintAccount(address account) public onlyOwner { _IS_ALLOWED_MINT_[account] = true; + emit addMinter(account); } function removeMintAccount(address account) public onlyOwner { _IS_ALLOWED_MINT_[account] = false; + emit removeMinter(account); } function init( diff --git a/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC721.sol b/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC721.sol index 070c6e6..d3c197e 100644 --- a/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC721.sol +++ b/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxERC721.sol @@ -10,15 +10,21 @@ pragma solidity 0.6.9; import {ERC721} from "../../external/ERC721/ERC721.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; -contract MysteryBoxERC721 is ERC721,InitializableOwnable { +contract MysteryBoxERC721 is ERC721, InitializableOwnable { mapping (address => bool) public _IS_ALLOWED_MINT_; + // ============ Event ============= + event addMinter(address account); + event removeMinter(address account); + function addMintAccount(address account) public onlyOwner { _IS_ALLOWED_MINT_[account] = true; + emit addMinter(account); } function removeMintAccount(address account) public onlyOwner { _IS_ALLOWED_MINT_[account] = false; + emit removeMinter(account); } function init( diff --git a/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxFeeModel.sol b/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxFeeModel.sol new file mode 100644 index 0000000..25aad85 --- /dev/null +++ b/contracts/DODOMysteryBox/MysteryBoxV2/MysteryBoxFeeModel.sol @@ -0,0 +1,71 @@ +/* + + Copyright 2021 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; + +import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; +import {SafeMath} from "../../lib/SafeMath.sol"; +import {DecimalMath} from "../../lib/DecimalMath.sol"; + +interface IFee { + function getUserFee(address user,uint256 ticketAmount) external view returns (uint256); +} + +interface IPrice { + function getUserPrice(address user, uint256 originalPrice, uint256 ticketAmount) external view returns (uint256); +} + +contract MysteryBoxFeeModel is InitializableOwnable { + using SafeMath for uint256; + + struct MysteryBoxInfo { + bool isSet; + uint256 globalFee; + address feeAddr; + address priceAddr; + } + + mapping(address => MysteryBoxInfo) mysteryBoxes; + + function addMysteryBoxInfo(address mysteryBox, uint256 globalFee, address feeAddr, address priceAddr) external onlyOwner { + MysteryBoxInfo memory boxInfo = MysteryBoxInfo({ + isSet: true, + globalFee: globalFee, + feeAddr: feeAddr, + priceAddr: priceAddr + }); + mysteryBoxes[mysteryBox] = boxInfo; + } + + function setMysteryBoxInfo(address mysteryBox, uint256 globalFee, address feeAddr, address priceAddr) external onlyOwner { + require(mysteryBoxes[mysteryBox].isSet, "NOT_FOUND_BOX"); + mysteryBoxes[mysteryBox].globalFee = globalFee; + mysteryBoxes[mysteryBox].feeAddr = feeAddr; + mysteryBoxes[mysteryBox].priceAddr = priceAddr; + } + + function getPayAmount(address mysteryBox, address user, uint256 originalPrice, uint256 ticketAmount) external view returns (uint256 payAmount, uint256 feeAmount) { + MysteryBoxInfo memory boxInfo = mysteryBoxes[mysteryBox]; + if(!mysteryBoxes[mysteryBox].isSet) { + payAmount = originalPrice.mul(ticketAmount); + feeAmount = 0; + } else { + uint256 feeRate = boxInfo.globalFee; + address feeAddr = boxInfo.feeAddr; + if(feeAddr != address(0)) + feeRate = IFee(feeAddr).getUserFee(user, ticketAmount); + + uint256 price = originalPrice; + address priceAddr = boxInfo.priceAddr; + if(priceAddr != address(0)) + price = IPrice(priceAddr).getUserPrice(user, originalPrice, ticketAmount); + + payAmount = price.mul(ticketAmount); + feeAmount = DecimalMath.mulFloor(payAmount, feeRate); + } + } +} \ No newline at end of file diff --git a/contracts/SmartRoute/proxies/DODOMysteryBoxProxy.sol b/contracts/SmartRoute/proxies/DODOMysteryBoxProxy.sol index 333ee4c..4cf4696 100644 --- a/contracts/SmartRoute/proxies/DODOMysteryBoxProxy.sol +++ b/contracts/SmartRoute/proxies/DODOMysteryBoxProxy.sol @@ -8,19 +8,18 @@ pragma solidity 0.6.9; import {IDODOApproveProxy} from "../DODOApproveProxy.sol"; import {IERC20} from "../../intf/IERC20.sol"; -import {IWETH} from "../../intf/IWETH.sol"; import {SafeMath} from "../../lib/SafeMath.sol"; import {SafeERC20} from "../../lib/SafeERC20.sol"; import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol"; interface IDODOMysteryBox { function _BUY_TOKEN_() external view returns (address); - function _FEE_MODEL_() external view returns (address); + function _DEFAULT_FEE_MODEL_() external view returns (address); function getPriceAndSellAmount() external view returns (uint256, uint256, uint256); function buyTickets(address assetTo, uint256 ticketAmount) external; } -interface IMysteryBoxPay { +interface IMysteryBoxFeeModel { function getPayAmount(address mysteryBox, address user, uint256 originalPrice, uint256 ticketAmount) external view returns (uint256, uint256); } @@ -35,8 +34,7 @@ contract DODOMysteryBoxProxy is ReentrancyGuard { // ============ Storage ============ - address constant _ETH_ADDRESS_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public immutable _WETH_; + address constant _BASE_COIN_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address public immutable _DODO_APPROVE_PROXY_; // ============ Events ============ @@ -46,11 +44,7 @@ contract DODOMysteryBoxProxy is ReentrancyGuard { receive() external payable {} - constructor( - address payable weth, - address dodoApproveProxy - ) public { - _WETH_ = weth; + constructor(address dodoApproveProxy) public { _DODO_APPROVE_PROXY_ = dodoApproveProxy; } @@ -59,12 +53,12 @@ contract DODOMysteryBoxProxy is ReentrancyGuard { require(curPrice > 0 && sellAmount > 0, "CAN_NOT_BUY"); require(ticketAmount <= sellAmount, "TICKETS_NOT_ENOUGH"); - address feeModel = IDODOMysteryBox(dodoMysteryBox)._FEE_MODEL_(); - (uint256 payAmount,) = IMysteryBoxPay(feeModel).getPayAmount(dodoMysteryBox, msg.sender, curPrice, ticketAmount); + address feeModel = IDODOMysteryBox(dodoMysteryBox)._DEFAULT_FEE_MODEL_(); + (uint256 payAmount,) = IMysteryBoxFeeModel(feeModel).getPayAmount(dodoMysteryBox, msg.sender, curPrice, ticketAmount); require(payAmount > 0, "UnQualified"); address buyToken = IDODOMysteryBox(dodoMysteryBox)._BUY_TOKEN_(); - if(buyToken == _ETH_ADDRESS_) { + if(buyToken == _BASE_COIN_) { require(msg.value >= payAmount, "PAYAMOUNT_NOT_ENOUGH"); dodoMysteryBox.transfer(payAmount); }else {