some changes & rename
This commit is contained in:
@@ -18,83 +18,151 @@ contract BaseFilterV1 is InitializableOwnable, ReentrancyGuard {
|
||||
//=================== Storage ===================
|
||||
address public _NFT_COLLECTION_;
|
||||
uint256 public _NFT_ID_START_;
|
||||
uint256 public _NFT_ID_END_;
|
||||
|
||||
uint256 public _NFT_ID_END_ = uint256(-1);
|
||||
|
||||
//tokenId => isRegistered
|
||||
mapping(uint256 => bool) public _SPREAD_IDS_REGISTRY_;
|
||||
|
||||
//tokenId => amount
|
||||
mapping(uint256 => uint256) public _NFT_RESERVE_;
|
||||
|
||||
uint256[] public _NFT_IDS_;
|
||||
|
||||
uint256 public _TOTAL_NFT_AMOUNT_;
|
||||
uint256 public _MAX_NFT_AMOUNT_;
|
||||
uint256 public _MIN_NFT_AMOUNT_;
|
||||
|
||||
// GS -> Geometric sequence
|
||||
// CR -> Common Ratio
|
||||
|
||||
//For NFT IN
|
||||
//For Deposit NFT INto Pool
|
||||
uint256 public _GS_START_IN_;
|
||||
uint256 public _CR_IN_;
|
||||
bool public _NFT_IN_SWITCH_ = false;
|
||||
|
||||
//For NFT Random OUT
|
||||
bool public _NFT_IN_TOGGLE_ = false;
|
||||
|
||||
//For NFT Random OUT from Pool
|
||||
uint256 public _GS_START_RANDOM_OUT_;
|
||||
uint256 public _CR_RANDOM_OUT_;
|
||||
bool public _NFT_RANDOM_SWITCH_ = false;
|
||||
bool public _NFT_RANDOM_OUT_TOGGLE_ = false;
|
||||
|
||||
//For NFT Target OUT
|
||||
//For NFT Target OUT from Pool
|
||||
uint256 public _GS_START_TARGET_OUT_;
|
||||
uint256 public _CR_TARGET_OUT_;
|
||||
bool public _NFT_TARGET_SWITCH_ = false;
|
||||
bool public _NFT_TARGET_OUT_TOGGLE_ = false;
|
||||
|
||||
modifier onlySuperOwner() {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ONLY_SUPER_OWNER");
|
||||
_;
|
||||
}
|
||||
|
||||
//==================== Query ==================
|
||||
//==================== Query Prop ==================
|
||||
|
||||
function isNFTValid(address nftCollectionAddress, uint256 nftId) external view returns (bool) {
|
||||
if(nftCollectionAddress == _NFT_COLLECTION_) {
|
||||
if (nftCollectionAddress == _NFT_COLLECTION_) {
|
||||
return isNFTIDValid(nftId);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isNFTIDValid(uint256 nftId) public view returns(bool){
|
||||
if((nftId >= _NFT_ID_START_ && nftId <= _NFT_ID_END_) || _SPREAD_IDS_REGISTRY_[nftId]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
function isNFTIDValid(uint256 nftId) public view returns (bool) {
|
||||
return (nftId >= _NFT_ID_START_ && nftId <= _NFT_ID_END_) || _SPREAD_IDS_REGISTRY_[nftId];
|
||||
}
|
||||
|
||||
function getAvaliableNFTIn() public view returns(uint256) {
|
||||
if(_MAX_NFT_AMOUNT_ <= _NFT_IDS_.length) {
|
||||
function getAvaliableNFTInAmount() public view returns (uint256) {
|
||||
if (_MAX_NFT_AMOUNT_ <= _TOTAL_NFT_AMOUNT_) {
|
||||
return 0;
|
||||
}else {
|
||||
return _MAX_NFT_AMOUNT_ - _NFT_IDS_.length;
|
||||
} else {
|
||||
return _MAX_NFT_AMOUNT_ - _TOTAL_NFT_AMOUNT_;
|
||||
}
|
||||
}
|
||||
|
||||
function getAvaliableNFTOut() public view returns(uint256) {
|
||||
if(_NFT_IDS_.length <= _MIN_NFT_AMOUNT_) {
|
||||
function getAvaliableNFTOutAmount() public view returns (uint256) {
|
||||
if (_TOTAL_NFT_AMOUNT_ <= _MIN_NFT_AMOUNT_) {
|
||||
return 0;
|
||||
}else {
|
||||
return _NFT_IDS_.length - _MIN_NFT_AMOUNT_;
|
||||
} else {
|
||||
return _TOTAL_NFT_AMOUNT_ - _MIN_NFT_AMOUNT_;
|
||||
}
|
||||
}
|
||||
|
||||
function getNFTIndexById(uint256 tokenId) public view returns(uint256) {
|
||||
function getNFTIndexById(uint256 tokenId) public view returns (uint256) {
|
||||
uint256 i = 0;
|
||||
for(; i < _NFT_IDS_.length; i++) {
|
||||
if(_NFT_IDS_[i] == tokenId) break;
|
||||
for (; i < _NFT_IDS_.length; i++) {
|
||||
if (_NFT_IDS_[i] == tokenId) break;
|
||||
}
|
||||
require(i < _NFT_IDS_.length, "TOKEN_ID_NOT_EXSIT");
|
||||
return i;
|
||||
}
|
||||
|
||||
//==================== Query Price ==================
|
||||
|
||||
function queryNFTIn(uint256 NFTInAmount)
|
||||
public
|
||||
view
|
||||
returns (
|
||||
uint256 received,
|
||||
uint256 poolFee,
|
||||
uint256 mtFee
|
||||
)
|
||||
{
|
||||
require(NFTInAmount <= getAvaliableNFTIn(), "EXCEDD_IN_AMOUNT");
|
||||
rawReceive = _geometricCalc(
|
||||
_GS_START_IN_,
|
||||
_CR_IN_,
|
||||
_TOTAL_NFT_AMOUNT_,
|
||||
_TOTAL_NFT_AMOUNT_ + NFTInAmount
|
||||
);
|
||||
(poolFee, mtFee, received) = IFilterAdmin(_OWNER_).queryChargeMintFee(rawReceive);
|
||||
}
|
||||
|
||||
function queryNFTTargetOut(uint256 NFTOutAmount)
|
||||
public
|
||||
view
|
||||
returns (
|
||||
uint256 paid,
|
||||
uint256 poolFee,
|
||||
uint256 mtFee
|
||||
)
|
||||
{
|
||||
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
|
||||
rawPay = _geometricCalc(
|
||||
_GS_START_TARGET_OUT_,
|
||||
_CR_TARGET_OUT_,
|
||||
_TOTAL_NFT_AMOUNT_ - NFTOutAmount,
|
||||
_TOTAL_NFT_AMOUNT_
|
||||
);
|
||||
(poolFee, mtFee, paid) = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay);
|
||||
}
|
||||
|
||||
function queryNFTRandomOut(uint256 NFTOutAmount)
|
||||
public
|
||||
view
|
||||
returns (
|
||||
uint256 paid,
|
||||
uint256 poolFee,
|
||||
uint256 mtFee
|
||||
)
|
||||
{
|
||||
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
|
||||
rawPay = _geometricCalc(
|
||||
_GS_START_RANDOM_OUT_,
|
||||
_CR_RANDOM_OUT_,
|
||||
_TOTAL_NFT_AMOUNT_ - NFTOutAmount,
|
||||
_TOTAL_NFT_AMOUNT_
|
||||
);
|
||||
(poolFee, mtFee, paid) = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay);
|
||||
}
|
||||
|
||||
// ============ Math =============
|
||||
|
||||
function _geometricCalc(uint256 a1, uint256 q, uint256 start, uint256 end) internal view returns(uint256) {
|
||||
function _geometricCalc(
|
||||
uint256 a1,
|
||||
uint256 q,
|
||||
uint256 start,
|
||||
uint256 end
|
||||
) internal view returns (uint256) {
|
||||
if (q == DecimalMath.ONE) {
|
||||
return end.sub(start).ml(a1);
|
||||
}
|
||||
//Sn=a1*(q^n-1)/(q-1)
|
||||
//Sn-Sm = a1*(q^n-q^m)/(q-1)
|
||||
|
||||
@@ -104,96 +172,110 @@ contract BaseFilterV1 is InitializableOwnable, ReentrancyGuard {
|
||||
uint256 qm = DecimalMath.powFloor(q, start);
|
||||
return a1.mul(qn.sub(qm)).div(q.sub(DecimalMath.ONE));
|
||||
}
|
||||
|
||||
function _getRandomOutId() public view returns (uint256 index) {
|
||||
uint256 nftAmount = _NFT_IDS_.length;
|
||||
index = uint256(keccak256(abi.encodePacked(tx.origin, blockhash(block.number-1), gasleft()))) % nftAmount;
|
||||
}
|
||||
|
||||
function _getRandomOutId() public view returns (uint256 index) {
|
||||
index =
|
||||
uint256(
|
||||
keccak256(abi.encodePacked(tx.origin, blockhash(block.number - 1), gasleft()))
|
||||
) %
|
||||
_TOTAL_NFT_AMOUNT_;
|
||||
}
|
||||
|
||||
// ================= Ownable ================
|
||||
|
||||
function changeNFTInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
_changeNFTInPrice(newGsStart, newCr, switchFlag);
|
||||
function changeNFTInPrice(
|
||||
uint256 newGsStart,
|
||||
uint256 newCr,
|
||||
bool toggleFlag
|
||||
) external onlySuperOwner {
|
||||
_changeNFTInPrice(newGsStart, newCr, toggleFlag);
|
||||
}
|
||||
|
||||
function _changeNFTInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) internal {
|
||||
if (!switchFlag) {
|
||||
_NFT_IN_SWITCH_ = false;
|
||||
} else {
|
||||
require(newCr > DecimalMath.ONE, "CR_INVALID");
|
||||
_GS_START_IN_ = newGsStart;
|
||||
_CR_IN_ = newCr;
|
||||
_NFT_IN_SWITCH_ = true;
|
||||
}
|
||||
function _changeNFTInPrice(
|
||||
uint256 newGsStart,
|
||||
uint256 newCr,
|
||||
bool toggleFlag
|
||||
) internal {
|
||||
require(newCr > DecimalMath.ONE, "CR_INVALID");
|
||||
_GS_START_IN_ = newGsStart;
|
||||
_CR_IN_ = newCr;
|
||||
_NFT_IN_TOGGLE_ = true;
|
||||
}
|
||||
|
||||
function changeNFTRandomInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
_changeNFTRandomInPrice(newGsStart, newCr, switchFlag);
|
||||
function changeNFTRandomInPrice(
|
||||
uint256 newGsStart,
|
||||
uint256 newCr,
|
||||
bool toggleFlag
|
||||
) external onlySuperOwner {
|
||||
_changeNFTRandomInPrice(newGsStart, newCr, toggleFlag);
|
||||
}
|
||||
|
||||
function _changeNFTRandomInPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) internal {
|
||||
if (!switchFlag) {
|
||||
_NFT_RANDOM_SWITCH_ = false;
|
||||
} else {
|
||||
require(newCr > DecimalMath.ONE, "CR_INVALID");
|
||||
_GS_START_RANDOM_OUT_ = newGsStart;
|
||||
_CR_RANDOM_OUT_ = newCr;
|
||||
_NFT_RANDOM_SWITCH_ = true;
|
||||
}
|
||||
function _changeNFTRandomInPrice(
|
||||
uint256 newGsStart,
|
||||
uint256 newCr,
|
||||
bool toggleFlag
|
||||
) internal {
|
||||
require(newCr > DecimalMath.ONE, "CR_INVALID");
|
||||
_GS_START_RANDOM_OUT_ = newGsStart;
|
||||
_CR_RANDOM_OUT_ = newCr;
|
||||
_NFT_RANDOM_OUT_TOGGLE_ = true;
|
||||
}
|
||||
|
||||
function changeNFTTargetOutPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
_changeNFTTargetOutPrice(newGsStart, newCr, switchFlag);
|
||||
function changeNFTTargetOutPrice(
|
||||
uint256 newGsStart,
|
||||
uint256 newCr,
|
||||
bool toggleFlag
|
||||
) external onlySuperOwner {
|
||||
_changeNFTTargetOutPrice(newGsStart, newCr, toggleFlag);
|
||||
}
|
||||
|
||||
function _changeNFTTargetOutPrice(uint256 newGsStart, uint256 newCr, bool switchFlag) internal {
|
||||
if (!switchFlag) {
|
||||
_NFT_TARGET_SWITCH_ = false;
|
||||
} else {
|
||||
require(newCr > DecimalMath.ONE, "CR_INVALID");
|
||||
_GS_START_TARGET_OUT_ = newGsStart;
|
||||
_CR_TARGET_OUT_ = newCr;
|
||||
_NFT_TARGET_SWITCH_ = true;
|
||||
}
|
||||
function _changeNFTTargetOutPrice(
|
||||
uint256 newGsStart,
|
||||
uint256 newCr,
|
||||
bool toggleFlag
|
||||
) internal {
|
||||
require(newCr > DecimalMath.ONE, "CR_INVALID");
|
||||
_GS_START_TARGET_OUT_ = newGsStart;
|
||||
_CR_TARGET_OUT_ = newCr;
|
||||
_NFT_TARGET_OUT_TOGGLE_ = true;
|
||||
}
|
||||
|
||||
function changeNFTAmount(uint256 maxNFTAmount, uint256 minNFTAmount) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
_changeNFTAmount(maxNFTAmount, minNFTAmount);
|
||||
function changeNFTAmountRange(uint256 maxNFTAmount, uint256 minNFTAmount)
|
||||
external
|
||||
onlySuperOwner
|
||||
{
|
||||
_changeNFTAmountRange(maxNFTAmount, minNFTAmount);
|
||||
}
|
||||
|
||||
function _changeNFTAmount(uint256 maxNFTAmount, uint256 minNFTAmount) internal {
|
||||
function _changeNFTAmountRange(uint256 maxNFTAmount, uint256 minNFTAmount) internal {
|
||||
require(maxNFTAmount >= minNFTAmount, "AMOUNT_INVALID");
|
||||
_MAX_NFT_AMOUNT_ = maxNFTAmount;
|
||||
_MIN_NFT_AMOUNT_ = minNFTAmount;
|
||||
}
|
||||
|
||||
function changeTokenIdRange(uint256 nftIdStart, uint256 nftIdEnd) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
function changeTokenIdRange(uint256 nftIdStart, uint256 nftIdEnd) external onlySuperOwner {
|
||||
_changeTokenIdRange(nftIdStart, nftIdEnd);
|
||||
}
|
||||
|
||||
function _changeTokenIdRange(uint256 nftIdStart, uint256 nftIdEnd) internal {
|
||||
require(nftIdStart <= nftIdEnd, "TOKEN_RANGE_INVALID");
|
||||
|
||||
|
||||
_NFT_ID_START_ = nftIdStart;
|
||||
_NFT_ID_END_ = nftIdEnd;
|
||||
}
|
||||
|
||||
function changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistrieds) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
_changeTokenIdMap(tokenIds, isRegistrieds);
|
||||
function changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistered)
|
||||
external
|
||||
onlySuperOwner
|
||||
{
|
||||
_changeTokenIdMap(tokenIds, isRegistered);
|
||||
}
|
||||
|
||||
function _changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistrieds) internal {
|
||||
require(tokenIds.length == isRegistrieds.length, "PARAM_NOT_MATCH");
|
||||
|
||||
for(uint256 i = 0; i < tokenIds.length; i++) {
|
||||
_SPREAD_IDS_REGISTRY_[tokenIds[i]] = isRegistrieds[i];
|
||||
function _changeTokenIdMap(uint256[] memory tokenIds, bool[] memory isRegistered) internal {
|
||||
require(tokenIds.length == isRegistered.length, "PARAM_NOT_MATCH");
|
||||
|
||||
for (uint256 i = 0; i < tokenIds.length; i++) {
|
||||
_SPREAD_IDS_REGISTRY_[tokenIds[i]] = isRegistered[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
79
contracts/NFTPool/impl/Controller.sol
Normal file
79
contracts/NFTPool/impl/Controller.sol
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
|
||||
contract Controller is InitializableOwnable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public _GLOBAL_NFT_IN_FEE_RATE_ = 0;
|
||||
uint256 public _GLOBAL_NFT_OUT_FEE_RATE_ = 0;
|
||||
|
||||
struct FilterAdminFeeRateInfo {
|
||||
uint256 nftInFeeRate;
|
||||
uint256 nftOutFeeRate;
|
||||
bool isOpen;
|
||||
}
|
||||
|
||||
mapping(address => FilterAdminFeeRateInfo) filterAdminFeeRates;
|
||||
|
||||
mapping(address => bool) public isEmergencyWithdrawOpen;
|
||||
|
||||
//==================== Event =====================
|
||||
event SetEmergencyWithdraw(address filter, bool isOpen);
|
||||
|
||||
//==================== Ownable ====================
|
||||
|
||||
function setFilterAdminFeeRateInfo(
|
||||
address filterAdminAddr,
|
||||
uint256 nftInFeeRate,
|
||||
uint256 nftOutFeeRate,
|
||||
bool isOpen
|
||||
) external onlyOwner {
|
||||
FilterAdminFeeRateInfo memory feeRateInfo = FilterAdminFeeRateInfo({
|
||||
nftInFeeRate: nftInFeeRate,
|
||||
nftOutFeeRate: nftOutFeeRate,
|
||||
isOpen: isOpen
|
||||
});
|
||||
filterAdminFeeRates[filterAdminAddr] = feeRateInfo;
|
||||
}
|
||||
|
||||
function setGlobalParam(uint256 nftInFeeRate, uint256 nftOutFeeRate) external onlyOwner {
|
||||
_GLOBAL_NFT_IN_FEE_RATE_ = nftInFeeRate;
|
||||
_GLOBAL_NFT_OUT_FEE_RATE_ = nftOutFeeRate;
|
||||
}
|
||||
|
||||
function setEmergencyWithdraw(address filter, bool isOpen) external onlyOwner {
|
||||
isEmergencyWithdrawOpen[filter] = isOpen;
|
||||
emit SetEmergencyWithdraw(filter, isOpen);
|
||||
}
|
||||
|
||||
//===================== View ========================
|
||||
function getMintFeeRate(address filterAdminAddr) external view returns (uint256) {
|
||||
FilterAdminFeeRateInfo memory filterAdminFeeRateInfo = filterAdminFeeRates[filterAdminAddr];
|
||||
|
||||
if (filterAdminFeeRateInfo.isSet) {
|
||||
return filterAdminFeeRateInfo.nftInFeeRate;
|
||||
} else {
|
||||
return _GLOBAL_NFT_IN_FEERate_;
|
||||
}
|
||||
}
|
||||
|
||||
function getBurnFeeRate(address filterAdminAddr) external view returns (uint256) {
|
||||
FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr];
|
||||
|
||||
if (filterAdminFeeInfo.isSet) {
|
||||
return filterAdminFeeInfo.nftOutFee;
|
||||
} else {
|
||||
return _GLOBAL_NFT_OUT_FEE_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
|
||||
contract ControllerModel is InitializableOwnable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public _GLOBAL_NFT_IN_FEE_ = 0;
|
||||
uint256 public _GLOBAL_NFT_OUT_FEE_ = 0;
|
||||
|
||||
struct FilterAdminFeeInfo {
|
||||
uint256 nftInFee;
|
||||
uint256 nftOutFee;
|
||||
bool isSet;
|
||||
}
|
||||
|
||||
mapping(address => FilterAdminFeeInfo) filterAdminFees;
|
||||
|
||||
mapping(address => bool) isEmergencyWithdraw;
|
||||
|
||||
//==================== Event =====================
|
||||
event SetEmergencyWithdraw(address filter, bool isOpen);
|
||||
|
||||
//==================== Ownable ====================
|
||||
|
||||
function addFilterAdminFeeInfo(address filterAdminAddr, uint256 nftInFee, uint256 nftOutFee) external onlyOwner {
|
||||
FilterAdminFeeInfo memory filterAdmin = FilterAdminFeeInfo({
|
||||
nftInFee: nftInFee,
|
||||
nftOutFee: nftOutFee,
|
||||
isSet: true
|
||||
});
|
||||
filterAdminFees[filterAdminAddr] = filterAdmin;
|
||||
}
|
||||
|
||||
function setFilterAdminFeeInfo(address filterAdminAddr, uint256 nftInFee, uint256 nftOutFee) external onlyOwner {
|
||||
filterAdminFees[filterAdminAddr].nftInFee = nftInFee;
|
||||
filterAdminFees[filterAdminAddr].nftOutFee = nftOutFee;
|
||||
}
|
||||
|
||||
function setGlobalParam(uint256 nftInFee, uint256 nftOutFee) external onlyOwner {
|
||||
_GLOBAL_NFT_IN_FEE_ = nftInFee;
|
||||
_GLOBAL_NFT_OUT_FEE_ = nftOutFee;
|
||||
}
|
||||
|
||||
function setEmergencyWithdraw(address filter, bool isOpen) external onlyOwner {
|
||||
isEmergencyWithdraw[filter] = isOpen;
|
||||
emit SetEmergencyWithdraw(filter, isOpen);
|
||||
}
|
||||
|
||||
//===================== View ========================
|
||||
function getMintFee(address filterAdminAddr) external view returns(uint256) {
|
||||
FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr];
|
||||
|
||||
if(filterAdminFeeInfo.isSet) {
|
||||
return filterAdminFeeInfo.nftInFee;
|
||||
}else {
|
||||
return _GLOBAL_NFT_IN_FEE_;
|
||||
}
|
||||
}
|
||||
|
||||
function getBurnFee(address filterAdminAddr) external view returns(uint256) {
|
||||
FilterAdminFeeInfo memory filterAdminFeeInfo = filterAdminFees[filterAdminAddr];
|
||||
|
||||
if(filterAdminFeeInfo.isSet) {
|
||||
return filterAdminFeeInfo.nftOutFee;
|
||||
}else {
|
||||
return _GLOBAL_NFT_OUT_FEE_;
|
||||
}
|
||||
}
|
||||
|
||||
function getEmergencySwitch(address filter) external view returns(bool) {
|
||||
return isEmergencyWithdraw[filter];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,99 +10,118 @@ pragma experimental ABIEncoderV2;
|
||||
|
||||
import {InitializableInternalMintableERC20} from "../../external/ERC20/InitializableInternalMintableERC20.sol";
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
import {IControllerModel} from "../intf/IControllerModel.sol";
|
||||
import {IController} from "../intf/IController.sol";
|
||||
import {DecimalMath} from "../../lib/DecimalMath.sol";
|
||||
|
||||
contract FilterAdmin is InitializableInternalMintableERC20 {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// ============ Storage ============
|
||||
address[] public _FILTER_REGISTRY_;
|
||||
uint256 public _FEE_;
|
||||
address public _CONTROLLER_MODEL_;
|
||||
address public _DEFAULT_MAINTAINER_;
|
||||
address[] public _FILTERS_;
|
||||
mapping(address => bool) public _FILTER_REGISTRY_;
|
||||
uint256 public _FEE_RATE_;
|
||||
address public _CONTROLLER_;
|
||||
address public _MAINTAINER_;
|
||||
uint256 public _INIT_SUPPLY_;
|
||||
|
||||
// ============ Event ============
|
||||
event ChangeFee(uint256 fee);
|
||||
event ChangeFeeRate(uint256 fee);
|
||||
|
||||
function init(
|
||||
address owner,
|
||||
uint256 initSupply,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 fee,
|
||||
address controllerModel,
|
||||
address defaultMaintainer,
|
||||
uint256 feeRate,
|
||||
address controller,
|
||||
address maintainer,
|
||||
address[] memory filters
|
||||
) external {
|
||||
super.init(owner, initSupply, name, symbol, 18);
|
||||
_FILTER_REGISTRY_ = filters;
|
||||
_FEE_ = fee;
|
||||
_CONTROLLER_MODEL_ = controllerModel;
|
||||
_DEFAULT_MAINTAINER_ = defaultMaintainer;
|
||||
_INIT_SUPPLY_ = initSupply;
|
||||
_FEE_RATE_ = feeRate;
|
||||
_CONTROLLER_ = controller;
|
||||
_MAINTAINER_ = maintainer;
|
||||
_FILTERS_ = filters;
|
||||
for (uint256 i = 0; i < filters.length; i++) {
|
||||
_FILTER_REGISTRY_[filters[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
function mintFragTo(address to, uint256 rawAmount) external returns (uint256 received){
|
||||
require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED");
|
||||
function mintFragTo(address to, uint256 rawAmount) external returns (uint256) {
|
||||
require(isRegisteredFilter(msg.sender), "FILTER_NOT_REGISTERED");
|
||||
|
||||
(uint256 poolFee, uint256 mtFee) = queryChargeMintFee(rawAmount);
|
||||
if(poolFee > 0) _mint(_OWNER_, poolFee);
|
||||
if(mtFee > 0) _mint(_DEFAULT_MAINTAINER_, mtFee);
|
||||
|
||||
received = rawAmount.sub(poolFee).sub(mtFee);
|
||||
_mint(to, received);
|
||||
(uint256 poolFee, uint256 mtFee, uint256 received) = queryMintFee(rawAmount);
|
||||
if (poolFee > 0) _mint(_OWNER_, poolFee);
|
||||
if (mtFee > 0) _mint(_MAINTAINER_, mtFee);
|
||||
|
||||
_mint(to, received);
|
||||
return received
|
||||
}
|
||||
|
||||
function burnFragFrom(address from, uint256 rawAmount) external returns (uint256 paid){
|
||||
require(isIncludeFilter(msg.sender), "FILTER_NOT_REGISTRIED");
|
||||
function burnFragFrom(address from, uint256 rawAmount) external returns (uint256) {
|
||||
require(isRegisteredFilter(msg.sender), "FILTER_NOT_REGISTERED");
|
||||
|
||||
(uint256 poolFee, uint256 mtFee) = queryChargeBurnFee(rawAmount);
|
||||
if(poolFee > 0) _mint(_OWNER_, poolFee);
|
||||
if(mtFee > 0) _mint(_DEFAULT_MAINTAINER_, mtFee);
|
||||
(uint256 poolFee, uint256 mtFee, uint256 paid) = queryBurnFee(rawAmount);
|
||||
if (poolFee > 0) _mint(_OWNER_, poolFee);
|
||||
if (mtFee > 0) _mint(_MAINTAINER_, mtFee);
|
||||
|
||||
paid = rawAmount.add(poolFee).add(mtFee);
|
||||
_burn(from, paid);
|
||||
return paid;
|
||||
}
|
||||
|
||||
//================ View ================
|
||||
function queryChargeMintFee(uint256 rawAmount) public returns (uint256 poolFee, uint256 mtFee) {
|
||||
uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getMintFee(address(this));
|
||||
poolFee = DecimalMath.mulFloor(rawAmount, _FEE_);
|
||||
function queryMintFee(uint256 rawAmount)
|
||||
public
|
||||
returns (
|
||||
uint256 poolFee,
|
||||
uint256 mtFee,
|
||||
uint256 afterChargedAmount
|
||||
)
|
||||
{
|
||||
uint256 mtFeeRate = IController(_CONTROLLER_).getMintFee(address(this));
|
||||
poolFee = DecimalMath.mulFloor(rawAmount, _FEE_RATE_);
|
||||
mtFee = DecimalMath.mulFloor(rawAmount, mtFeeRate);
|
||||
afterChargedAmount = rawAmount.sub(poolFee).sub(mtFee);
|
||||
}
|
||||
|
||||
function queryChargeBurnFee(uint256 rawAmount) public returns (uint256 poolFee, uint256 mtFee) {
|
||||
uint256 mtFeeRate = IControllerModel(_CONTROLLER_MODEL_).getBurnFee(address(this));
|
||||
poolFee = DecimalMath.mulFloor(rawAmount, _FEE_);
|
||||
function queryBurnFee(uint256 rawAmount)
|
||||
public
|
||||
returns (
|
||||
uint256 poolFee,
|
||||
uint256 mtFee,
|
||||
uint256 afterChargedAmount
|
||||
)
|
||||
{
|
||||
uint256 mtFeeRate = IController(_CONTROLLER_).getBurnFee(address(this));
|
||||
poolFee = DecimalMath.mulFloor(rawAmount, _FEE_RATE_);
|
||||
mtFee = DecimalMath.mulFloor(rawAmount, mtFeeRate);
|
||||
afterChargedAmount = rawAmount.add(poolFee).add(mtFee);
|
||||
}
|
||||
|
||||
|
||||
function isIncludeFilter(address filter) view public returns (bool) {
|
||||
uint256 i = 0;
|
||||
for(; i < _FILTER_REGISTRY_.length; i++) {
|
||||
if(filter == _FILTER_REGISTRY_[i]) break;
|
||||
}
|
||||
return i == _FILTER_REGISTRY_.length ? false : true;
|
||||
function isRegisteredFilter(address filter) public view returns (bool) {
|
||||
return _FILTER_REGISTRY_[i];
|
||||
}
|
||||
|
||||
function getFilters() view public returns (address[] memory) {
|
||||
return _FILTER_REGISTRY_;
|
||||
}
|
||||
|
||||
function version() virtual external pure returns (string memory) {
|
||||
return "FADMIN 1.0.0";
|
||||
function getFilters() public view returns (address[] memory) {
|
||||
return _FILTERS_;
|
||||
}
|
||||
|
||||
//================= Owner ================
|
||||
function addFilter(address filter) external onlyOwner {
|
||||
require(!isIncludeFilter(filter), "FILTER_NOT_INCLUDE");
|
||||
_FILTER_REGISTRY_.push(filter);
|
||||
require(!isRegisteredFilter(filter), "FILTER_ALREADY_EXIST");
|
||||
_FILTERS_.push(filter);
|
||||
_FILTER_REGISTRY_[filter] = true;
|
||||
}
|
||||
|
||||
function changeFee(uint256 newFee) external onlyOwner {
|
||||
require(newFee <= DecimalMath.ONE, "FEE_TOO_LARGE");
|
||||
_FEE_ = newFee;
|
||||
emit ChangeFee(newFee);
|
||||
function changeFeeRate(uint256 newFeeRate) external onlyOwner {
|
||||
require(newFeeRate <= DecimalMath.ONE, "FEE_RATE_TOO_LARGE");
|
||||
_FEE_RATE_ = newFeeRate;
|
||||
emit ChangeFeeRate(newFeeRate);
|
||||
}
|
||||
|
||||
//================= Support ================
|
||||
function version() external pure virtual returns (string memory) {
|
||||
return "FILTER ADMIN 1.0.0";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,10 @@ import {BaseFilterV1} from "./BaseFilterV1.sol";
|
||||
contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
using SafeMath for uint256;
|
||||
|
||||
//=================== Storage ===================
|
||||
uint256 public _TOTAL_NFT_AMOUNT_;
|
||||
|
||||
function init(
|
||||
address filterAdmin,
|
||||
address nftCollection,
|
||||
bool[] memory switches,
|
||||
bool[] memory toggles,
|
||||
uint256[] memory numParams, //0 - startId, 1 - endId, 2 - maxAmount, 3 - minAmount
|
||||
uint256[] memory priceRules,
|
||||
uint256[] memory spreadIds
|
||||
@@ -31,55 +28,40 @@ contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
initOwner(filterAdmin);
|
||||
_NFT_COLLECTION_ = nftCollection;
|
||||
|
||||
_changeNFTInPrice(priceRules[0],priceRules[1],switches[0]);
|
||||
_changeNFTRandomInPrice(priceRules[2],priceRules[3],switches[1]);
|
||||
_changeNFTTargetOutPrice(priceRules[4],priceRules[5],switches[2]);
|
||||
_changeNFTInPrice(priceRules[0], priceRules[1], toggles[0]);
|
||||
_changeNFTRandomInPrice(priceRules[2], priceRules[3], toggles[1]);
|
||||
_changeNFTTargetOutPrice(priceRules[4], priceRules[5], toggles[2]);
|
||||
|
||||
_changeNFTAmount(numParams[2],numParams[3]);
|
||||
_changeNFTAmount(numParams[2], numParams[3]);
|
||||
|
||||
_changeTokenIdRange(numParams[0],numParams[1]);
|
||||
for(uint256 i = 0; i < spreadIds.length; i++) {
|
||||
_changeTokenIdRange(numParams[0], numParams[1]);
|
||||
for (uint256 i = 0; i < spreadIds.length; i++) {
|
||||
_SPREAD_IDS_REGISTRY_[spreadIds[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
//==================== Query ==================
|
||||
|
||||
function queryNFTIn(uint256 NFTInAmount) public view returns (uint256 rawReceive, uint256 received) {
|
||||
require(NFTInAmount <= getAvaliableNFTIn(), "EXCEDD_IN_AMOUNT");
|
||||
rawReceive = _geometricCalc(_GS_START_IN_, _CR_IN_, _TOTAL_NFT_AMOUNT_, _TOTAL_NFT_AMOUNT_ + NFTInAmount);
|
||||
(uint256 poolFee, uint256 mtFee) = IFilterAdmin(_OWNER_).queryChargeMintFee(rawReceive);
|
||||
received = rawReceive.sub(poolFee).sub(mtFee);
|
||||
}
|
||||
|
||||
function queryNFTTargetOut(uint256 NFTOutAmount) public view returns (uint256 rawPay, uint256 pay) {
|
||||
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
|
||||
rawPay = _geometricCalc(_GS_START_TARGET_OUT_,_CR_TARGET_OUT_, _TOTAL_NFT_AMOUNT_ - NFTOutAmount, _TOTAL_NFT_AMOUNT_);
|
||||
(uint256 poolFee, uint256 mtFee) = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay);
|
||||
pay = rawPay.add(poolFee).add(mtFee);
|
||||
}
|
||||
|
||||
function queryNFTRandomOut(uint256 NFTOutAmount) public view returns (uint256 rawPay, uint256 pay) {
|
||||
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
|
||||
rawPay = _geometricCalc(_GS_START_RANDOM_OUT_,_CR_RANDOM_OUT_, _TOTAL_NFT_AMOUNT_ - NFTOutAmount, _TOTAL_NFT_AMOUNT_);
|
||||
(uint256 poolFee, uint256 mtFee) = IFilterAdmin(_OWNER_).queryChargeBurnFee(rawPay);
|
||||
pay = rawPay.add(poolFee).add(mtFee);
|
||||
}
|
||||
|
||||
// ================= Trading ================
|
||||
|
||||
function ERC1155In(uint256[] memory tokenIds, address to) external preventReentrant returns(uint256 received) {
|
||||
function ERC1155In(uint256[] memory tokenIds, address to)
|
||||
external
|
||||
preventReentrant
|
||||
returns (uint256 received)
|
||||
{
|
||||
uint256 totalAmount = 0;
|
||||
for (uint256 i = 0; i < tokenIds.length; i++) {
|
||||
uint256 tokenId = tokenIds[i];
|
||||
require(isNFTIDValid(tokenId), "NFT_ID_NOT_SUPPORT");
|
||||
totalAmount += _maintainERC1155In(tokenId);
|
||||
}
|
||||
(uint256 rawReceive,) = queryNFTIn(totalAmount);
|
||||
(uint256 rawReceive, ) = queryNFTIn(totalAmount);
|
||||
received = IFilterAdmin(_OWNER_).mintFragTo(to, rawReceive);
|
||||
}
|
||||
|
||||
function ERC1155TargetOut(uint256[] memory indexes, uint256[] memory amounts, address to) external preventReentrant returns(uint256 paid) {
|
||||
function ERC1155TargetOut(
|
||||
uint256[] memory indexes,
|
||||
uint256[] memory amounts,
|
||||
address to
|
||||
) external preventReentrant returns (uint256 paid) {
|
||||
uint256 totalAmount = 0;
|
||||
for (uint256 i = 0; i < indexes.length; i++) {
|
||||
totalAmount += amounts[i];
|
||||
@@ -89,7 +71,11 @@ contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay);
|
||||
}
|
||||
|
||||
function ERC1155RandomOut(uint256 amount, address to) external preventReentrant returns (uint256 paid) {
|
||||
function ERC1155RandomOut(uint256 amount, address to)
|
||||
external
|
||||
preventReentrant
|
||||
returns (uint256 paid)
|
||||
{
|
||||
(uint256 rawPay, ) = queryNFTRandomOut(amount);
|
||||
paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay);
|
||||
for (uint256 i = 0; i < amount; i++) {
|
||||
@@ -105,7 +91,7 @@ contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
uint256,
|
||||
uint256,
|
||||
bytes calldata
|
||||
) external override returns (bytes4){
|
||||
) external override returns (bytes4) {
|
||||
return IERC1155Receiver.onERC1155Received.selector;
|
||||
}
|
||||
|
||||
@@ -115,28 +101,41 @@ contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
uint256[] calldata,
|
||||
uint256[] calldata,
|
||||
bytes calldata
|
||||
) external override returns (bytes4){
|
||||
) external override returns (bytes4) {
|
||||
return IERC1155Receiver.onERC1155BatchReceived.selector;
|
||||
}
|
||||
|
||||
function _transferOutERC1155(address to, uint256 index, uint256 amount) internal {
|
||||
function _transferOutERC1155(
|
||||
address to,
|
||||
uint256 index,
|
||||
uint256 amount
|
||||
) internal {
|
||||
require(index < _NFT_IDS_.length, "INDEX_NOT_EXIST");
|
||||
uint256 tokenId = _NFT_IDS_[index];
|
||||
IERC1155(_NFT_COLLECTION_).safeTransferFrom(address(this), to, tokenId, amount, "");
|
||||
_maintainERC1155Out(index, tokenId);
|
||||
}
|
||||
|
||||
function emergencyWithdraw(address[] memory nftContract, uint256[] memory tokenIds, uint256[] memory amounts, address to) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
require(nftContract.length == tokenIds.length, "PARAM_INVALID");
|
||||
require(nftContract.length == amounts.length, "PARAM_INVALID");
|
||||
address controllerModel = IFilterAdmin(_OWNER_)._CONTROLLER_MODEL_();
|
||||
require(IControllerModel(controllerModel).getEmergencySwitch(address(this)), "NOT_OPEN");
|
||||
function emergencyWithdraw(
|
||||
address[] memory nftContract,
|
||||
uint256[] memory tokenIds,
|
||||
uint256[] memory amounts,
|
||||
address to
|
||||
) external onlySuperOwner {
|
||||
require(
|
||||
nftContract.length == tokenIds.length && nftContract.length == amounts.length,
|
||||
"PARAM_INVALID"
|
||||
);
|
||||
address controller = IFilterAdmin(_OWNER_)._CONTROLLER_();
|
||||
require(
|
||||
IController(controller).isEmergencyWithdrawOpen(address(this)),
|
||||
"EMERGENCY_WITHDRAW_NOT_OPEN"
|
||||
);
|
||||
|
||||
for(uint256 i = 0; i< nftContract.length; i++) {
|
||||
for (uint256 i = 0; i < nftContract.length; i++) {
|
||||
uint256 tokenId = tokenIds[i];
|
||||
IERC1155(nftContract[i]).safeTransferFrom(address(this), to, tokenId, amounts[i], "");
|
||||
if(isNFTIDValid(tokenId) && nftContract[i] == _NFT_COLLECTION_){
|
||||
if (_NFT_RESERVE_[tokenId] > 0 && nftContract[i] == _NFT_COLLECTION_) {
|
||||
_maintainERC1155Out(getNFTIndexById(tokenId), tokenId);
|
||||
}
|
||||
}
|
||||
@@ -153,10 +152,10 @@ contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
}
|
||||
}
|
||||
|
||||
function _maintainERC1155In(uint256 tokenId) internal returns(uint256 inAmount){
|
||||
function _maintainERC1155In(uint256 tokenId) internal returns (uint256 inAmount) {
|
||||
uint256 currentAmount = IERC1155(_NFT_COLLECTION_).balanceOf(address(this), tokenId);
|
||||
inAmount = currentAmount.sub(_NFT_RESERVE_[tokenId]);
|
||||
if(_NFT_RESERVE_[tokenId] == 0 && currentAmount > 0) {
|
||||
if (_NFT_RESERVE_[tokenId] == 0 && currentAmount > 0) {
|
||||
_NFT_IDS_.push(tokenId);
|
||||
}
|
||||
_NFT_RESERVE_[tokenId] = currentAmount;
|
||||
@@ -165,12 +164,11 @@ contract FilterERC1155V1 is IERC1155Receiver, BaseFilterV1 {
|
||||
|
||||
// ============ Support ============
|
||||
|
||||
function supportsInterface(bytes4 interfaceId) override public view returns (bool) {
|
||||
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
|
||||
return interfaceId == type(IERC1155Receiver).interfaceId;
|
||||
}
|
||||
|
||||
|
||||
function version() virtual external pure returns (string memory) {
|
||||
function version() external pure virtual returns (string memory) {
|
||||
return "FILTER_1_ERC1155 1.0.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ contract FilterERC721V1 is IERC721Receiver, BaseFilterV1 {
|
||||
function init(
|
||||
address filterAdmin,
|
||||
address nftCollection,
|
||||
bool[] memory switches,
|
||||
bool[] memory toggles,
|
||||
uint256[] memory numParams, //0 - startId, 1 - endId, 2 - maxAmount, 3 - minAmount
|
||||
uint256[] memory priceRules,
|
||||
uint256[] memory spreadIds
|
||||
@@ -31,72 +31,65 @@ contract FilterERC721V1 is IERC721Receiver, BaseFilterV1 {
|
||||
initOwner(filterAdmin);
|
||||
_NFT_COLLECTION_ = nftCollection;
|
||||
|
||||
_changeNFTInPrice(priceRules[0],priceRules[1],switches[0]);
|
||||
_changeNFTRandomInPrice(priceRules[2],priceRules[3],switches[1]);
|
||||
_changeNFTTargetOutPrice(priceRules[4],priceRules[5],switches[2]);
|
||||
_changeNFTInPrice(priceRules[0], priceRules[1], toggles[0]);
|
||||
_changeNFTRandomInPrice(priceRules[2], priceRules[3], toggles[1]);
|
||||
_changeNFTTargetOutPrice(priceRules[4], priceRules[5], toggles[2]);
|
||||
|
||||
_changeNFTAmount(numParams[2],numParams[3]);
|
||||
_changeNFTAmount(numParams[2], numParams[3]);
|
||||
|
||||
_changeTokenIdRange(numParams[0],numParams[1]);
|
||||
for(uint256 i = 0; i < spreadIds.length; i++) {
|
||||
_changeTokenIdRange(numParams[0], numParams[1]);
|
||||
for (uint256 i = 0; i < spreadIds.length; i++) {
|
||||
_SPREAD_IDS_REGISTRY_[spreadIds[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
//==================== Query ==================
|
||||
|
||||
function queryNFTIn(uint256 NFTInAmount) public view returns (uint256 rawReceive, uint256 received) {
|
||||
require(NFTInAmount <= getAvaliableNFTIn(), "EXCEDD_IN_AMOUNT");
|
||||
uint256 nftAmount = _NFT_IDS_.length;
|
||||
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) public view returns (uint256 rawPay, uint256 pay) {
|
||||
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
|
||||
uint256 nftAmount = _NFT_IDS_.length;
|
||||
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) public view returns (uint256 rawPay, uint256 pay) {
|
||||
require(NFTOutAmount <= getAvaliableNFTOut(), "EXCEED_OUT_AMOUNT");
|
||||
uint256 nftAmount = _NFT_IDS_.length;
|
||||
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 ================
|
||||
|
||||
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++) {
|
||||
uint256 tokenId = tokenIds[i];
|
||||
require(isNFTIDValid(tokenId), "NFT_ID_NOT_SUPPORT");
|
||||
require(_NFT_RESERVE_[tokenId] == 0 && IERC721(_NFT_COLLECTION_).ownerOf(tokenId) == address(this), "NFT_NOT_SEND");
|
||||
require(
|
||||
_NFT_RESERVE_[tokenId] == 0 &&
|
||||
IERC721(_NFT_COLLECTION_).ownerOf(tokenId) == address(this),
|
||||
"NFT_NOT_SEND"
|
||||
);
|
||||
_NFT_IDS_.push(tokenId);
|
||||
_NFT_RESERVE_[tokenId] = 1;
|
||||
}
|
||||
(uint256 rawReceive,) = queryNFTIn(tokenIds.length);
|
||||
_TOTAL_NFT_AMOUNT_ = _NFT_IDS_.length;
|
||||
(uint256 rawReceive, ) = queryNFTIn(tokenIds.length);
|
||||
received = IFilterAdmin(_OWNER_).mintFragTo(to, rawReceive);
|
||||
}
|
||||
|
||||
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, ) = queryNFTTargetOut(indexes.length);
|
||||
paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay);
|
||||
for (uint256 i = 0; i < indexes.length; i++) {
|
||||
_transferOutERC721(to, indexes[i]);
|
||||
}
|
||||
_TOTAL_NFT_AMOUNT_ = _NFT_IDS_.length;
|
||||
}
|
||||
|
||||
function ERC721RandomOut(uint256 amount, address to) external preventReentrant returns (uint256 paid) {
|
||||
function ERC721RandomOut(uint256 amount, address to)
|
||||
external
|
||||
preventReentrant
|
||||
returns (uint256 paid)
|
||||
{
|
||||
(uint256 rawPay, ) = queryNFTRandomOut(amount);
|
||||
paid = IFilterAdmin(_OWNER_).burnFragFrom(msg.sender, rawPay);
|
||||
for (uint256 i = 0; i < amount; i++) {
|
||||
_transferOutERC721(to, _getRandomOutId());
|
||||
}
|
||||
_TOTAL_NFT_AMOUNT_ = _NFT_IDS_.length;
|
||||
}
|
||||
|
||||
// ============ Transfer =============
|
||||
@@ -110,7 +103,7 @@ contract FilterERC721V1 is IERC721Receiver, BaseFilterV1 {
|
||||
return IERC721Receiver.onERC721Received.selector;
|
||||
}
|
||||
|
||||
function _transferOutERC721(address to, uint256 index) internal {
|
||||
function _transferOutERC721(address to, uint256 index) internal {
|
||||
require(index < _NFT_IDS_.length, "INDEX_NOT_EXIST");
|
||||
uint256 tokenId = _NFT_IDS_[index];
|
||||
IERC721(_NFT_COLLECTION_).safeTransferFrom(address(this), to, tokenId);
|
||||
@@ -119,21 +112,29 @@ contract FilterERC721V1 is IERC721Receiver, BaseFilterV1 {
|
||||
_NFT_RESERVE_[tokenId] = 0;
|
||||
}
|
||||
|
||||
function emergencyWithdraw(address[] memory nftContract, uint256[] memory tokenIds, address to) external {
|
||||
require(msg.sender == IFilterAdmin(_OWNER_)._OWNER_(), "ACCESS_RESTRICTED");
|
||||
function emergencyWithdraw(
|
||||
address[] memory nftContract,
|
||||
uint256[] memory tokenIds,
|
||||
address to
|
||||
) external onlySuperOwner {
|
||||
require(nftContract.length == tokenIds.length, "PARAM_INVALID");
|
||||
address controllerModel = IFilterAdmin(_OWNER_)._CONTROLLER_MODEL_();
|
||||
require(IControllerModel(controllerModel).getEmergencySwitch(address(this)), "NOT_OPEN");
|
||||
address controller = IFilterAdmin(_OWNER_)._CONTROLLER_();
|
||||
require(
|
||||
IController(controller).isEmergencyWithdrawOpen(address(this)),
|
||||
"EMERGENCY_WITHDRAW_NOT_OPEN"
|
||||
);
|
||||
|
||||
for(uint256 i = 0; i< nftContract.length; i++) {
|
||||
if(_NFT_RESERVE_[tokenIds[i]] == 1 && nftContract[i] == _NFT_COLLECTION_){
|
||||
uint256 index = getNFTIndexById(tokenIds[i]);
|
||||
for (uint256 i = 0; i < nftContract.length; i++) {
|
||||
uint256 tokenId = tokenIds[i];
|
||||
if (_NFT_RESERVE_[tokenId] > 0 && nftContract[i] == _NFT_COLLECTION_) {
|
||||
uint256 index = getNFTIndexById(tokenId);
|
||||
_NFT_IDS_[index] = _NFT_IDS_[_NFT_IDS_.length - 1];
|
||||
_NFT_IDS_.pop();
|
||||
_NFT_RESERVE_[tokenIds[i]] = 0;
|
||||
_NFT_RESERVE_[tokenId] = 0;
|
||||
}
|
||||
IERC721(nftContract[i]).safeTransferFrom(address(this), to, tokenIds[i]);
|
||||
}
|
||||
_TOTAL_NFT_AMOUNT_ = _NFT_IDS_.length;
|
||||
}
|
||||
|
||||
// ============ Support ============
|
||||
@@ -142,8 +143,7 @@ contract FilterERC721V1 is IERC721Receiver, BaseFilterV1 {
|
||||
return interfaceId == type(IERC721Receiver).interfaceId;
|
||||
}
|
||||
|
||||
function version() virtual external pure returns (string memory) {
|
||||
function version() external pure virtual returns (string memory) {
|
||||
return "FILTER_1_ERC721 1.0.0";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
16
contracts/NFTPool/intf/IController.sol
Normal file
16
contracts/NFTPool/intf/IController.sol
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
interface IController {
|
||||
function getMintFeeRate(address filterAdminAddr) external view returns (uint256);
|
||||
|
||||
function getBurnFeeRate(address filterAdminAddr) external view returns (uint256);
|
||||
|
||||
function isEmergencyWithdrawOpen(address filter) external view returns (bool);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
interface IControllerModel {
|
||||
function getMintFee(address filterAdminAddr) external view returns (uint256);
|
||||
|
||||
function getBurnFee(address filterAdminAddr) external view returns (uint256);
|
||||
|
||||
function getEmergencySwitch(address filter) external view returns (bool);
|
||||
}
|
||||
45
contracts/NFTPool/intf/IFilter.sol
Normal file
45
contracts/NFTPool/intf/IFilter.sol
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
interface IFilter {
|
||||
function isNFTValid(address nftCollectionAddress, uint256 nftId) external view returns (bool);
|
||||
|
||||
function _NFT_COLLECTION_() external view returns (address);
|
||||
|
||||
function queryNFTIn(uint256 NFTInAmount)
|
||||
external
|
||||
view
|
||||
returns (uint256 rawReceive, uint256 received);
|
||||
|
||||
function queryNFTTargetOut(uint256 NFTOutAmount)
|
||||
external
|
||||
view
|
||||
returns (uint256 rawPay, uint256 pay);
|
||||
|
||||
function queryNFTRandomOut(uint256 NFTOutAmount)
|
||||
external
|
||||
view
|
||||
returns (uint256 rawPay, uint256 pay);
|
||||
|
||||
function ERC721In(uint256[] memory tokenIds, address to) external returns (uint256 received);
|
||||
|
||||
function ERC721TargetOut(uint256[] memory indexes, address to) external returns (uint256 paid);
|
||||
|
||||
function ERC721RandomOut(uint256 amount, address to) external returns (uint256 paid);
|
||||
|
||||
function ERC1155In(uint256[] memory tokenIds, address to) external returns (uint256 received);
|
||||
|
||||
function ERC1155TargetOut(
|
||||
uint256[] memory indexes,
|
||||
uint256[] memory amounts,
|
||||
address to
|
||||
) external returns (uint256 paid);
|
||||
|
||||
function ERC1155RandomOut(uint256 amount, address to) external returns (uint256 paid);
|
||||
}
|
||||
@@ -10,16 +10,16 @@ pragma solidity 0.6.9;
|
||||
interface IFilterAdmin {
|
||||
function _OWNER_() external returns (address);
|
||||
|
||||
function _CONTROLLER_MODEL_() external returns (address);
|
||||
function _CONTROLLER_() external returns (address);
|
||||
|
||||
function init(
|
||||
address owner,
|
||||
uint256 initSupply,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 fee,
|
||||
address mtFeeModel,
|
||||
address defaultMaintainer,
|
||||
uint256 feeRate,
|
||||
address controller,
|
||||
address maintainer,
|
||||
address[] memory filters
|
||||
) external;
|
||||
|
||||
@@ -27,7 +27,21 @@ interface IFilterAdmin {
|
||||
|
||||
function burnFragFrom(address from, uint256 rawAmount) external returns (uint256 paid);
|
||||
|
||||
function queryChargeMintFee(uint256 rawAmount) external view returns (uint256 poolFee, uint256 mtFee);
|
||||
function queryMintFee(uint256 rawAmount)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 poolFee,
|
||||
uint256 mtFee,
|
||||
uint256 afterChargedAmount
|
||||
);
|
||||
|
||||
function queryChargeBurnFee(uint256 rawAmount) external view returns (uint256 poolFee, uint256 mtFee);
|
||||
function queryBurnFee(uint256 rawAmount)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 poolFee,
|
||||
uint256 mtFee,
|
||||
uint256 afterChargedAmount
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
interface IFilterModel {
|
||||
function isNFTValid(address nftCollectionAddress, uint256 nftId) external view returns (bool);
|
||||
|
||||
function _NFT_COLLECTION_() external view returns(address);
|
||||
|
||||
function queryNFTIn(uint256 NFTInAmount) external view returns (uint256 rawReceive, uint256 received);
|
||||
|
||||
function queryNFTTargetOut(uint256 NFTOutAmount) external view returns (uint256 rawPay, uint256 pay);
|
||||
|
||||
function queryNFTRandomOut(uint256 NFTOutAmount) external view returns (uint256 rawPay, uint256 pay);
|
||||
|
||||
function ERC721In(uint256[] memory tokenIds, address to) external returns(uint256 received);
|
||||
|
||||
function ERC721TargetOut(uint256[] memory indexes, address to) external returns(uint256 paid);
|
||||
|
||||
function ERC721RandomOut(uint256 amount, address to) external returns (uint256 paid);
|
||||
|
||||
function ERC1155In(uint256[] memory tokenIds, address to) external returns(uint256 received);
|
||||
|
||||
function ERC1155TargetOut(uint256[] memory indexes, uint256[] memory amounts, address to) external returns(uint256 paid);
|
||||
|
||||
function ERC1155RandomOut(uint256 amount, address to) external returns (uint256 paid);
|
||||
}
|
||||
Reference in New Issue
Block a user