From b652974a60814c3453b916dbfa49a76edadae57b Mon Sep 17 00:00:00 2001 From: owen05 Date: Thu, 9 Sep 2021 19:29:50 +0800 Subject: [PATCH] dev --- contracts/NFTPool/impl/FilterAdmin.sol | 223 ++++-------------- contracts/NFTPool/impl/FilterModel01.sol | 34 +++ .../SmartRoute/proxies/DODONFTPoolProxy.sol | 2 + contracts/lib/DecimalMath.sol | 15 ++ 4 files changed, 92 insertions(+), 182 deletions(-) diff --git a/contracts/NFTPool/impl/FilterAdmin.sol b/contracts/NFTPool/impl/FilterAdmin.sol index 760d869..68ff2ac 100644 --- a/contracts/NFTPool/impl/FilterAdmin.sol +++ b/contracts/NFTPool/impl/FilterAdmin.sol @@ -24,202 +24,74 @@ contract FilterAdmin is InitializableInternalMintableERC20, ReentrancyGuard { address public _CONTROLLER_MODEL_; address public _DEFAULT_MAINTAINER_; + // ============ Event ============ + event ChangeFee(uint256 fee); + function init( address _owner, string memory _name, string memory _symbol, uint256 fee, - address mtFeeModel, + address controllerModel, address defaultMaintainer, address[] memory filters ) external { super.init(_owner, 0, _name, _symbol, 18); _FILTER_REGISTRY_ = filters; _FEE_ = fee; - _CONTROLLER_MODEL_ = mtFeeModel; + _CONTROLLER_MODEL_ = controllerModel; _DEFAULT_MAINTAINER_ = defaultMaintainer; } - function ERC721In( - address filter, - address nftContract, - uint256[] memory tokenIds, - uint256 minMintAmount - ) - external - preventReentrant - returns (uint256 actualMintAmount) - { - require(isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); - require(IFilterModel(filter)._NFT_IN_SWITCH_(), "NFT_IN_CLOSED"); - require(IFilterModel(filter).getAvaliableNFTIn() >= tokenIds.length, "EXCEED_MAX_AMOUNT"); - uint256 totalPrice = 0; - for(uint256 i = 0; i < tokenIds.length; i++) { - require(IFilterModel(filter).isFilterERC721Pass(nftContract, tokenIds[i]), "NOT_REGISTERED"); - totalPrice = totalPrice.add(IFilterModel(filter).getNFTInPrice(nftContract, tokenIds[i])); - IFilterModel(filter).transferInERC721(nftContract, msg.sender, tokenIds[i]); - } + function chargeMint(address user, uint256 totalMintAmount) external { + require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED"); - (uint256 poolFeeAmount, uint256 mtFeeAmount) = _nftInFeeTransfer(totalPrice); + (uint256 poolFeeAmount, uint256 mtFeeAmount) = getMintFee(user, totalMintAmount); if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); - actualMintAmount = totalPrice.sub(mtFeeAmount).sub(poolFeeAmount); - require(actualMintAmount >= minMintAmount, "MINT_AMOUNT_NOT_ENOUGH"); - _mint(msg.sender, actualMintAmount); + _mint(user, totalMintAmount.sub(poolFeeAmount).sub(mtFeeAmount)); } - function ERC1155In( - address filter, - address nftContract, - uint256[] memory tokenIds, - uint256[] memory amounts, - uint256 minMintAmount - ) - external - preventReentrant - returns (uint256 actualMintAmount) - { - require(tokenIds.length == amounts.length, "PARAMS_NOT_MATCH"); - require(isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); - require(IFilterModel(filter)._NFT_IN_SWITCH_(), "NFT_IN_CLOSED"); - require(IFilterModel(filter).getAvaliableNFTIn() >= tokenIds.length, "EXCEED_MAX_AMOUNT"); - uint256 totalPrice = 0; - for(uint256 i = 0; i < tokenIds.length; i++) { - require(IFilterModel(filter).isFilterERC1155Pass(nftContract, tokenIds[i], amounts[i]), "NOT_REGISTERED"); - totalPrice = totalPrice.add(IFilterModel(filter).getNFTInPrice(nftContract, tokenIds[i]).mul(amounts[i])); - } + function chargeRandomBurn(address user, uint256 totalBurnAmount) external { + require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED"); - (uint256 poolFeeAmount, uint256 mtFeeAmount) = _nftInFeeTransfer(totalPrice); + (uint256 poolFeeAmount, uint256 mtFeeAmount) = getRandomBurnFee(user, totalBurnAmount); if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); - actualMintAmount = totalPrice.sub(mtFeeAmount).sub(poolFeeAmount); - require(actualMintAmount >= minMintAmount, "MINT_AMOUNT_NOT_ENOUGH"); - _mint(msg.sender, actualMintAmount); - - IFilterModel(filter).transferBatchInERC1155(nftContract, msg.sender, tokenIds, amounts); + _burn(user, totalBurnAmount); } - function ERC721RandomOut( - address filter, - uint256 times, - uint256 maxBurnAmount - ) - external - preventReentrant - returns (uint256 actualBurnAmount) - { - require(msg.sender == tx.origin, "ONLY_ALLOW_EOA"); - require(isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); - require(IFilterModel(filter)._NFT_RANDOM_SWITCH_(), "NFT_RANDOM_CLOSED"); - require(IFilterModel(filter).getAvaliableNFTOut() >= times, "EXCEED_MAX_AMOUNT"); - uint256 totalPrice = 0; - for(uint256 i = 0; i < times; i++) { - totalPrice = totalPrice.add(IFilterModel(filter).getNFTRandomOutPrice()); - (address nftContract, uint256 tokenId) = IFilterModel(filter).getRandomOutId(); - IFilterModel(filter).transferOutERC721(nftContract, msg.sender, tokenId); - } + function chargeTargetBurn(address user, uint256 totalBurnAmount) external { + require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED"); - (uint256 poolFeeAmount, uint256 mtFeeAmount) = _nftRandomOutFeeTransfer(totalPrice); + (uint256 poolFeeAmount, uint256 mtFeeAmount) = getTargetBurnFee(user, totalBurnAmount); if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); - actualBurnAmount = totalPrice; - require(actualBurnAmount <= maxBurnAmount, "EXTRA_BURN_AMOUNT"); - _burn(msg.sender, actualBurnAmount); + + _burn(user, totalBurnAmount); } - - function ERC1155RandomOut( - address filter, - uint256 times, - uint256 maxBurnAmount - ) - external - preventReentrant - returns (uint256 actualBurnAmount) - { - require(msg.sender == tx.origin, "ONLY_ALLOW_EOA"); - require(isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); - require(IFilterModel(filter)._NFT_RANDOM_SWITCH_(), "NFT_RANDOM_OUT_CLOSED"); - require(IFilterModel(filter).getAvaliableNFTOut() >= times, "EXCEED_MAX_AMOUNT"); - - uint256 totalPrice = 0; - for(uint256 i = 0; i < times; i++) { - totalPrice = totalPrice.add(IFilterModel(filter).getNFTRandomOutPrice()); - (address nftContract, uint256 tokenId) = IFilterModel(filter).getRandomOutId(); - IFilterModel(filter).transferOutERC1155(nftContract, msg.sender, tokenId, 1); - } - - (uint256 poolFeeAmount, uint256 mtFeeAmount) = _nftRandomOutFeeTransfer(totalPrice); - if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); - if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); - - actualBurnAmount = totalPrice; - require(actualBurnAmount <= maxBurnAmount, "EXTRA_BURN_AMOUNT"); - _burn(msg.sender, actualBurnAmount); - } - - function ERC721TargetOut( - address filter, - address nftContract, - uint256[] memory tokenIds, - uint256 maxBurnAmount - ) - external - preventReentrant - returns(uint256 actualBurnAmount) - { - require(isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); - require(IFilterModel(filter)._NFT_TARGET_SWITCH_(), "NFT_TARGET_OUT_CLOSED"); - require(IFilterModel(filter).getAvaliableNFTOut() >= tokenIds.length, "EXCEED_MAX_AMOUNT"); - uint256 totalPrice = 0; - for(uint256 i = 0; i < tokenIds.length; i++) { - totalPrice = totalPrice.add(IFilterModel(filter).getNFTTargetOutPrice(nftContract, tokenIds[i])); - IFilterModel(filter).transferOutERC721(nftContract, msg.sender, tokenIds[i]); - } - - (uint256 poolFeeAmount, uint256 mtFeeAmount) = _nftTargetOutFeeTransfer(totalPrice); - if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); - if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); - - actualBurnAmount = totalPrice; - require(actualBurnAmount <= maxBurnAmount, "EXTRA_BURN_AMOUNT"); - _burn(msg.sender, actualBurnAmount); - } - - function ERC1155TargetOut( - address filter, - address nftContract, - uint256[] memory tokenIds, - uint256[] memory amounts, - uint256 maxBurnAmount - ) - external - preventReentrant - returns(uint256 actualBurnAmount) - { - require(tokenIds.length == amounts.length, "PARAMS_NOT_MATCH"); - require(isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); - require(IFilterModel(filter)._NFT_TARGET_SWITCH_(), "NFT_TARGET_OUT_CLOSED"); - require(IFilterModel(filter).getAvaliableNFTOut() >= tokenIds.length, "EXCEED_MAX_AMOUNT"); - uint256 totalPrice = 0; - for(uint256 i = 0; i < tokenIds.length; i++) { - totalPrice = totalPrice.add(IFilterModel(filter).getNFTTargetOutPrice(nftContract, tokenIds[i]).mul(amounts[i])); - } - (uint256 poolFeeAmount, uint256 mtFeeAmount) = _nftTargetOutFeeTransfer(totalPrice); - if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); - if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); - - actualBurnAmount = totalPrice; - require(actualBurnAmount <= maxBurnAmount, "EXTRA_BURN_AMOUNT"); - _burn(msg.sender, actualBurnAmount); - - IFilterModel(filter).transferBatchOutERC1155(nftContract, msg.sender, tokenIds, amounts); - } - - //================ View ================ + function getMintFee(address user, uint256 totalMintAmount) public returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { + uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTInFee(address(this), user); + poolFeeAmount = DecimalMath.mulFloor(totalMintAmount, _FEE_); + mtFeeAmount = DecimalMath.mulFloor(totalMintAmount, mtFeeRate); + } + + function getRandomBurnFee(address user, uint256 totalBurnAmount) public returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { + uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTRandomOutFee(address(this), user); + poolFeeAmount = DecimalMath.mulFloor(totalBurnAmount, _FEE_); + mtFeeAmount = DecimalMath.mulFloor(totalBurnAmount, mtFeeRate); + } + + function getTargetBurnFee(address user, uint256 totalBurnAmount) public returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { + uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTTargetOutFee(address(this), user); + poolFeeAmount = DecimalMath.mulFloor(totalBurnAmount, _FEE_); + mtFeeAmount = DecimalMath.mulFloor(totalBurnAmount, mtFeeRate); + } + function isIncludeFilter(address filter) view public returns (bool) { uint256 i = 0; for(; i < _FILTER_REGISTRY_.length; i++) { @@ -236,28 +108,15 @@ contract FilterAdmin is InitializableInternalMintableERC20, ReentrancyGuard { return "FADMIN 1.0.0"; } - //=============== Owner ============== + //================= Owner ================ function addFilter(address filter) external onlyOwner { require(!isIncludeFilter(filter), "FILTER_NOT_INCLUDE"); _FILTER_REGISTRY_.push(filter); } - - //=============== Internal ============== - function _nftInFeeTransfer(uint256 totalPrice) internal returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { - uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTInFee(address(this), msg.sender); - poolFeeAmount = DecimalMath.mulFloor(totalPrice, _FEE_); - mtFeeAmount = DecimalMath.mulFloor(totalPrice, mtFeeRate); - } - function _nftRandomOutFeeTransfer(uint256 totalPrice) internal returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { - uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTRandomOutFee(address(this), msg.sender); - poolFeeAmount = DecimalMath.mulFloor(totalPrice, _FEE_); - mtFeeAmount = DecimalMath.mulFloor(totalPrice, mtFeeRate); - } - - function _nftTargetOutFeeTransfer(uint256 totalPrice) internal returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { - uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTTargetOutFee(address(this), msg.sender); - poolFeeAmount = DecimalMath.mulFloor(totalPrice, _FEE_); - mtFeeAmount = DecimalMath.mulFloor(totalPrice, mtFeeRate); + function changeFee(uint256 newFee) external onlyOwner { + require(newFee <= 1e18, "FEE_TOO_LARGE"); + _FEE_ = newFee; + emit ChangeFee(newFee); } } diff --git a/contracts/NFTPool/impl/FilterModel01.sol b/contracts/NFTPool/impl/FilterModel01.sol index 17a52dc..4d24d14 100644 --- a/contracts/NFTPool/impl/FilterModel01.sol +++ b/contracts/NFTPool/impl/FilterModel01.sol @@ -265,5 +265,39 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver { function version() virtual external pure returns (string memory) { return "FILTER_1_ERC721 1.0.0"; + //TODO: + function geometricCalc1(uint256 base, uint256 ratio, uint256 times) internal view returns(uint256 newBase, uint256 sum) { + require(times > 0); + //q^(n-1) + uint256 general_coefficient = ratio.powFloor(times - 1); + //an=a1*q^n-1 + newBase = base.mul(general_coefficient); + + if(ratio == 1e18) { + //na1 + sum = base.mul(times); + } else { + //a1(1-q^n)/(1-q) + uint256 denominator = base.mul(1e18.sub(DecimalMath.mulFloor(general_coefficient, ratio))); + sum = denominator.div(1e18.sub(ratio)); + } + } + + function removeTokenId(uint256 id) internal returns(bool){ + uint256[] memory tokenIds = _TOKEN_IDS_; + uint256 i; + for (; i < tokenIds.length; i++) { + if (tokenIds[i] == id) { + tokenIds[i] = tokenIds[tokenIds.length - 1]; + break; + } + } + if(i < tokenIds.length) { + _TOKEN_IDS_ = tokenIds; + _TOKEN_IDS_.pop(); + return true; + }else { + return false; + } } } \ No newline at end of file diff --git a/contracts/SmartRoute/proxies/DODONFTPoolProxy.sol b/contracts/SmartRoute/proxies/DODONFTPoolProxy.sol index f084c20..8430652 100644 --- a/contracts/SmartRoute/proxies/DODONFTPoolProxy.sol +++ b/contracts/SmartRoute/proxies/DODONFTPoolProxy.sol @@ -122,6 +122,8 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable { uint256[] memory tokenIds = new uint256[](1); tokenIds[0] = tokenId; + + //TODO: uint256 mintAmount = IFilterAdmin(filterAdmin).ERC721In(filter, nftContract, tokenIds, 0); _generalApproveMax(filterAdmin, dodoApprove, mintAmount); diff --git a/contracts/lib/DecimalMath.sol b/contracts/lib/DecimalMath.sol index 542bc77..f740048 100644 --- a/contracts/lib/DecimalMath.sol +++ b/contracts/lib/DecimalMath.sol @@ -45,4 +45,19 @@ library DecimalMath { function reciprocalCeil(uint256 target) internal pure returns (uint256) { return uint256(10**36).divCeil(target); } + + function powFloor(uint256 target, uint256 e) internal pure returns (uint256) { + if (e == 0) { + return 1; + } else if (e == 1) { + return target; + } else { + uint p = powFloor(target, e.div(2)); + p = p.mul(p) / (10**18); + if (e % 2 == 1) { + p = p.mul(target) / (10**18); + } + return p; + } + } }