This commit is contained in:
owen05
2021-09-09 22:38:19 +08:00
parent b652974a60
commit e617e61fe6
9 changed files with 379 additions and 227 deletions

View File

@@ -16,13 +16,11 @@ contract ControllerModel is InitializableOwnable {
using SafeMath for uint256; using SafeMath for uint256;
uint256 public _GLOBAL_NFT_IN_FEE_ = 0; uint256 public _GLOBAL_NFT_IN_FEE_ = 0;
uint256 public _GLOBAL_NFT_RANDOM_OUT_FEE_ = 0; uint256 public _GLOBAL_NFT_OUT_FEE_ = 0;
uint256 public _GLOBAL_NFT_TARGET_OUT_FEE_ = 50000000000000000;//0.05
struct FilterAdminFeeInfo { struct FilterAdminFeeInfo {
uint256 nftInFee; uint256 nftInFee;
uint256 nftRandomOutFee; uint256 nftOutFee;
uint256 nftTargetOutFee;
bool isSet; bool isSet;
} }
@@ -35,26 +33,23 @@ contract ControllerModel is InitializableOwnable {
//==================== Ownable ==================== //==================== Ownable ====================
function addFilterAdminFeeInfo(address filterAdminAddr, uint256 nftInFee, uint256 nftRandomOutFee, uint256 nftTargetOutFee) external onlyOwner { function addFilterAdminFeeInfo(address filterAdminAddr, uint256 nftInFee, uint256 nftOutFee) external onlyOwner {
FilterAdminFeeInfo memory filterAdmin = FilterAdminFeeInfo({ FilterAdminFeeInfo memory filterAdmin = FilterAdminFeeInfo({
nftInFee: nftInFee, nftInFee: nftInFee,
nftRandomOutFee: nftRandomOutFee, nftOutFee: nftOutFee,
nftTargetOutFee: nftTargetOutFee,
isSet: true isSet: true
}); });
filterAdminFees[filterAdminAddr] = filterAdmin; filterAdminFees[filterAdminAddr] = filterAdmin;
} }
function setFilterAdminFeeInfo(address filterAdminAddr, uint256 nftInFee, uint256 nftRandomOutFee, uint256 nftTargetOutFee) external onlyOwner { function setFilterAdminFeeInfo(address filterAdminAddr, uint256 nftInFee, uint256 nftOutFee) external onlyOwner {
filterAdminFees[filterAdminAddr].nftInFee = nftInFee; filterAdminFees[filterAdminAddr].nftInFee = nftInFee;
filterAdminFees[filterAdminAddr].nftRandomOutFee = nftRandomOutFee; filterAdminFees[filterAdminAddr].nftOutFee = nftOutFee;
filterAdminFees[filterAdminAddr].nftTargetOutFee = nftTargetOutFee;
} }
function setGlobalParam(uint256 nftInFee, uint256 nftRandomOutFee, uint256 nftTargetOutFee) external onlyOwner { function setGlobalParam(uint256 nftInFee, uint256 nftOutFee) external onlyOwner {
_GLOBAL_NFT_IN_FEE_ = nftInFee; _GLOBAL_NFT_IN_FEE_ = nftInFee;
_GLOBAL_NFT_RANDOM_OUT_FEE_ = nftRandomOutFee; _GLOBAL_NFT_OUT_FEE_ = nftOutFee;
_GLOBAL_NFT_TARGET_OUT_FEE_ = nftTargetOutFee;
} }
function setEmergencyWithdraw(address filter, bool isOpen) external onlyOwner { function setEmergencyWithdraw(address filter, bool isOpen) external onlyOwner {
@@ -63,7 +58,7 @@ contract ControllerModel is InitializableOwnable {
} }
//===================== View ======================== //===================== View ========================
function getNFTInFee(address filterAdminAddr, address) external view returns(uint256) { function getMintFee(address filterAdminAddr) external view returns(uint256) {
FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr]; FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr];
if(filterAdminFeeInfo.isSet) { if(filterAdminFeeInfo.isSet) {
@@ -73,26 +68,16 @@ contract ControllerModel is InitializableOwnable {
} }
} }
function getNFTRandomOutFee(address filterAdminAddr, address) external view returns(uint256) { function getBurnFee(address filterAdminAddr) external view returns(uint256) {
FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr]; FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr];
if(filterAdminFeeInfo.isSet) { if(filterAdminFeeInfo.isSet) {
return filterAdminFeeInfo.nftRandomOutFee; return filterAdminFeeInfo.nftOutFee;
}else { }else {
return _GLOBAL_NFT_RANDOM_OUT_FEE_; return _GLOBAL_NFT_OUT_FEE_;
} }
} }
function getNFTTargetOutFee(address filterAdminAddr, address) external view returns(uint256) {
FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr];
if(filterAdminFeeInfo.isSet) {
return filterAdminFeeInfo.nftTargetOutFee;
}else {
return _GLOBAL_NFT_TARGET_OUT_FEE_;
}
}
function getEmergencySwitch(address filter) external view returns(bool) { function getEmergencySwitch(address filter) external view returns(bool) {
return isEmergencyWithdraw[filter]; return isEmergencyWithdraw[filter];
} }

View File

