Files
2021-08-26 16:01:24 +08:00

225 lines
7.7 KiB
Solidity

/*
Copyright 2020 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
import {IDODOApproveProxy} from "../DODOApproveProxy.sol";
import {ICloneFactory} from "../../lib/CloneFactory.sol";
import {IERC20} from "../../intf/IERC20.sol";
import {IWETH} from "../../intf/IWETH.sol";
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
import {ICollateralVault} from "../../CollateralVault/intf/ICollateralVault.sol";
import {IDVM} from "../../DODOVendingMachine/intf/IDVM.sol";
import {IFragment} from "../../GeneralizedFragment/intf/IFragment.sol";
import {IDODONFTRegistry} from "../../Factory/Registries/DODONFTRegistry.sol";
import {SafeMath} from "../../lib/SafeMath.sol";
import {SafeERC20} from "../../lib/SafeERC20.sol";
import {DecimalMath} from "../../lib/DecimalMath.sol";
import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol";
/**
* @title DODONFTProxy
* @author DODO Breeder
*
* @notice Entrance of NFT in DODO platform
*/
contract DODONFTProxy is ReentrancyGuard, InitializableOwnable {
using SafeMath for uint256;
// ============ Storage ============
address constant _ETH_ADDRESS_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address public immutable _WETH_;
address public immutable _DODO_APPROVE_PROXY_;
address public immutable _CLONE_FACTORY_;
address public immutable _NFT_REGISTY_;
address public _DEFAULT_MAINTAINER_;
address public _MT_FEE_RATE_MODEL_;
address public _VAULT_TEMPLATE_;
address public _FRAG_TEMPLATE_;
address public _DVM_TEMPLATE_;
address public _BUYOUT_MODEL_;
// ============ Events ============
event ChangeVaultTemplate(address newVaultTemplate);
event ChangeFragTemplate(address newFragTemplate);
event ChangeDvmTemplate(address newDvmTemplate);
event ChangeMtFeeRateTemplate(address newMtFeeRateTemplate);
event ChangeBuyoutModel(address newBuyoutModel);
event ChangeMaintainer(address newMaintainer);
event CreateNFTCollateralVault(address creator, address vault, string name, string baseURI);
event CreateFragment(address vault, address fragment, address dvm);
event Buyout(address from, address fragment, uint256 amount);
// ============ Modifiers ============
modifier judgeExpired(uint256 deadLine) {
require(deadLine >= block.timestamp, "DODONFTProxy: EXPIRED");
_;
}
fallback() external payable {}
receive() external payable {}
constructor(
address cloneFactory,
address payable weth,
address dodoApproveProxy,
address defaultMaintainer,
address buyoutModel,
address mtFeeRateModel,
address vaultTemplate,
address fragTemplate,
address dvmTemplate,
address nftRegistry
) public {
_CLONE_FACTORY_ = cloneFactory;
_WETH_ = weth;
_DODO_APPROVE_PROXY_ = dodoApproveProxy;
_DEFAULT_MAINTAINER_ = defaultMaintainer;
_MT_FEE_RATE_MODEL_ = mtFeeRateModel;
_BUYOUT_MODEL_ = buyoutModel;
_VAULT_TEMPLATE_ = vaultTemplate;
_FRAG_TEMPLATE_ = fragTemplate;
_DVM_TEMPLATE_ = dvmTemplate;
_NFT_REGISTY_ = nftRegistry;
}
function createNFTCollateralVault(string memory name, string memory baseURI) external returns (address newVault) {
newVault = ICloneFactory(_CLONE_FACTORY_).clone(_VAULT_TEMPLATE_);
ICollateralVault(newVault).init(msg.sender, name, baseURI);
emit CreateNFTCollateralVault(msg.sender, newVault, name, baseURI);
}
function createFragment(
address[] calldata addrList, //0 - quoteToken, 1 - vaultPreOwner
uint256[] calldata params, //(DVM: 0 - lpFeeRate 1 - I, 2 - K) , (FRAG: 3 - totalSupply, 4 - ownerRatio, 5 - buyoutTimestamp, 6 - distributionRatio)
bool isOpenTwap,
string memory fragSymbol
) external returns (address newFragment, address newDvm) {
newFragment = ICloneFactory(_CLONE_FACTORY_).clone(_FRAG_TEMPLATE_);
address _quoteToken = addrList[0] == _ETH_ADDRESS_ ? _WETH_ : addrList[0];
{
uint256[] memory _params = params;
newDvm = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_TEMPLATE_);
IDVM(newDvm).init(
_DEFAULT_MAINTAINER_,
newFragment,
_quoteToken,
_params[0],
_MT_FEE_RATE_MODEL_,
_params[1],
_params[2],
isOpenTwap
);
IFragment(newFragment).init(
newDvm,
addrList[1],
msg.sender,
_params[3],
_params[4],
_params[5],
_DEFAULT_MAINTAINER_,
_BUYOUT_MODEL_,
_params[6],
fragSymbol
);
}
ICollateralVault(msg.sender).directTransferOwnership(newFragment);
IDODONFTRegistry(_NFT_REGISTY_).addRegistry(msg.sender, newFragment, _quoteToken, newDvm);
emit CreateFragment(msg.sender, newFragment, newDvm);
}
function buyout(
address fragment,
uint256 quoteMaxAmount,
uint8 flag, // 0 - ERC20, 1 - quoteInETH
uint256 deadLine
) external payable preventReentrant judgeExpired(deadLine) {
if(flag == 0)
require(msg.value == 0, "DODONFTProxy: WE_SAVED_YOUR_MONEY");
address dvm = IFragment(fragment)._DVM_();
uint256 fragTotalSupply = IFragment(fragment).totalSupply();
uint256 buyPrice = IDVM(dvm).getMidPrice();
uint256 curRequireQuote = DecimalMath.mulCeil(buyPrice, fragTotalSupply);
require(curRequireQuote <= quoteMaxAmount, "DODONFTProxy: CURRENT_TOTAL_VAULE_MORE_THAN_QUOTEMAX");
_deposit(msg.sender, fragment, IFragment(fragment)._QUOTE_(), curRequireQuote, flag == 1);
IFragment(fragment).buyout(msg.sender);
// IDODONFTRegistry(_NFT_REGISTY_).removeRegistry(fragment);
// refund dust eth
if (flag == 1 && msg.value > curRequireQuote) msg.sender.transfer(msg.value - curRequireQuote);
emit Buyout(msg.sender, fragment, curRequireQuote);
}
//============= Owner ===================
function updateVaultTemplate(address newVaultTemplate) external onlyOwner {
_VAULT_TEMPLATE_ = newVaultTemplate;
emit ChangeVaultTemplate(newVaultTemplate);
}
function updateFragTemplate(address newFragTemplate) external onlyOwner {
_FRAG_TEMPLATE_ = newFragTemplate;
emit ChangeFragTemplate(newFragTemplate);
}
function updateMtFeeRateTemplate(address newMtFeeRateTemplate) external onlyOwner {
_MT_FEE_RATE_MODEL_ = newMtFeeRateTemplate;
emit ChangeMtFeeRateTemplate(newMtFeeRateTemplate);
}
function updateDvmTemplate(address newDvmTemplate) external onlyOwner {
_DVM_TEMPLATE_ = newDvmTemplate;
emit ChangeDvmTemplate(newDvmTemplate);
}
function updateBuyoutModel(address newBuyoutModel) external onlyOwner {
_BUYOUT_MODEL_ = newBuyoutModel;
emit ChangeBuyoutModel(newBuyoutModel);
}
function updateMaintainer(address newMaintainer) external onlyOwner {
_DEFAULT_MAINTAINER_ = newMaintainer;
emit ChangeMaintainer(newMaintainer);
}
//============= Internal ================
function _deposit(
address from,
address to,
address token,
uint256 amount,
bool isETH
) internal {
if (isETH) {
if (amount > 0) {
IWETH(_WETH_).deposit{value: amount}();
if (to != address(this)) SafeERC20.safeTransfer(IERC20(_WETH_), to, amount);
}
} else {
IDODOApproveProxy(_DODO_APPROVE_PROXY_).claimTokens(token, from, to, amount);
}
}
}