nftproxy&®ister&&fix
This commit is contained in:
@@ -27,7 +27,11 @@ contract NFTCollateralVault is InitializableOwnable, IERC721Receiver, IERC1155Re
|
||||
}
|
||||
NftInfo[] public nftInfos;
|
||||
|
||||
constructor (string memory _name) public {
|
||||
function init(
|
||||
address owner,
|
||||
string memory _name
|
||||
) external {
|
||||
initOwner(owner);
|
||||
name = _name;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
interface ICollateralVault {
|
||||
function _OWNER_() external returns (address);
|
||||
|
||||
function transferOwner(address to) external;
|
||||
function init(address owner, string memory name) external;
|
||||
|
||||
function directTransferOwnership(address newOwner) external;
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@ import {SafeMath} from "../lib/SafeMath.sol";
|
||||
import {DecimalMath} from "../lib/DecimalMath.sol";
|
||||
import {IERC20} from "../intf/IERC20.sol";
|
||||
import {SafeERC20} from "../lib/SafeERC20.sol";
|
||||
import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
|
||||
import {Ownable} from "../lib/Ownable.sol";
|
||||
|
||||
contract FeeDistributor is InitializableOwnable {
|
||||
contract FeeDistributor {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
@@ -24,46 +23,55 @@ contract FeeDistributor is InitializableOwnable {
|
||||
address public _QUOTE_TOKEN_;
|
||||
uint256 public _BASE_RESERVE_;
|
||||
uint256 public _QUOTE_RESERVE_;
|
||||
uint256 public _BASE_REWARD_RATIO_;
|
||||
uint256 public _QUOTE_REWARD_RATIO_;
|
||||
|
||||
address public _STAKE_VAULT_;
|
||||
address public _STAKE_TOKEN_;
|
||||
uint256 public _STAKE_RESERVE_;
|
||||
mapping(address => uint256) internal _BASE_DEBT_;
|
||||
mapping(address => uint256) internal _QUOTE_DEBT_;
|
||||
mapping(address => uint256) internal _SHARES_;
|
||||
|
||||
uint256 public _BASE_REWARD_RATIO_;
|
||||
mapping(address => uint256) internal _USER_BASE_REWARDS_;
|
||||
mapping(address => uint256) internal _USER_BASE_PER_SHARE_;
|
||||
|
||||
uint256 public _QUOTE_REWARD_RATIO_;
|
||||
mapping(address => uint256) internal _USER_QUOTE_REWARDS_;
|
||||
mapping(address => uint256) internal _USER_QUOTE_PER_SHARE_;
|
||||
|
||||
mapping(address => uint256) internal _SHARES_;
|
||||
|
||||
bool internal _FEE_INITIALIZED_;
|
||||
|
||||
function init(
|
||||
address baseToken,
|
||||
address quoteToken,
|
||||
address stakeToken
|
||||
) external {
|
||||
require(!_FEE_INITIALIZED_, "ALREADY_INITIALIZED");
|
||||
_FEE_INITIALIZED_ = true;
|
||||
|
||||
_BASE_TOKEN_ = baseToken;
|
||||
_QUOTE_TOKEN_ = quoteToken;
|
||||
_STAKE_TOKEN_ = stakeToken;
|
||||
_BASE_REWARD_RATIO_ = DecimalMath.ONE;
|
||||
_QUOTE_REWARD_RATIO_ = DecimalMath.ONE;
|
||||
_STAKE_VAULT_ = address(new StakeVault());
|
||||
}
|
||||
|
||||
//TODO: 用户的手续费base or quote 直接转到该合约中,stakeVault保存的是?
|
||||
function stake(address to) external {
|
||||
_accuReward();
|
||||
_updateGlobalState();
|
||||
_updateUserReward(to);
|
||||
uint256 stakeVault = IERC20(_STAKE_TOKEN_).balanceOf(_STAKE_VAULT_);
|
||||
uint256 stakeInput = stakeVault.sub(_STAKE_RESERVE_);
|
||||
_addShares(stakeInput, to);
|
||||
}
|
||||
|
||||
function claim(address to) external {
|
||||
_accuReward();
|
||||
_updateGlobalState();
|
||||
_updateUserReward(msg.sender);
|
||||
_claim(msg.sender, to);
|
||||
}
|
||||
|
||||
function unstake(uint256 amount, address to, bool withClaim) external {
|
||||
require(_SHARES_[msg.sender]>=amount, "STAKE BALANCE ONT ENOUGH");
|
||||
_accuReward();
|
||||
_updateGlobalState();
|
||||
_updateUserReward(msg.sender);
|
||||
|
||||
if (withClaim) {
|
||||
_claim(msg.sender, to);
|
||||
@@ -73,30 +81,18 @@ contract FeeDistributor is InitializableOwnable {
|
||||
StakeVault(_STAKE_VAULT_).transferOut(_STAKE_TOKEN_, amount, to);
|
||||
}
|
||||
|
||||
// ============ Internal ============
|
||||
|
||||
function _claim(address sender, address to) internal {
|
||||
uint256 allBase = DecimalMath.mulFloor(_SHARES_[sender], _BASE_REWARD_RATIO_);
|
||||
uint256 allQuote = DecimalMath.mulFloor(_SHARES_[sender], _QUOTE_REWARD_RATIO_);
|
||||
IERC20(_BASE_TOKEN_).safeTransfer(to, allBase.sub(_BASE_DEBT_[sender]));
|
||||
IERC20(_QUOTE_TOKEN_).safeTransfer(to, allQuote.sub(_QUOTE_DEBT_[sender]));
|
||||
_BASE_DEBT_[sender] = allBase;
|
||||
_QUOTE_DEBT_[sender] = allQuote;
|
||||
uint256 allBase = _USER_BASE_REWARDS_[sender];
|
||||
uint256 allQuote = _USER_QUOTE_REWARDS_[sender];
|
||||
IERC20(_BASE_TOKEN_).safeTransfer(to, allBase);
|
||||
IERC20(_QUOTE_TOKEN_).safeTransfer(to, allQuote);
|
||||
_USER_BASE_REWARDS_[sender] = 0;
|
||||
_USER_BASE_REWARDS_[sender] = 0;
|
||||
}
|
||||
|
||||
function _addShares(uint256 amount, address to) internal {
|
||||
_SHARES_[to] = _SHARES_[to].add(amount);
|
||||
_BASE_DEBT_[to] = _BASE_DEBT_[to].add(DecimalMath.mulCeil(amount, _BASE_REWARD_RATIO_));
|
||||
_QUOTE_DEBT_[to] = _QUOTE_DEBT_[to].add(DecimalMath.mulCeil(amount, _QUOTE_REWARD_RATIO_));
|
||||
_STAKE_RESERVE_ = IERC20(_STAKE_TOKEN_).balanceOf(_STAKE_VAULT_);
|
||||
}
|
||||
|
||||
function _removeShares(uint256 amount, address from) internal {
|
||||
_SHARES_[from] = _SHARES_[from].sub(amount);
|
||||
_BASE_DEBT_[from] = _BASE_DEBT_[from].sub(DecimalMath.mulFloor(amount, _BASE_REWARD_RATIO_));
|
||||
_QUOTE_DEBT_[from] = _QUOTE_DEBT_[from].sub(DecimalMath.mulFloor(amount, _QUOTE_REWARD_RATIO_));
|
||||
_STAKE_RESERVE_ = IERC20(_STAKE_TOKEN_).balanceOf(_STAKE_VAULT_);
|
||||
}
|
||||
|
||||
function _accuReward() internal {
|
||||
function _updateGlobalState() internal {
|
||||
uint256 baseInput = IERC20(_BASE_TOKEN_).balanceOf(address(this)).sub(_BASE_RESERVE_);
|
||||
uint256 quoteInput = IERC20(_QUOTE_TOKEN_).balanceOf(address(this)).sub(_QUOTE_RESERVE_);
|
||||
_BASE_REWARD_RATIO_ = _BASE_REWARD_RATIO_.add(DecimalMath.divFloor(baseInput, _STAKE_RESERVE_));
|
||||
@@ -105,6 +101,31 @@ contract FeeDistributor is InitializableOwnable {
|
||||
_QUOTE_RESERVE_ = _QUOTE_RESERVE_.add(quoteInput);
|
||||
}
|
||||
|
||||
function _updateUserReward(address user) internal {
|
||||
_USER_BASE_REWARDS_[user] = DecimalMath.mulFloor(
|
||||
_SHARES_[user],
|
||||
_BASE_REWARD_RATIO_.sub(_USER_BASE_PER_SHARE_[user])
|
||||
).add(_USER_BASE_REWARDS_[user]);
|
||||
|
||||
_USER_BASE_PER_SHARE_[user] = _BASE_REWARD_RATIO_;
|
||||
|
||||
_USER_QUOTE_REWARDS_[user] = DecimalMath.mulFloor(
|
||||
_SHARES_[user],
|
||||
_QUOTE_REWARD_RATIO_.sub(_USER_QUOTE_PER_SHARE_[user])
|
||||
).add(_USER_QUOTE_REWARDS_[user]);
|
||||
|
||||
_USER_QUOTE_PER_SHARE_[user] = _QUOTE_REWARD_RATIO_;
|
||||
}
|
||||
|
||||
function _addShares(uint256 amount, address to) internal {
|
||||
_SHARES_[to] = _SHARES_[to].add(amount);
|
||||
_STAKE_RESERVE_ = IERC20(_STAKE_TOKEN_).balanceOf(_STAKE_VAULT_);
|
||||
}
|
||||
|
||||
function _removeShares(uint256 amount, address from) internal {
|
||||
_SHARES_[from] = _SHARES_[from].sub(amount);
|
||||
_STAKE_RESERVE_ = IERC20(_STAKE_TOKEN_).balanceOf(_STAKE_VAULT_);
|
||||
}
|
||||
}
|
||||
|
||||
contract StakeVault is Ownable {
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
|
||||
import {ICloneFactory} from "../lib/CloneFactory.sol";
|
||||
import {IDVM} from "../DODOVendingMachine/intf/IDVM.sol";
|
||||
|
||||
// 这一部分最后写,先把前面的接口定下来
|
||||
// 业务流程(没有NFT的情况下)
|
||||
// 1. 上传媒体,创建NFTCollateralVault
|
||||
// 2. 把CollateralVault提供给FragmentFactory做碎片化
|
||||
// (已经有NFT的情况下)
|
||||
// 1. 将NFT打包成NFTCollateralVault
|
||||
// 2. 把CollateralVault提供给FragmentFactory做碎片化
|
||||
// 所以总体来说,factory只需要处理vault已经建立好之后的拼装工作即可
|
||||
|
||||
interface IFragmentFactory {
|
||||
function createFragment() external returns (address newVendingMachine);
|
||||
}
|
||||
|
||||
contract FragmentFactory is InitializableOwnable {
|
||||
// ============ Templates ============
|
||||
|
||||
address public immutable _CLONE_FACTORY_;
|
||||
address public immutable _MT_FEE_RATE_MODEL_;
|
||||
address public _DVM_TEMPLATE_;
|
||||
address public _FEE_DISTRIBUTOR_TEMPLATE_;
|
||||
address public _FRAGMENT_TEMPLATE_;
|
||||
|
||||
// ============ Registry ============
|
||||
|
||||
// base -> quote -> DVM address list
|
||||
mapping(address => mapping(address => address[])) public _REGISTRY_;
|
||||
// creator -> DVM address list
|
||||
mapping(address => address[]) public _USER_REGISTRY_;
|
||||
|
||||
// ============ Functions ============
|
||||
|
||||
constructor(
|
||||
address cloneFactory,
|
||||
address dvmTemplate,
|
||||
address feeDistributorTemplate,
|
||||
address fragmentTemplate,
|
||||
address mtFeeRateModel
|
||||
) public {
|
||||
_CLONE_FACTORY_ = cloneFactory;
|
||||
_DVM_TEMPLATE_ = dvmTemplate;
|
||||
_FEE_DISTRIBUTOR_TEMPLATE_ = feeDistributorTemplate;
|
||||
_FRAGMENT_TEMPLATE_ = fragmentTemplate;
|
||||
_MT_FEE_RATE_MODEL_ = mtFeeRateModel;
|
||||
}
|
||||
|
||||
function createFragment(
|
||||
address owner,
|
||||
address vault,
|
||||
address quoteToken,
|
||||
uint256 mtFeeRate,
|
||||
uint256 i,
|
||||
uint256 k,
|
||||
uint256 totalSupply,
|
||||
uint256 ownerRatio,
|
||||
uint256 buyoutTimestamp
|
||||
) external returns (address newFragment) {
|
||||
// newFragment = ICloneFactory(_CLONE_FACTORY_).clone(_FRAGMENT_TEMPLATE_);
|
||||
// newVendingMachine = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_TEMPLATE_);
|
||||
// newFeeDistributor = ICloneFactory(_CLONE_FACTORY_).clone(_FEE_DISTRIBUTOR_TEMPLATE_);
|
||||
|
||||
// {
|
||||
// IFeeDistributor(newFeeDistributor).init(newFragment, quoteToken, newFragment);
|
||||
// }
|
||||
|
||||
// {
|
||||
// IDVM(newVendingMachine).init(
|
||||
// newFeeDistributor,
|
||||
// newFragment,
|
||||
// quoteToken,
|
||||
// 0,
|
||||
// mtFeeRateModel,
|
||||
// i,
|
||||
// k,
|
||||
// false
|
||||
// );
|
||||
// IFeeRateRegistry(mtFeeRateModel).set(newVendingMachine, mtFeeRate);
|
||||
// }
|
||||
|
||||
// {
|
||||
// IFragment(newFragment).init(owner, newVendingMachine, vault, totalSupply, ownerRatio, buyoutTimestamp);
|
||||
// }
|
||||
}
|
||||
}
|
||||
86
contracts/Factory/Registries/DODONFTRegistry.sol
Normal file
86
contracts/Factory/Registries/DODONFTRegistry.sol
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
|
||||
|
||||
interface IDODONFTRegistry {
|
||||
function addRegistry(
|
||||
address vault,
|
||||
address fragment,
|
||||
address feeDistributor,
|
||||
address dvm
|
||||
) external;
|
||||
}
|
||||
|
||||
/**
|
||||
* @title DODONFT Registry
|
||||
* @author DODO Breeder
|
||||
*
|
||||
* @notice Register DODONFT Pools
|
||||
*/
|
||||
contract DODONFTRegistry is InitializableOwnable {
|
||||
|
||||
mapping (address => bool) public isAdminListed;
|
||||
|
||||
// ============ Registry ============
|
||||
|
||||
// Frag -> FeeDistributor
|
||||
mapping(address => address) public _FRAG_FEE_REGISTRY_;
|
||||
// DVM -> FeeDistributor
|
||||
mapping(address => address) public _DVM_FEE_REGISTRY_;
|
||||
// Vault -> Frag
|
||||
mapping(address => address) public _VAULT_FRAG_REGISTRY_;
|
||||
|
||||
// ============ Events ============
|
||||
|
||||
event NewRegistry(
|
||||
address vault,
|
||||
address fragment,
|
||||
address feeDistributor,
|
||||
address dvm
|
||||
);
|
||||
|
||||
event RemoveRegistry(address fragment);
|
||||
|
||||
|
||||
// ============ Admin Operation Functions ============
|
||||
|
||||
function addRegistry(
|
||||
address vault,
|
||||
address fragment,
|
||||
address feeDistributor,
|
||||
address dvm
|
||||
) external {
|
||||
require(isAdminListed[msg.sender], "ACCESS_DENIED");
|
||||
_FRAG_FEE_REGISTRY_[fragment] = feeDistributor;
|
||||
_DVM_FEE_REGISTRY_[dvm] = feeDistributor;
|
||||
_VAULT_FRAG_REGISTRY_[vault] = fragment;
|
||||
emit NewRegistry(vault, fragment, feeDistributor, dvm);
|
||||
}
|
||||
|
||||
function removeRegistry(
|
||||
address vault,
|
||||
address fragment,
|
||||
address dvm
|
||||
) external onlyOwner {
|
||||
_FRAG_FEE_REGISTRY_[fragment] = address(0);
|
||||
_DVM_FEE_REGISTRY_[dvm] = address(0);
|
||||
_VAULT_FRAG_REGISTRY_[vault] = address(0);
|
||||
emit RemoveRegistry(fragment);
|
||||
}
|
||||
|
||||
function addAmindList (address contractAddr) public onlyOwner {
|
||||
isAdminListed[contractAddr] = true;
|
||||
}
|
||||
|
||||
function removeWhiteList (address contractAddr) public onlyOwner {
|
||||
isAdminListed[contractAddr] = false;
|
||||
}
|
||||
}
|
||||
85
contracts/Factory/TokenFactory.sol
Normal file
85
contracts/Factory/TokenFactory.sol
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
//TODO:
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {ICloneFactory} from "../lib/CloneFactory.sol";
|
||||
import {InitializableERC20} from "../external/ERC20/InitializableERC20.sol";
|
||||
import {InitializableMintableERC20} from "../external/ERC20/InitializableMintableERC20.sol";
|
||||
|
||||
/**
|
||||
* @title DODO TokenFactory
|
||||
* @author DODO Breeder
|
||||
*
|
||||
* @notice Help user to create erc20 && erc721 && erc1155 token
|
||||
*/
|
||||
contract TokenFacotry {
|
||||
// ============ Templates ============
|
||||
|
||||
address public immutable _CLONE_FACTORY_;
|
||||
address public immutable _ERC20_TEMPLATE_;
|
||||
address public immutable _MINTABLE_ERC20_TEMPLATE_;
|
||||
|
||||
// ============ Events ============
|
||||
|
||||
event NewERC20(address erc20, address creator, bool isMintable);
|
||||
|
||||
// ============ Registry ============
|
||||
// creator -> token address list
|
||||
mapping(address => address[]) public _USER_STD_REGISTRY_;
|
||||
|
||||
// ============ Functions ============
|
||||
|
||||
constructor(
|
||||
address cloneFactory,
|
||||
address erc20Template,
|
||||
address mintableErc20Template
|
||||
) public {
|
||||
_CLONE_FACTORY_ = cloneFactory;
|
||||
_ERC20_TEMPLATE_ = erc20Template;
|
||||
_MINTABLE_ERC20_TEMPLATE_ = mintableErc20Template;
|
||||
}
|
||||
|
||||
function createStdERC20(
|
||||
uint256 totalSupply,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 decimals
|
||||
) external returns (address newERC20) {
|
||||
newERC20 = ICloneFactory(_CLONE_FACTORY_).clone(_ERC20_TEMPLATE_);
|
||||
InitializableERC20(newERC20).init(msg.sender, totalSupply, name, symbol, decimals);
|
||||
_USER_STD_REGISTRY_[msg.sender].push(newERC20);
|
||||
emit NewERC20(newERC20, msg.sender, false);
|
||||
}
|
||||
|
||||
function createMintableERC20(
|
||||
uint256 initSupply,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 decimals
|
||||
) external returns (address newMintableERC20) {
|
||||
newMintableERC20 = ICloneFactory(_CLONE_FACTORY_).clone(_MINTABLE_ERC20_TEMPLATE_);
|
||||
InitializableMintableERC20(newMintableERC20).init(
|
||||
msg.sender,
|
||||
initSupply,
|
||||
name,
|
||||
symbol,
|
||||
decimals
|
||||
);
|
||||
emit NewERC20(newMintableERC20, msg.sender, true);
|
||||
}
|
||||
|
||||
|
||||
function getTokenByUser(address user)
|
||||
external
|
||||
view
|
||||
returns (address[] memory tokens)
|
||||
{
|
||||
return _USER_STD_REGISTRY_[user];
|
||||
}
|
||||
}
|
||||
@@ -7,17 +7,14 @@
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
import {SafeMath} from "../lib/SafeMath.sol";
|
||||
import {SafeERC20} from "../lib/SafeERC20.sol";
|
||||
import {DecimalMath} from "../lib/DecimalMath.sol";
|
||||
import {IDVM} from "../DODOVendingMachine/intf/IDVM.sol";
|
||||
import {IERC20} from "../intf/IERC20.sol";
|
||||
import {InitializableERC20} from "../external/ERC20/InitializableERC20.sol";
|
||||
|
||||
interface ICollateralVault {
|
||||
function directTransferOwnership(address newOwner) external;
|
||||
}
|
||||
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
import {SafeERC20} from "../../lib/SafeERC20.sol";
|
||||
import {DecimalMath} from "../../lib/DecimalMath.sol";
|
||||
import {IDVM} from "../../DODOVendingMachine/intf/IDVM.sol";
|
||||
import {IDODOCallee} from "../../intf/IDODOCallee.sol";
|
||||
import {IERC20} from "../../intf/IERC20.sol";
|
||||
import {InitializableERC20} from "../../external/ERC20/InitializableERC20.sol";
|
||||
import {ICollateralVault} from "../../CollateralVault/intf/ICollateralVault.sol";
|
||||
|
||||
contract Fragment is InitializableERC20 {
|
||||
using SafeMath for uint256;
|
||||
@@ -105,11 +102,20 @@ contract Fragment is InitializableERC20 {
|
||||
}
|
||||
|
||||
|
||||
function redeem(address to) external {
|
||||
function redeem(address to, bytes calldata data) external {
|
||||
require(_IS_BUYOUT_, "DODOFragment: NEED_BUYOUT");
|
||||
|
||||
IERC20(_QUOTE_).safeTransfer(to, DecimalMath.mulFloor(_BUYOUT_PRICE_, balances[to]));
|
||||
_clearBalance(to);
|
||||
uint256 quoteAmount = DecimalMath.mulFloor(_BUYOUT_PRICE_, balances[msg.sender]);
|
||||
IERC20(_QUOTE_).safeTransfer(to, quoteAmount);
|
||||
_clearBalance(msg.sender);
|
||||
|
||||
if (data.length > 0) {
|
||||
IDODOCallee(to).NFTRedeemCall(
|
||||
msg.sender,
|
||||
quoteAmount,
|
||||
data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getBuyoutRequirement() external view returns (uint256 requireQuote){
|
||||
28
contracts/GeneralizedFragment/intf/IFragment.sol
Normal file
28
contracts/GeneralizedFragment/intf/IFragment.sol
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
|
||||
interface IFragment {
|
||||
|
||||
function init(
|
||||
address dvm,
|
||||
address vaultPreOwner,
|
||||
address collateralVault,
|
||||
uint256 totalSupply,
|
||||
uint256 ownerRatio,
|
||||
uint256 buyoutTimestamp,
|
||||
bool isOpenBuyout
|
||||
) external;
|
||||
|
||||
function buyout(address newVaultOwner) external;
|
||||
|
||||
function redeem(address to) external;
|
||||
|
||||
function _QUOTE_() external view returns (address);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {IDODOV2} from "../intf/IDODOV2.sol";
|
||||
import {IFragment} from "../../GeneralizedFragment/intf/IFragment.sol";
|
||||
import {IERC20} from "../../intf/IERC20.sol";
|
||||
import {IWETH} from "../../intf/IWETH.sol";
|
||||
import {SafeERC20} from "../../lib/SafeERC20.sol";
|
||||
@@ -64,6 +65,15 @@ contract DODOCalleeHelper is ReentrancyGuard {
|
||||
_withdraw(assetTo, _quoteToken, quoteAmount, _quoteToken == _WETH_);
|
||||
}
|
||||
|
||||
function NFTRedeemCall(
|
||||
address payable assetTo,
|
||||
uint256 quoteAmount,
|
||||
bytes calldata
|
||||
) external preventReentrant {
|
||||
address _quoteToken = IFragment(msg.sender)._QUOTE_();
|
||||
_withdraw(assetTo, _quoteToken, quoteAmount, _quoteToken == _WETH_);
|
||||
}
|
||||
|
||||
function _withdraw(
|
||||
address payable to,
|
||||
address token,
|
||||
|
||||
195
contracts/SmartRoute/proxies/DODONFTProxy.sol
Normal file
195
contracts/SmartRoute/proxies/DODONFTProxy.sol
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
|
||||
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 {IDODOV2} from "../intf/IDODOV2.sol";
|
||||
import {IFragment} from "../../GeneralizedFragment/intf/IFragment.sol";
|
||||
import {IFeeDistributor} from "../../intf/IFeeDistributor.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 _DVM_FACTORY_;
|
||||
address public immutable _NFT_REGISTY_;
|
||||
|
||||
address public _VAULT_TEMPLATE_;
|
||||
address public _FRAG_TEMPLATE_;
|
||||
address public _FEE_TEMPLATE_;
|
||||
|
||||
// ============ Events ============
|
||||
event ChangeVaultTemplate(address newVaultTemplate);
|
||||
event ChangeFragTemplate(address newFragTemplate);
|
||||
event ChangeFeeTemplate(address newFeeTemplate);
|
||||
event CreateNFTCollateralVault(address creator, address vault);
|
||||
event CreateFragment(address vault, address fragment, address dvm, address feeDistributor);
|
||||
event Buyout(address from, address fragment, uint256 amount);
|
||||
event Stake(address from, address feeDistributor, uint256 amount);
|
||||
|
||||
|
||||
fallback() external payable {}
|
||||
|
||||
receive() external payable {}
|
||||
|
||||
constructor(
|
||||
address cloneFactory,
|
||||
address payable weth,
|
||||
address dodoApproveProxy,
|
||||
address dvmFactory,
|
||||
address vaultTemplate,
|
||||
address fragTemplate,
|
||||
address feeTemplate,
|
||||
address nftRegistry
|
||||
) public {
|
||||
_CLONE_FACTORY_ = cloneFactory;
|
||||
_WETH_ = weth;
|
||||
_DODO_APPROVE_PROXY_ = dodoApproveProxy;
|
||||
_DVM_FACTORY_ = dvmFactory;
|
||||
_VAULT_TEMPLATE_ = vaultTemplate;
|
||||
_FRAG_TEMPLATE_ = fragTemplate;
|
||||
_FEE_TEMPLATE_ = feeTemplate;
|
||||
_NFT_REGISTY_ = nftRegistry;
|
||||
}
|
||||
|
||||
function createNFTCollateralVault(string memory name) external returns (address newVault) {
|
||||
newVault = ICloneFactory(_CLONE_FACTORY_).clone(_VAULT_TEMPLATE_);
|
||||
ICollateralVault(newVault).init(msg.sender, name);
|
||||
emit CreateNFTCollateralVault(msg.sender, newVault);
|
||||
}
|
||||
|
||||
function createFragment(
|
||||
address quoteToken,
|
||||
address collateralVault,
|
||||
address vaultPreOwner,
|
||||
address stakeToken,
|
||||
uint256[] calldata dvmParams, //0 - lpFeeRate, 1 - I, 2 - K
|
||||
uint256[] calldata fragParams, //0 - totalSupply, 1 - ownerRatio, 2 - buyoutTimestamp
|
||||
bool isOpenBuyout
|
||||
) external returns (address newFragment, address newDvm, address newFeeDistributor) {
|
||||
require(msg.sender == collateralVault, "NEED_BE_CALLED_BY_VAULT");
|
||||
|
||||
newFragment = ICloneFactory(_CLONE_FACTORY_).clone(_FRAG_TEMPLATE_);
|
||||
address _quoteToken = quoteToken == _ETH_ADDRESS_ ? _WETH_ : quoteToken;
|
||||
|
||||
{
|
||||
uint256[] memory _dvmParams = dvmParams;
|
||||
uint256[] memory _fragParams = fragParams;
|
||||
|
||||
newDvm = IDODOV2(_DVM_FACTORY_).createDODOVendingMachine(
|
||||
newFragment,
|
||||
_quoteToken,
|
||||
_dvmParams[0],
|
||||
_dvmParams[1],
|
||||
_dvmParams[2],
|
||||
false
|
||||
);
|
||||
|
||||
IFragment(newFragment).init(
|
||||
newDvm,
|
||||
vaultPreOwner,
|
||||
msg.sender,
|
||||
_fragParams[0],
|
||||
_fragParams[1],
|
||||
_fragParams[2],
|
||||
isOpenBuyout
|
||||
);
|
||||
}
|
||||
|
||||
ICollateralVault(msg.sender).directTransferOwnership(newFragment);
|
||||
|
||||
|
||||
if(stakeToken == address(0)) {
|
||||
newFeeDistributor = address(0);
|
||||
} else {
|
||||
newFeeDistributor = ICloneFactory(_CLONE_FACTORY_).clone(_FEE_TEMPLATE_);
|
||||
IFeeDistributor(newFeeDistributor).init(newFragment, _quoteToken, stakeToken);
|
||||
}
|
||||
|
||||
IDODONFTRegistry(_NFT_REGISTY_).addRegistry(msg.sender, newFragment, newFeeDistributor, newDvm);
|
||||
|
||||
emit CreateFragment(msg.sender, newFragment, newDvm, newFeeDistributor);
|
||||
}
|
||||
|
||||
function buyout(
|
||||
address fragment,
|
||||
uint256 quoteAmount,
|
||||
uint8 flag // 0 - ERC20, 1 - quoteInETH
|
||||
) external payable preventReentrant {
|
||||
_deposit(msg.sender, fragment, IFragment(fragment)._QUOTE_(), quoteAmount, flag == 1);
|
||||
IFragment(fragment).buyout(msg.sender);
|
||||
emit Buyout(msg.sender, fragment, quoteAmount);
|
||||
}
|
||||
|
||||
function stakeToFeeDistributor(
|
||||
address feeDistributor,
|
||||
uint256 stakeAmount,
|
||||
uint8 flag // 0 - ERC20, 1 - ETH
|
||||
) external payable preventReentrant {
|
||||
_deposit(msg.sender, feeDistributor, IFeeDistributor(feeDistributor)._STAKE_TOKEN_(), stakeAmount, flag == 1);
|
||||
IFeeDistributor(feeDistributor).stake(msg.sender);
|
||||
emit Stake(msg.sender, feeDistributor, stakeAmount);
|
||||
}
|
||||
|
||||
//============= 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 updateFeeTemplate(address newFeeTemplate) external onlyOwner {
|
||||
_FEE_TEMPLATE_ = newFeeTemplate;
|
||||
emit ChangeFeeTemplate(newFeeTemplate);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,4 +50,10 @@ interface IDODOCallee {
|
||||
uint256 quoteAmount,
|
||||
bytes calldata data
|
||||
) external;
|
||||
|
||||
function NFTRedeemCall(
|
||||
address payable assetTo,
|
||||
uint256 quoteAmount,
|
||||
bytes calldata
|
||||
) external;
|
||||
}
|
||||
|
||||
21
contracts/intf/IFeeDistributor.sol
Normal file
21
contracts/intf/IFeeDistributor.sol
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
interface IFeeDistributor {
|
||||
function init(
|
||||
address baseToken,
|
||||
address quoteToken,
|
||||
address stakeToken
|
||||
) external;
|
||||
|
||||
function stake(address to) external;
|
||||
|
||||
function _STAKE_TOKEN_() external view returns(address);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user