@@ -10,12 +10,10 @@ pragma experimental ABIEncoderV2;
import {InitializableInternalMintableERC20} from "../../external/ERC20/InitializableInternalMintableERC20.sol"; import {InitializableInternalMintableERC20} from "../../external/ERC20/InitializableInternalMintableERC20.sol";
import {SafeMath} from "../../lib/SafeMath.sol"; import {SafeMath} from "../../lib/SafeMath.sol";
import {IFilterModel} from "../intf/IFilterModel.sol";
import {IControllerModel} from "../intf/IControllerModel.sol"; import {IControllerModel} from "../intf/IControllerModel.sol";
import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol";
import {DecimalMath} from "../../lib/DecimalMath.sol"; import {DecimalMath} from "../../lib/DecimalMath.sol";
contract FilterAdmin is InitializableInternalMintableERC20, ReentrancyGuard { contract FilterAdmin is InitializableInternalMintableERC20 {
using SafeMath for uint256; using SafeMath for uint256;
// ============ Storage ============ // ============ Storage ============
@@ -28,69 +26,57 @@ contract FilterAdmin is InitializableInternalMintableERC20, ReentrancyGuard {
event ChangeFee(uint256 fee); event ChangeFee(uint256 fee);
function init( function init(
address _owner, address owner,
string memory _name, uint256 initSupply,
string memory _symbol, string memory name,
string memory symbol,
uint256 fee, uint256 fee,
address controllerModel, address controllerModel,
address defaultMaintainer, address defaultMaintainer,
address[] memory filters address[] memory filters
) external { ) external {
super.init(_owner, 0, _name, _symbol, 18); super.init(owner, initSupply, name, symbol, 18);
_FILTER_REGISTRY_ = filters; _FILTER_REGISTRY_ = filters;
_FEE_ = fee; _FEE_ = fee;
_CONTROLLER_MODEL_ = controllerModel; _CONTROLLER_MODEL_ = controllerModel;
_DEFAULT_MAINTAINER_ = defaultMaintainer; _DEFAULT_MAINTAINER_ = defaultMaintainer;
} }
function chargeMint(address user, uint256 totalMintAmount) external { function mintFragTo(address to, uint256 rawAmount) external returns (uint256 received){
require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED"); require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED");
(uint256 poolFeeAmount, uint256 mtFeeAmount) = getMintFee(user, totalMintAmount); (uint256 poolFee, uint256 mtFee) = queryChargeMintFee(rawAmount);
if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); if(poolFee > 0) _mint(_OWNER_, poolFee);
if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); if(mtFee > 0) _mint(_DEFAULT_MAINTAINER_, mtFee);
_mint(user, totalMintAmount.sub(poolFeeAmount).sub(mtFeeAmount)); received = rawAmount.sub(poolFee).sub(mtFee);
_mint(to, received);
} }
function chargeRandomBurn(address user, uint256 totalBurnAmount) external { function burnFragFrom(address from, uint256 rawAmount) external returns (uint256 paid){
require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED"); require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED");
(uint256 poolFeeAmount, uint256 mtFeeAmount) = getRandomBurnFee(user, totalBurnAmount); (uint256 poolFee, uint256 mtFee) = queryChargeBurnFee(rawAmount);
if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount); if(poolFee > 0) _mint(_OWNER_, poolFee);
if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount); if(mtFee > 0) _mint(_DEFAULT_MAINTAINER_, mtFee);
_burn(user, totalBurnAmount); paid = rawAmount.add(poolFee).add(mtFee);
} _burn(from, paid);
function chargeTargetBurn(address user, uint256 totalBurnAmount) external {
require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED");
(uint256 poolFeeAmount, uint256 mtFeeAmount) = getTargetBurnFee(user, totalBurnAmount);
if(poolFeeAmount > 0) _mint(_OWNER_, poolFeeAmount);
if(mtFeeAmount > 0) _mint(_DEFAULT_MAINTAINER_, mtFeeAmount);
_burn(user, totalBurnAmount);
} }
//================ View ================ //================ View ================
function getMintFee(address user, uint256 totalMintAmount) public returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { function queryChargeMintFee(uint256 rawAmount) public returns (uint256 poolFee, uint256 mtFee) {
uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTInFee(address(this), user); uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getMintFee(address(this));
poolFeeAmount = DecimalMath.mulFloor(totalMintAmount, _FEE_); poolFee = DecimalMath.mulFloor(rawAmount, _FEE_);
mtFeeAmount = DecimalMath.mulFloor(totalMintAmount, mtFeeRate); mtFee = DecimalMath.mulFloor(rawAmount, mtFeeRate);
} }
function getRandomBurnFee(address user, uint256 totalBurnAmount) public returns (uint256 poolFeeAmount, uint256 mtFeeAmount) { function queryChargeBurnFee(uint256 rawAmount) public returns (uint256 poolFee, uint256 mtFee) {
uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getNFTRandomOutFee(address(this), user); uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getBurnFee(address(this));
poolFeeAmount = DecimalMath.mulFloor(totalBurnAmount, _FEE_); poolFee = DecimalMath.mulFloor(rawAmount, _FEE_);
mtFeeAmount = DecimalMath.mulFloor(totalBurnAmount, mtFeeRate); mtFee = DecimalMath.mulFloor(rawAmount, 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) { function isIncludeFilter(address filter) view public returns (bool) {
uint256 i = 0; uint256 i = 0;

View File

@@ -15,9 +15,9 @@ import {IControllerModel} from "../intf/IControllerModel.sol";
import {IERC721} from "../../intf/IERC721.sol"; import {IERC721} from "../../intf/IERC721.sol";
import {IERC721Receiver} from "../../intf/IERC721Receiver.sol"; import {IERC721Receiver} from "../../intf/IERC721Receiver.sol";
import {DecimalMath} from "../../lib/DecimalMath.sol"; import {DecimalMath} from "../../lib/DecimalMath.sol";
import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol";
contract FilterERC721V1 is InitializableOwnable, IERC721Receiver, ReentrancyGuard {
contract FilterModel01 is InitializableOwnable, IERC721Receiver {
using SafeMath for uint256; using SafeMath for uint256;
//=================== Storage =================== //=================== Storage ===================
@@ -27,6 +27,7 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
//tokenId => isRegistered //tokenId => isRegistered
mapping(uint256 => bool) public _SPREAD_IDS_REGISTRY_; mapping(uint256 => bool) public _SPREAD_IDS_REGISTRY_;
//tokenId => 1
mapping(uint256 => uint256) public _NFT_RESERVE_; mapping(uint256 => uint256) public _NFT_RESERVE_;
uint256[] public _NFT_IDS_; uint256[] public _NFT_IDS_;
@@ -54,9 +55,25 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
function init( function init(
address filterAdmin, address filterAdmin,
address nftCollection, address nftCollection,
bool[] memory switches,
uint256[] memory tokenRanges,
uint256[] memory nftAmounts,
uint256[] memory priceRules,
uint256[] memory spreadIds
) external { ) external {
initOwner(filterAdmin); initOwner(filterAdmin);
_NFT_COLLECTION_ = nftCollection; _NFT_COLLECTION_ = nftCollection;
_changeNFTInPrice(priceRules[0],priceRules[1],switches[0]);
_changeNFTRandomInPrice(priceRules[2],priceRules[3],switches[1]);
_changeNFTTargetOutPrice(priceRules[4],priceRules[5],switches[2]);
_changeNFTAmount(nftAmounts[0],nftAmounts[1]);
_changeTokenIdRange(tokenRanges[0],tokenRanges[1]);
for(uint256 i = 0; i < spreadIds.length; i++) {
_SPREAD_IDS_REGISTRY_[spreadIds[i]] = true;
}
} }
//==================== Query ================== //==================== Query ==================
@@ -69,54 +86,69 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
} }
} }
function isNFTIDValid(uint256 nftId) public view returns(bool){ function isNFTIDValid(uint256 nftId) public view returns(bool) {
if((nftId >= _TOKEN_ID_START_ && nftId <= _TOKEN_ID_END_) || _SPREAD_IDS_REGISTRY_[nftId]) { if((nftId >= _NFT_ID_START_ && nftId <= _NFT_ID_END_) || _SPREAD_IDS_REGISTRY_[nftId]) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
function getAvaliableNFTIn() public view returns(uint256) { function getAvaliableNFTIn() public view returns(uint256) {
if(_MAX_NFT_AMOUNT_ < _TOKEN_IDS_.length) { if(_MAX_NFT_AMOUNT_ < _NFT_IDS_.length) {
return 0; return 0;
}else { }else {
return _MAX_NFT_AMOUNT_ - _TOKEN_IDS_.length; return _MAX_NFT_AMOUNT_ - _NFT_IDS_.length;
} }
} }
function getAvaliableNFTOut() public view returns(uint256) { function getAvaliableNFTOut() public view returns(uint256) {
if(_TOKEN_IDS_.length < _MIN_NFT_AMOUNT_) { if(_NFT_IDS_.length < _MIN_NFT_AMOUNT_) {
return 0; return 0;
}else { }else {
return _TOKEN_IDS_.length - _MIN_NFT_AMOUNT_; return _NFT_IDS_.length - _MIN_NFT_AMOUNT_;
} }
} }
function queryNFTIn(uint256 NFTInAmount) external view returns (uint256 rawReceive, uint256 receive) { function getNFTIndexById(uint256 tokenId) public view returns(uint256) {
uint256 i = 0;
for(; i < _NFT_IDS_.length; i++) {
if(_NFT_IDS_[i] == tokenId) break;
}
require(i < _NFT_IDS_.length, "TOKEN_ID_NOT_EXSIT");
return i;
}
function queryNFTIn(uint256 NFTInAmount) public view returns (uint256 rawReceive, uint256 received) {
require(NFTInAmount <= getAvaliableNFTIn(), "EXCEDD_IN_AMOUNT"); require(NFTInAmount <= getAvaliableNFTIn(), "EXCEDD_IN_AMOUNT");
rawReceive = geometricCalc(_GS_START_IN_, _CR_IN_, _NFT_AMOUNT_, _NFT_AMOUNT_+NFTInAmount); uint256 nftAmount = _NFT_IDS_.length;
receive = IFilterAdmin(_OWNER_).queryChargeMintFee(rawReceive); rawReceive = geometricCalc(_GS_START_IN_, _CR_IN_, nftAmount, nftAmount + NFTInAmount);
(uint256 poolFee, uint256 mtFee) = IFilterAdmin(_OWNER_).queryChargeMintFee(rawReceive);
received = rawReceive.sub(poolFee).sub(mtFee);
} }
function queryNFTTargetOut(uint256 NFTOutAmount) external view returns (uint256 rawPay, uint256 pay) { function queryNFTTargetOut(uint256 NFTOutAmount) public view returns (uint256 rawPay, uint256 pay) {
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT"); require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
rawPay = geometricCalc(_GS_START_TARGET_OUT_,_CR_TARGET_OUT_, _NFT_AMOUNT_-NFTOutAmount,_NFT_AMOUNT_); uint256 nftAmount = _NFT_IDS_.length;
pay = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay); rawPay = geometricCalc(_GS_START_TARGET_OUT_,_CR_TARGET_OUT_, nftAmount - NFTOutAmount, nftAmount);
(uint256 poolFee, uint256 mtFee) = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay);
pay = rawPay.add(poolFee).add(mtFee);
} }
function queryNFTRandomOut(uint256 NFTOutAmount) external view returns (uint256 rawPay, uint256 pay) { function queryNFTRandomOut(uint256 NFTOutAmount) public view returns (uint256 rawPay, uint256 pay) {
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT"); require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
rawPay = geometricCalc(_GS_START_RANDOM_OUT_,_CR_RANDOM_OUT_, _NFT_AMOUNT_-NFTOutAmount,_NFT_AMOUNT_); uint256 nftAmount = _NFT_IDS_.length;
pay = IFilterAdmin(_OWNER_).chargeBurnFee(rawPay); rawPay = geometricCalc(_GS_START_RANDOM_OUT_,_CR_RANDOM_OUT_, nftAmount - NFTOutAmount, nftAmount);
(uint256 poolFee, uint256 mtFee) = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay);
pay = rawPay.add(poolFee).add(mtFee);
} }
// ================= Trading ================ // ================= Trading ================
function ERC721In(uint256[] memory tokenIds, address to) external preventReentrant returns(uint256 received) { function ERC721In(uint256[] memory tokenIds, address to) external preventReentrant returns(uint256 received) {
for (uint256 i = 0; i < tokenIds.length; i++) { for (uint256 i = 0; i < tokenIds.length; i++) {
require(!_NFT_RESERVE_[tokenIds[i]] && IERC721(_NFT_COLLECTION_).ownerOf(tokenIds[i])==address(this), "NFT_NOT_SEND"); require(_NFT_RESERVE_[tokenIds[i]] == 0 && IERC721(_NFT_COLLECTION_).ownerOf(tokenIds[i])==address(this), "NFT_NOT_SEND");
_NFT_IDS_.push(tokenId); _NFT_IDS_.push(tokenIds[i]);
_NFT_RESERVE_[tokenIds[i]] = 1; _NFT_RESERVE_[tokenIds[i]] = 1;
} }
(uint256 rawReceive,) = queryNFTIn(tokenIds.length); (uint256 rawReceive,) = queryNFTIn(tokenIds.length);
@@ -124,7 +156,7 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
} }
function ERC721TargetOut(uint256[] memory indexes, address to) external preventReentrant returns(uint256 paid) { function ERC721TargetOut(uint256[] memory indexes, address to) external preventReentrant returns(uint256 paid) {
(uint256 rawPay, ) = queryNFTOut(tokenIds.length); (uint256 rawPay, ) = queryNFTTargetOut(indexes.length);
paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay); paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay);
for (uint256 i = 0; i < indexes.length; i++) { for (uint256 i = 0; i < indexes.length; i++) {
_transferOutERC721(to, indexes[i]); _transferOutERC721(to, indexes[i]);
@@ -132,7 +164,7 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
} }
function ERC721RandomOut(uint256 amount, address to) external preventReentrant returns (uint256 paid) { function ERC721RandomOut(uint256 amount, address to) external preventReentrant returns (uint256 paid) {
(uint256 rawPay, ) = queryNFTOut(amount); (uint256 rawPay, ) = queryNFTRandomOut(amount);
paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay); paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay);
for (uint256 i = 0; i < amount; i++) { for (uint256 i = 0; i < amount; i++) {
_transferOutERC721(to, getRandomOutId()); _transferOutERC721(to, getRandomOutId());
@@ -144,18 +176,18 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
function onERC721Received( function onERC721Received(
address, address,
address, address,
uint256 tokenId, uint256,
bytes calldata bytes calldata
) external override returns (bytes4) { ) external override returns (bytes4) {
return IERC721Receiver.onERC721Received.selector; return IERC721Receiver.onERC721Received.selector;
} }
function _transferOutERC721(address to, uint256 index) internal { function _transferOutERC721(address to, uint256 index) internal {
require(index<_TOKEN_IDS_.length, "INDEX_NOT_EXIST"); require(index < _NFT_IDS_.length, "INDEX_NOT_EXIST");
uint256 tokenId = _TOKEN_IDS_[index]; uint256 tokenId = _NFT_IDS_[index];
IERC721(_NFT_COLLECTION_).safeTransfer(to, tokenId); IERC721(_NFT_COLLECTION_).safeTransferFrom(address(this), to, tokenId);
_TOKEN_IDS_[index] = _TOKEN_IDS_[_TOKEN_IDS_.length - 1]; _NFT_IDS_[index] = _NFT_IDS_[_NFT_IDS_.length - 1];
_TOKEN_IDS_.pop(); _NFT_IDS_.pop();
_NFT_RESERVE_[tokenId] = 0; _NFT_RESERVE_[tokenId] = 0;
} }
@@ -166,89 +198,115 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
require(IControllerModel(controllerModel).getEmergencySwitch(address(this)), "NOT_OPEN"); require(IControllerModel(controllerModel).getEmergencySwitch(address(this)), "NOT_OPEN");
for(uint256 i = 0; i< nftContract.length; i++) { for(uint256 i = 0; i< nftContract.length; i++) {
if(_NFT_RESERVE_[tokenIds[i]] && nftContract[i]==_NFT_COLLECTION_){ if(_NFT_RESERVE_[tokenIds[i]] == 1 && nftContract[i] == _NFT_COLLECTION_){
uint256 index = getNFTIndex(tokenIds[i]); uint256 index = getNFTIndexById(tokenIds[i]);
_TOKEN_IDS_[index] = _TOKEN_IDS_[_TOKEN_IDS_.length - 1]; _NFT_IDS_[index] = _NFT_IDS_[_NFT_IDS_.length - 1];
_TOKEN_IDS_.pop(); _NFT_IDS_.pop();
_NFT_RESERVE_[tokenId] = 0; _NFT_RESERVE_[tokenIds[i]] = 0;
} }
IERC721(nftContract[i]).safeTransfer(to, tokenId); IERC721(nftContract[i]).safeTransferFrom(address(this), to, tokenIds[i]);
} }
} }
// ============ Math ============= // ============ Math =============
function geometricCalc(uint256 base, uint256 ratio, uint256 times) internal view returns(uint256 newBase, uint256 sum) { function geometricCalc(uint256 a1, uint256 q, uint256 start, uint256 end) internal view returns(uint256) {
sum = 0; //Sn=a1*(q^n-1)/(q-1)
for(uint256 i = 0; i < times; i++) { //Sn-Sm = a1*(q^n-q^m)/(q-1)
base = DecimalMath.mulFloor(base, ratio);
sum = sum.add(base); //q^n
} uint256 qn = DecimalMath.powFloor(q, end);
newBase = base; //q^m
uint256 qm = DecimalMath.powFloor(q, start);
return a1.mul(qn.sub(qm)).div(q.sub(DecimalMath.ONE));
} }
function getRandomOutId() external view returns (uint256 index) { function getRandomOutId() public view returns (uint256 index) {
uint256 nftAmount = _TOKEN_IDS_.length; uint256 nftAmount = _NFT_IDS_.length;
index = uint256(keccak256(abi.encodePacked(tx.origin, blockhash(block.number-1), gasleft()))) % nftAmount; index = uint256(keccak256(abi.encodePacked(tx.origin, blockhash(block.number-1), gasleft()))) % nftAmount;
} }
// ================= Ownable ================ // ================= Ownable ================
function changeNFTInPrice(uint256 newGsStart, uint256 newCr, bool switch) external { function changeNFTInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) external {
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED"); require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
if (!switch) { _changeNFTInPrice(newGsStart, newCr, switchFlag);
}
function _changeNFTInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) internal {
if (!switchFlag) {
_NFT_IN_SWITCH_ = false; _NFT_IN_SWITCH_ = false;
} else { } else {
require(newCr>DecimalMath.ONE, "CR_ZERO"); require(newCr > DecimalMath.ONE, "CR_INVALID");
_GS_START_IN_ = newGsStart; _GS_START_IN_ = newGsStart;
_CR_IN_ = newCr; _CR_IN_ = newCr;
_NFT_IN_SWITCH_ = true; _NFT_IN_SWITCH_ = true;
} }
} }
function changeNFTRandomInPrice(uint256 newGsStart, uint256 newCr, bool switch) external { function changeNFTRandomInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) external {
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED"); require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
if (!switch) { _changeNFTRandomInPrice(newGsStart, newCr, switchFlag);
_NFT_RANDOM_OUT_SWITCH_ = false; }
function _changeNFTRandomInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) internal {
if (!switchFlag) {
_NFT_RANDOM_SWITCH_ = false;
} else { } else {
require(newCr>DecimalMath.ONE, "CR_ZERO"); require(newCr > DecimalMath.ONE, "CR_INVALID");
_GS_START_RANDOM_OUT_ = newGsStart; _GS_START_RANDOM_OUT_ = newGsStart;
_CR_RANDOM_OUT_ = newCr; _CR_RANDOM_OUT_ = newCr;
_NFT_RANDOM_OUT_SWITCH_ = true; _NFT_RANDOM_SWITCH_ = true;
} }
} }
function changeNFTTargetOutPrice(uint256 newGsStart, uint256 newCr, bool switch) external { function changeNFTTargetOutPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) external {
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED"); require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
if (!switch) { _changeNFTTargetOutPrice(newGsStart, newCr, switchFlag);
_NFT_TARGET_OUT_SWITCH_ = false; }
function _changeNFTTargetOutPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) internal {
if (!switchFlag) {
_NFT_TARGET_SWITCH_ = false;
} else { } else {
require(newCr>DecimalMath.ONE, "CR_ZERO"); require(newCr > DecimalMath.ONE, "CR_INVALID");
_GS_START_TARGET_OUT_ = newGsStart; _GS_START_TARGET_OUT_ = newGsStart;
_CR_TARGET_OUT_ = newCr; _CR_TARGET_OUT_ = newCr;
_NFT_TARGET_OUT_SWITCH_ = true; _NFT_TARGET_SWITCH_ = true;
} }
} }
function changeNFTAmount(uint256 maxNFTAmount, uint256 minNFTAmount) external { function changeNFTAmount(uint256 maxNFTAmount, uint256 minNFTAmount) external {
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED"); require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
_changeNFTAmount(maxNFTAmount, minNFTAmount);
}
function _changeNFTAmount(uint256 maxNFTAmount, uint256 minNFTAmount) internal {
require(maxNFTAmount >= minNFTAmount, "AMOUNT_INVALID"); require(maxNFTAmount >= minNFTAmount, "AMOUNT_INVALID");
_MAX_NFT_AMOUNT_ = maxNFTAmount; _MAX_NFT_AMOUNT_ = maxNFTAmount;
_MIN_NFT_AMOUNT_ = minNFTAmount; _MIN_NFT_AMOUNT_ = minNFTAmount;
} }
function changeTokenIdRange(uint256 tokenIdStart, uint256 tokenIdEnd) external { function changeTokenIdRange(uint256 nftIdStart, uint256 nftIdEnd) external {
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED"); require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
require(tokenIdStart <= tokenIdEnd, "TOKEN_RANGE_INVALID"); _changeTokenIdRange(nftIdStart, nftIdEnd);
}
function _changeTokenIdRange(uint256 nftIdStart, uint256 nftIdEnd) internal {
require(nftIdStart <= nftIdEnd, "TOKEN_RANGE_INVALID");
_TOKEN_ID_START_ = tokenIdStart; _NFT_ID_START_ = nftIdStart;
_TOKEN_ID_END_ = tokenIdEnd; _NFT_ID_END_ = nftIdEnd;
} }
function changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistrieds) external { function changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistrieds) external {
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED"); require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
_changeTokenIdMap(tokenIds, isRegistrieds);
}
function _changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistrieds) internal {
require(tokenIds.length == isRegistrieds.length, "PARAM_NOT_MATCH"); require(tokenIds.length == isRegistrieds.length, "PARAM_NOT_MATCH");
for(uint256 i = 0; i < tokenIds.length; i++) { for(uint256 i = 0; i < tokenIds.length; i++) {
@@ -262,42 +320,8 @@ contract FilterModel01 is InitializableOwnable, IERC721Receiver {
return interfaceId == type(IERC721Receiver).interfaceId; return interfaceId == type(IERC721Receiver).interfaceId;
} }
function version() virtual external pure returns (string memory) { function version() virtual external pure returns (string memory) {
return "FILTER_1_ERC721 1.0.0"; 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;
}
}
} }

