diff --git a/contracts/lib/FeeRateImpl.sol b/contracts/lib/FeeRateImpl.sol new file mode 100644 index 0000000..9462129 --- /dev/null +++ b/contracts/lib/FeeRateImpl.sol @@ -0,0 +1,106 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +import {InitializableOwnable} from "./InitializableOwnable.sol"; +import {IERC20} from "../intf/IERC20.sol"; +import {SafeMath} from "./SafeMath.sol"; + +interface ICrowdPooling { + function _QUOTE_RESERVE_() external view returns (uint256); + function getShares(address user) external view returns (uint256); +} + +interface IFee { + function getUserFee(address user) external view returns (uint256); +} + +interface IQuota { + function getUserQuota(address user) external view returns (uint256); +} + +contract FeeRateImpl is InitializableOwnable { + using SafeMath for uint256; + + struct CPPoolInfo { + address quoteToken; + uint256 globalQuota; + address feeAddr; + address quotaAddr; + } + + mapping(address => CPPoolInfo) cpPools; + + function addCpPoolInfo(address cpPool, address quoteToken, uint256 globalQuota, address feeAddr, address quotaAddr) external onlyOwner { + CPPoolInfo memory cpPoolInfo = CPPoolInfo({ + quoteToken: quoteToken, + globalQuota: globalQuota, + feeAddr: feeAddr, + quotaAddr: quotaAddr + }); + cpPools[cpPool] = cpPoolInfo; + } + + function setCpPoolInfo(address cpPool, address quoteToken, uint256 globalQuota, address feeAddr, address quotaAddr) external onlyOwner { + cpPools[cpPool].quoteToken = quoteToken; + cpPools[cpPool].globalQuota = globalQuota; + cpPools[cpPool].feeAddr = feeAddr; + cpPools[cpPool].quotaAddr = quotaAddr; + } + + function getFeeRate(address pool, address user) external view returns (uint256) { + CPPoolInfo memory cpPoolInfo = cpPools[pool]; + address quoteToken = cpPoolInfo.quoteToken; + if(quoteToken == address(0)) { + return 0; + }else { + uint256 userInput = IERC20(quoteToken).balanceOf(pool).sub(ICrowdPooling(pool)._QUOTE_RESERVE_()); + uint256 userStake = ICrowdPooling(pool).getShares(user); + address feeAddr = cpPoolInfo.feeAddr; + address quotaAddr = cpPoolInfo.quotaAddr; + uint256 curQuota = cpPoolInfo.globalQuota; + if(quotaAddr != address(0)) + curQuota = IQuota(quotaAddr).getUserQuota(user); + + if(curQuota != 0 && userInput.add(userStake) > curQuota) { + return 2 * 10**18; //over hardcap, will revert + } else { + if(feeAddr == address(0)) { + return 0; + }else { + return IFee(feeAddr).getUserFee(user); + } + } + } + } + + + function getCPInfoByUser(address pool, address user) external view returns(bool isHaveCap, uint256 curQuota, uint256 userFee) { + CPPoolInfo memory cpPoolInfo = cpPools[pool]; + address quotaAddr = cpPoolInfo.quotaAddr; + curQuota = cpPoolInfo.globalQuota; + if(quotaAddr != address(0)) + curQuota = IQuota(quotaAddr).getUserQuota(user); + + if(curQuota == 0) { + isHaveCap = false; + }else { + isHaveCap = true; + uint256 userStake = ICrowdPooling(pool).getShares(user); + curQuota = curQuota.sub(userStake); + } + + address feeAddr = cpPoolInfo.feeAddr; + if(feeAddr == address(0)) { + userFee = 0; + } else { + userFee = IFee(feeAddr).getUserFee(user); + } + } +} diff --git a/migrations/5_deploy_periphery.js b/migrations/5_deploy_periphery.js index e8ce9f8..aefb227 100644 --- a/migrations/5_deploy_periphery.js +++ b/migrations/5_deploy_periphery.js @@ -10,6 +10,7 @@ const vDODOToken = artifacts.require("vDODOToken"); const DODOCirculationHelper = artifacts.require("DODOCirculationHelper"); const DODOApproveProxy = artifacts.require("DODOApproveProxy"); const DODOMine = artifacts.require("DODOMine"); +const FeeRateImpl = artifacts.require("FeeRateImpl"); module.exports = async (deployer, network, accounts) => { @@ -50,7 +51,15 @@ module.exports = async (deployer, network, accounts) => { logger.log("network type: " + network); logger.log("Deploy time: " + new Date().toLocaleString()); - + if(deploySwitch.FEERATEIMPL) { + logger.log("Deploy type: FeeRateImpl"); + await deployer.deploy(FeeRateImpl); + var FeeRateImplAddress = FeeRateImpl.address; + logger.log("FeeRateImplAddress: ", FeeRateImplAddress); + const feeRateImplInstance = await FeeRateImpl.at(FeeRateImplAddress); + var tx = await feeRateImplInstance.initOwner(multiSigAddress); + logger.log("Init feeRateImpl Tx:", tx.tx); + } if (deploySwitch.MINE) { logger.log("Deploy type: DODOMine"); diff --git a/truffle-config.js b/truffle-config.js index b37b015..db998b1 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -51,7 +51,8 @@ module.exports = { vDODOToken: false, CALLEE: false, DODORecharge: false, - MINE: false + MINE: false, + FEERATEIMPL: false }, networks: {