some changes & rename

This commit is contained in:
mingda
2021-09-10 19:37:06 +08:00
committed by owen05
parent 8d40444a89
commit 551e7063dd
11 changed files with 502 additions and 381 deletions

View File

@@ -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];
}
}
}
}

View 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_;
}
}
}

View File

@@ -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];
}
}

View File

@@ -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";
}
}

View File

@@ -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";
}
}
}

View File

@@ -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";
}
}
}

View 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);
}

View File

@@ -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);
}

View 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);
}

View File

@@ -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
);
}

View File

@@ -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);
}