View File

@@ -8,11 +8,9 @@
pragma solidity 0.6.9; pragma solidity 0.6.9;
interface IControllerModel { interface IControllerModel {
function getNFTInFee(address filterAdminAddr, address user) external view returns(uint256); function getMintFee(address filterAdminAddr) external view returns (uint256);
function getNFTRandomOutFee(address filterAdminAddr, address user) external view returns(uint256); function getBurnFee(address filterAdminAddr) external view returns (uint256);
function getNFTTargetOutFee(address filterAdminAddr, address user) external view returns(uint256); function getEmergencySwitch(address filter) external view returns (bool);
function getEmergencySwitch(address filter) external view returns(bool);
} }

View File

@@ -13,27 +13,21 @@ interface IFilterAdmin {
function _CONTROLLER_MODEL_() external returns (address); function _CONTROLLER_MODEL_() external returns (address);
function init( function init(
address _owner, address owner,
string memory _name, uint256 initSupply,
string memory _symbol, string memory name,
string memory symbol,
uint256 fee, uint256 fee,
address mtFeeModel, address mtFeeModel,
address defaultMaintainer, address defaultMaintainer,
address[] memory filters address[] memory filters
) external; ) external;
function ERC721In( function mintFragTo(address to, uint256 rawAmount) external returns (uint256 received);
address filter,
address nftContract,
uint256[] memory tokenIds,
uint256 minMintAmount
) external returns (uint256 actualMintAmount);
function mintFragTo(address to, uint256 rawAmount) external; function burnFragFrom(address from, uint256 rawAmount) external returns (uint256 paid);
function burnFragFrom(address from, uint256 rawAmount) external; function queryChargeMintFee(uint256 rawAmount) external view returns (uint256 poolFee, uint256 mtFee);
function queryChargeMintFee(uint256 rawAmount) external; function queryChargeBurnFee(uint256 rawAmount) external view returns (uint256 poolFee, uint256 mtFee);
function queryChargeBurnFee(uint256 rawAmount) external;
} }

View File

@@ -8,35 +8,21 @@
pragma solidity 0.6.9; pragma solidity 0.6.9;
interface IFilterModel { interface IFilterModel {
function isFilterERC721Pass(address nftCollectionAddress, uint256 nftId) external view returns (bool); function isNFTValid(address nftCollectionAddress, uint256 nftId) external view returns (bool);
function _NFT_COLLECTION_() external view returns(address);
function isFilterERC1155Pass(address nftCollectionAddress, uint256 nftId, uint256 amount) external view returns (bool); function queryNFTIn(uint256 NFTInAmount) external view returns (uint256 rawReceive, uint256 received);
function getAvaliableNFTIn() external view returns(uint256); function queryNFTTargetOut(uint256 NFTOutAmount) external view returns (uint256 rawPay, uint256 pay);
function getAvaliableNFTOut() external view returns(uint256); function queryNFTRandomOut(uint256 NFTOutAmount) external view returns (uint256 rawPay, uint256 pay);
function _NFT_IN_SWITCH_() external view returns(bool); function ERC721In(uint256[] memory tokenIds, address to) external returns(uint256 received);
function _NFT_RANDOM_SWITCH_() external view returns(bool); function ERC721TargetOut(uint256[] memory indexes, address to) external returns(uint256 paid);
function _NFT_TARGET_SWITCH_() external view returns(bool); function ERC721RandomOut(uint256 amount, address to) external returns (uint256 paid);
function getNFTInPrice(address nftCollectionAddress, uint256 nftId) external view returns (uint256);
function getNFTRandomOutPrice() external view returns (uint256);
function getNFTTargetOutPrice(address nftCollectionAddress, uint256 nftId) external view returns (uint256);
function getRandomOutId() external view returns (address nftCollection, uint256 nftId);
function transferOutERC721(address nftContract, address assetTo, uint256 nftId) external;
function transferInERC721(address nftContract, address assetFrom, uint256 nftId) external;
function transferOutERC1155(address nftContract, address assetTo, uint256 nftId, uint256 amount) external;
function transferBatchOutERC1155(address nftContract, address assetTo, uint256[] memory nftIds, uint256[] memory amounts) external;
function transferBatchInERC1155(address nftContract, address assetFrom, uint256[] memory nftIds, uint256[] memory amounts) external;
} }

View File

@@ -0,0 +1,103 @@
/*
Copyright 2021 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
import {IERC721} from "../intf/IERC721.sol";
import {IERC1155} from "../intf/IERC1155.sol";
import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
/**
* @title DODONFTApprove
* @author DODO Breeder
*
* @notice Handle NFT authorizations in DODO platform
*/
contract DODONFTApprove is InitializableOwnable {
// ============ Storage ============
uint256 private constant _TIMELOCK_DURATION_ = 3 days;
mapping (address => bool) public _IS_ALLOWED_PROXY_;
uint256 public _TIMELOCK_;
address public _PENDING_ADD_DODO_PROXY_;
// ============ Events ============
event AddDODOProxy(address dodoProxy);
// ============ Modifiers ============
modifier notLocked() {
require(
_TIMELOCK_ <= block.timestamp,
"SetProxy is timelocked"
);
_;
}
function init(address owner, address[] memory proxies) external {
initOwner(owner);
for(uint i = 0; i < proxies.length; i++)
_IS_ALLOWED_PROXY_[proxies[i]] = true;
}
function unlockAddProxy(address newDodoProxy) public onlyOwner {
_TIMELOCK_ = block.timestamp + _TIMELOCK_DURATION_;
_PENDING_ADD_DODO_PROXY_ = newDodoProxy;
}
function lockAddProxy() public onlyOwner {
_PENDING_ADD_DODO_PROXY_ = address(0);
_TIMELOCK_ = 0;
}
function addDODOProxy() external onlyOwner notLocked() {
_IS_ALLOWED_PROXY_[_PENDING_ADD_DODO_PROXY_] = true;
lockAddProxy();
emit AddDODOProxy(_PENDING_ADD_DODO_PROXY_);
}
function removeDODOProxy (address oldDodoProxy) public onlyOwner {
_IS_ALLOWED_PROXY_[oldDodoProxy] = false;
}
function claimERC721(
address nftContract,
address who,
address dest,
uint256 tokenId
) external {
require(_IS_ALLOWED_PROXY_[msg.sender], "DODONFTApprove:Access restricted");
IERC721(nftContract).safeTransferFrom(who, dest, tokenId);
}
function claimERC1155(
address nftContract,
address who,
address dest,
uint256 tokenId,
uint256 amount
) external {
require(_IS_ALLOWED_PROXY_[msg.sender], "DODONFTApprove:Access restricted");
IERC1155(nftContract).safeTransferFrom(who, dest, tokenId, amount, "");
}
function claimERC1155Batch(
address nftContract,
address who,
address dest,
uint256[] memory tokenIds,
uint256[] memory amounts
) external {
require(_IS_ALLOWED_PROXY_[msg.sender], "DODONFTApprove:Access restricted");
IERC1155(nftContract).safeBatchTransferFrom(who, dest, tokenIds, amounts, "");
}
function isAllowedProxy(address _proxy) external view returns (bool) {
return _IS_ALLOWED_PROXY_[_proxy];
}
}

View File

@@ -9,12 +9,13 @@ import {SafeMath} from "../../lib/SafeMath.sol";
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
import {ICloneFactory} from "../../lib/CloneFactory.sol"; import {ICloneFactory} from "../../lib/CloneFactory.sol";
import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol"; import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol";
import {IFilterModel} from "../../NFTPool/intf/IFilterModel.sol";
import {IFilterAdmin} from "../../NFTPool/intf/IFilterAdmin.sol"; import {IFilterAdmin} from "../../NFTPool/intf/IFilterAdmin.sol";
import {IERC721} from "../../intf/IERC721.sol"; import {IDODONFTApprove} from "../../intf/IDODONFTApprove.sol";
import {IERC20} from "../../intf/IERC20.sol"; import {IERC20} from "../../intf/IERC20.sol";
import {SafeERC20} from "../../lib/SafeERC20.sol"; import {SafeERC20} from "../../lib/SafeERC20.sol";
interface IFilter01 { interface IFilterERC721V1 {
function init( function init(
address filterAdmin, address filterAdmin,
address nftCollection, address nftCollection,
@@ -35,8 +36,10 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable {
mapping(uint256 => address) public _FILTER_TEMPLATES_; mapping(uint256 => address) public _FILTER_TEMPLATES_;
address public _FILTER_ADMIN_TEMPLATE_; address public _FILTER_ADMIN_TEMPLATE_;
address public _DEFAULT_MAINTAINER_; address public _DEFAULT_MAINTAINER_;
address public _NFT_POOL_FEE_MODEL_; address public _CONTROLLER_MODEL_;
address public immutable _CLONE_FACTORY_; address public immutable _CLONE_FACTORY_;
address public immutable _DODO_NFT_APPROVE_;
address public immutable _DODO_APPROVE_;
// ============ Event ============== // ============ Event ==============
@@ -45,16 +48,60 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable {
constructor( constructor(
address cloneFactory, address cloneFactory,
address filterAdminTemplate, address filterAdminTemplate,
address nftPoolFeeModel, address controllerModel,
address defaultMaintainer address defaultMaintainer,
address dodoNftApprove,
address dodoApprove
) public { ) public {
_CLONE_FACTORY_ = cloneFactory; _CLONE_FACTORY_ = cloneFactory;
_FILTER_ADMIN_TEMPLATE_ = filterAdminTemplate; _FILTER_ADMIN_TEMPLATE_ = filterAdminTemplate;
_NFT_POOL_FEE_MODEL_ = nftPoolFeeModel; _CONTROLLER_MODEL_ = controllerModel;
_DEFAULT_MAINTAINER_ = defaultMaintainer; _DEFAULT_MAINTAINER_ = defaultMaintainer;
_DODO_NFT_APPROVE_ = dodoNftApprove;
_DODO_APPROVE_ = dodoApprove;
} }
// ================ NFT In and Out ===================
function nftIn(
address filter,
address nftCollection,
uint256[] memory tokenIds,
address to,
uint256 minMintAmount
) external {
for(uint256 i = 0; i < tokenIds.length; i++) {
require(IFilterModel(filter).isNFTValid(nftCollection,tokenIds[i]), "NOT_REGISTRIED");
IDODONFTApprove(_DODO_NFT_APPROVE_).claimERC721(nftCollection, msg.sender, filter, tokenIds[i]);
}
uint256 received = IFilterModel(filter).ERC721In(tokenIds, to);
require(received >= minMintAmount, "MINT_AMOUNT_NOT_ENOUGH");
}
function nftTargetOut(
address filter,
uint256[] memory indexes,
address to,
uint256 maxBurnAmount
) external {
uint256 paid = IFilterModel(filter).ERC721TargetOut(indexes, to);
require(paid <= maxBurnAmount, "BURN_AMOUNT_EXCEED");
}
function nftRandomOut(
address filter,
uint256 amount,
address to,
uint256 maxBurnAmount
) external {
uint256 paid = IFilterModel(filter).ERC721RandomOut(amount, to);
require(paid <= maxBurnAmount, "BURN_AMOUNT_EXCEED");
}
// ================== Create NFTPool ===================
function createNewNFTPool01( function createNewNFTPool01(
uint256 initSupply,
string memory name, string memory name,
string memory symbol, string memory symbol,
uint256 fee, uint256 fee,
@@ -67,7 +114,7 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable {
) external returns(address newFilterAdmin) { ) external returns(address newFilterAdmin) {
newFilterAdmin = ICloneFactory(_CLONE_FACTORY_).clone(_FILTER_ADMIN_TEMPLATE_); newFilterAdmin = ICloneFactory(_CLONE_FACTORY_).clone(_FILTER_ADMIN_TEMPLATE_);
address filter01 = createFilter01( address filter01 = createFilterERC721V1(
newFilterAdmin, newFilterAdmin,
nftCollection, nftCollection,
switches, switches,
@@ -82,16 +129,19 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable {
IFilterAdmin(newFilterAdmin).init( IFilterAdmin(newFilterAdmin).init(
msg.sender, msg.sender,
initSupply,
name, name,
symbol, symbol,
fee, fee,
_NFT_POOL_FEE_MODEL_, _CONTROLLER_MODEL_,
_DEFAULT_MAINTAINER_, _DEFAULT_MAINTAINER_,
filters filters
); );
} }
function createFilter01(
// ================== Create Filter ===================
function createFilterERC721V1(
address filterAdmin, address filterAdmin,
address nftCollection, address nftCollection,
bool[] memory switches, bool[] memory switches,
@@ -99,34 +149,42 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable {
uint256[] memory nftAmounts, uint256[] memory nftAmounts,
uint256[] memory priceRules, uint256[] memory priceRules,
uint256[] memory spreadIds uint256[] memory spreadIds
) public returns(address newFilter01) { ) public returns(address newFilterERC721V1) {
newFilter01 = ICloneFactory(_CLONE_FACTORY_).clone(_FILTER_TEMPLATES_[1]); //key = 1 => FilterERC721V1
IFilter01(newFilter01).init(filterAdmin, nftCollection, switches, tokenRanges, nftAmounts, priceRules, spreadIds); newFilterERC721V1 = ICloneFactory(_CLONE_FACTORY_).clone(_FILTER_TEMPLATES_[1]);
IFilterERC721V1(newFilterERC721V1).init(
filterAdmin,
nftCollection,
switches,
tokenRanges,
nftAmounts,
priceRules,
spreadIds
);
} }
// ================== NFT ERC20 Swap ======================
function erc721ToErc20( function erc721ToErc20(
address filterAdmin, address filterAdmin,
address filter, address filter,
address nftContract, address nftContract,
uint256 tokenId, uint256 tokenId,
address toToken, address toToken,
address dodoApprove,
address dodoProxy, address dodoProxy,
bytes memory dodoSwapData bytes memory dodoSwapData
) )
external external
preventReentrant preventReentrant
{ {
IERC721(nftContract).safeTransferFrom(msg.sender, address(this), tokenId); IDODONFTApprove(_DODO_NFT_APPROVE_).claimERC721(nftContract, msg.sender, filter, tokenId);
IERC721(nftContract).approve(filter, tokenId);
uint256[] memory tokenIds = new uint256[](1); uint256[] memory tokenIds = new uint256[](1);
tokenIds[0] = tokenId; tokenIds[0] = tokenId;
//TODO: uint256 receivedFragAmount = IFilterModel(filter).ERC721In(tokenIds, address(this));
uint256 mintAmount = IFilterAdmin(filterAdmin).ERC721In(filter, nftContract, tokenIds, 0);
_generalApproveMax(filterAdmin, dodoApprove, mintAmount); _generalApproveMax(filterAdmin, _DODO_APPROVE_, receivedFragAmount);
(bool success, ) = dodoProxy.call(dodoSwapData); (bool success, ) = dodoProxy.call(dodoSwapData);
require(success, "API_SWAP_FAILED"); require(success, "API_SWAP_FAILED");
@@ -146,8 +204,8 @@ contract DODONFTPoolProxy is ReentrancyGuard, InitializableOwnable {
_FILTER_ADMIN_TEMPLATE_ = newFilterAdminTemplate; _FILTER_ADMIN_TEMPLATE_ = newFilterAdminTemplate;
} }
function changeNftPoolFeeModel(address newNftPoolFeeModel) external onlyOwner { function changeControllerModel(address newControllerModel) external onlyOwner {
_NFT_POOL_FEE_MODEL_ = newNftPoolFeeModel; _CONTROLLER_MODEL_ = newControllerModel;
} }
function setFilterTemplate(uint256 idx, address newFilterTemplate) external onlyOwner { function setFilterTemplate(uint256 idx, address newFilterTemplate) external onlyOwner {

View File

@@ -0,0 +1,18 @@
/*
Copyright 2021 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
interface IDODONFTApprove {
function isAllowedProxy(address _proxy) external view returns (bool);
function claimERC721(address nftContract, address who, address dest, uint256 tokenId) external;
function claimERC1155(address nftContract, address who, address dest, uint256 tokenId, uint256 amount) external;
function claimERC1155Batch(address nftContract, address who, address dest, uint256[] memory tokenIds, uint256[] memory amounts) external;
}