Merge branch 'feature/V2' of github.com:DODOEX/contractV2 into feature/V2
This commit is contained in:
@@ -70,61 +70,32 @@ contract CPFunding is CPStorage {
|
||||
function settle() external phaseSettlement preventReentrant {
|
||||
_settle();
|
||||
|
||||
(uint256 poolBase, uint256 poolQuote) = getSettleResult();
|
||||
_UNUSED_QUOTE_ = _QUOTE_TOKEN_.balanceOf(address(this)).sub(poolQuote);
|
||||
_UNUSED_BASE_ = _BASE_TOKEN_.balanceOf(address(this)).sub(poolBase);
|
||||
(uint256 poolBase, uint256 poolQuote, uint256 poolI, uint256 unUsedBase, uint256 unUsedQuote) = getSettleResult();
|
||||
_UNUSED_BASE_ = unUsedBase;
|
||||
_UNUSED_QUOTE_ = unUsedQuote;
|
||||
|
||||
// Try to make midPrice equal to avgPrice
|
||||
// k=1, If quote and base are not balanced, one side must be cut off
|
||||
// DVM truncated quote, but if more quote than base entering the pool, we need set the quote to the base
|
||||
address _poolBaseToken;
|
||||
address _poolQuoteToken;
|
||||
|
||||
// m = avgPrice
|
||||
// i = m (1-quote/(m*base))
|
||||
// if quote = m*base i = 1
|
||||
// if quote > m*base reverse
|
||||
{
|
||||
address _poolBaseToken;
|
||||
address _poolQuoteToken;
|
||||
uint256 _poolI;
|
||||
|
||||
uint256 avgPrice = _UNUSED_BASE_ == 0
|
||||
? _I_
|
||||
: DecimalMath.divCeil(poolQuote, _UNUSED_BASE_);
|
||||
uint256 baseDepth = DecimalMath.mulFloor(avgPrice, poolBase);
|
||||
|
||||
if (poolQuote == 0) {
|
||||
// ask side only DVM
|
||||
_poolBaseToken = address(_BASE_TOKEN_);
|
||||
_poolQuoteToken = address(_QUOTE_TOKEN_);
|
||||
_poolI = _I_;
|
||||
} else if (_UNUSED_BASE_== poolBase) {
|
||||
// standard bonding curve
|
||||
_poolBaseToken = address(_BASE_TOKEN_);
|
||||
_poolQuoteToken = address(_QUOTE_TOKEN_);
|
||||
_poolI = 1;
|
||||
} else if (_UNUSED_BASE_ < poolBase) {
|
||||
// poolI up round
|
||||
_poolBaseToken = address(_BASE_TOKEN_);
|
||||
_poolQuoteToken = address(_QUOTE_TOKEN_);
|
||||
uint256 ratio = DecimalMath.ONE.sub(DecimalMath.divFloor(poolQuote, baseDepth));
|
||||
_poolI = avgPrice.mul(ratio).mul(ratio).divCeil(DecimalMath.ONE2);
|
||||
} else if (_UNUSED_BASE_ > poolBase) {
|
||||
// poolI down round
|
||||
_poolBaseToken = address(_QUOTE_TOKEN_);
|
||||
_poolQuoteToken = address(_BASE_TOKEN_);
|
||||
uint256 ratio = DecimalMath.ONE.sub(DecimalMath.divCeil(baseDepth, poolQuote));
|
||||
_poolI = ratio.mul(ratio).div(avgPrice);
|
||||
}
|
||||
_POOL_ = IDVMFactory(_POOL_FACTORY_).createDODOVendingMachine(
|
||||
_poolBaseToken,
|
||||
_poolQuoteToken,
|
||||
3e15, // 0.3% lp feeRate
|
||||
_poolI,
|
||||
DecimalMath.ONE
|
||||
);
|
||||
_AVG_SETTLED_PRICE_ = avgPrice;
|
||||
if (_UNUSED_BASE_ > poolBase) {
|
||||
_poolBaseToken = address(_QUOTE_TOKEN_);
|
||||
_poolQuoteToken = address(_BASE_TOKEN_);
|
||||
} else {
|
||||
_poolBaseToken = address(_BASE_TOKEN_);
|
||||
_poolQuoteToken = address(_QUOTE_TOKEN_);
|
||||
}
|
||||
|
||||
_POOL_ = IDVMFactory(_POOL_FACTORY_).createDODOVendingMachine(
|
||||
_poolBaseToken,
|
||||
_poolQuoteToken,
|
||||
3e15, // 0.3% lp feeRate
|
||||
poolI,
|
||||
DecimalMath.ONE
|
||||
);
|
||||
|
||||
uint256 avgPrice = unUsedBase == 0 ? _I_ : DecimalMath.divCeil(poolQuote, unUsedBase);
|
||||
_AVG_SETTLED_PRICE_ = avgPrice;
|
||||
|
||||
_transferBaseOut(_POOL_, poolBase);
|
||||
_transferQuoteOut(_POOL_, poolQuote);
|
||||
|
||||
@@ -148,13 +119,43 @@ contract CPFunding is CPStorage {
|
||||
|
||||
// ============ Pricing ============
|
||||
|
||||
function getSettleResult() public view returns (uint256 poolBase, uint256 poolQuote) {
|
||||
function getSettleResult() public view returns (uint256 poolBase, uint256 poolQuote, uint256 poolI, uint256 unUsedBase, uint256 unUsedQuote) {
|
||||
poolQuote = _QUOTE_TOKEN_.balanceOf(address(this));
|
||||
if (poolQuote > _POOL_QUOTE_CAP_) {
|
||||
poolQuote = _POOL_QUOTE_CAP_;
|
||||
}
|
||||
(uint256 soldBase,) = PMMPricing.sellQuoteToken(_getPMMState(), poolQuote);
|
||||
poolBase = _TOTAL_BASE_.sub(soldBase);
|
||||
|
||||
unUsedQuote = _QUOTE_TOKEN_.balanceOf(address(this)).sub(poolQuote);
|
||||
unUsedBase = _BASE_TOKEN_.balanceOf(address(this)).sub(poolBase);
|
||||
|
||||
// Try to make midPrice equal to avgPrice
|
||||
// k=1, If quote and base are not balanced, one side must be cut off
|
||||
// DVM truncated quote, but if more quote than base entering the pool, we need set the quote to the base
|
||||
|
||||
// m = avgPrice
|
||||
// i = m (1-quote/(m*base))
|
||||
// if quote = m*base i = 1
|
||||
// if quote > m*base reverse
|
||||
uint256 avgPrice = unUsedBase == 0 ? _I_ : DecimalMath.divCeil(poolQuote, unUsedBase);
|
||||
uint256 baseDepth = DecimalMath.mulFloor(avgPrice, poolBase);
|
||||
|
||||
if (poolQuote == 0) {
|
||||
// ask side only DVM
|
||||
poolI = _I_;
|
||||
} else if (unUsedBase== poolBase) {
|
||||
// standard bonding curve
|
||||
poolI = 1;
|
||||
} else if (unUsedBase < poolBase) {
|
||||
// poolI up round
|
||||
uint256 ratio = DecimalMath.ONE.sub(DecimalMath.divFloor(poolQuote, baseDepth));
|
||||
poolI = avgPrice.mul(ratio).mul(ratio).divCeil(DecimalMath.ONE2);
|
||||
} else if (unUsedBase > poolBase) {
|
||||
// poolI down round
|
||||
uint256 ratio = DecimalMath.ONE.sub(DecimalMath.divCeil(baseDepth, poolQuote));
|
||||
poolI = ratio.mul(ratio).div(avgPrice);
|
||||
}
|
||||
}
|
||||
|
||||
function _getPMMState() internal view returns (PMMPricing.PMMState memory state) {
|
||||
@@ -169,7 +170,7 @@ contract CPFunding is CPStorage {
|
||||
|
||||
function getExpectedAvgPrice() external view returns (uint256) {
|
||||
require(!_SETTLED_, "ALREADY_SETTLED");
|
||||
(uint256 poolBase, uint256 poolQuote) = getSettleResult();
|
||||
(uint256 poolBase, uint256 poolQuote, , , ) = getSettleResult();
|
||||
return DecimalMath.divCeil(poolQuote, _BASE_TOKEN_.balanceOf(address(this)).sub(poolBase));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ contract DPPTrader is DPPVault {
|
||||
address toToken,
|
||||
uint256 fromAmount,
|
||||
uint256 toAmount,
|
||||
address trader
|
||||
address trader,
|
||||
address receiver
|
||||
);
|
||||
|
||||
event DODOFlashLoan(
|
||||
@@ -67,7 +68,8 @@ contract DPPTrader is DPPVault {
|
||||
address(_QUOTE_TOKEN_),
|
||||
baseInput,
|
||||
receiveQuoteAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
to
|
||||
);
|
||||
}
|
||||
|
||||
@@ -103,7 +105,8 @@ contract DPPTrader is DPPVault {
|
||||
address(_BASE_TOKEN_),
|
||||
quoteInput,
|
||||
receiveBaseAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
to
|
||||
);
|
||||
}
|
||||
|
||||
@@ -152,7 +155,8 @@ contract DPPTrader is DPPVault {
|
||||
address(_BASE_TOKEN_),
|
||||
quoteInput,
|
||||
receiveBaseAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
assetTo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -180,7 +184,8 @@ contract DPPTrader is DPPVault {
|
||||
address(_QUOTE_TOKEN_),
|
||||
baseInput,
|
||||
receiveQuoteAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
assetTo
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ contract DVMTrader is DVMVault {
|
||||
address toToken,
|
||||
uint256 fromAmount,
|
||||
uint256 toAmount,
|
||||
address trader
|
||||
address trader,
|
||||
address receiver
|
||||
);
|
||||
|
||||
event DODOFlashLoan(
|
||||
@@ -56,7 +57,8 @@ contract DVMTrader is DVMVault {
|
||||
address(_QUOTE_TOKEN_),
|
||||
baseInput,
|
||||
receiveQuoteAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
to
|
||||
);
|
||||
}
|
||||
|
||||
@@ -79,7 +81,8 @@ contract DVMTrader is DVMVault {
|
||||
address(_BASE_TOKEN_),
|
||||
quoteInput,
|
||||
receiveBaseAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
to
|
||||
);
|
||||
}
|
||||
|
||||
@@ -116,7 +119,8 @@ contract DVMTrader is DVMVault {
|
||||
address(_BASE_TOKEN_),
|
||||
quoteInput,
|
||||
receiveBaseAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
assetTo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -132,7 +136,8 @@ contract DVMTrader is DVMVault {
|
||||
address(_QUOTE_TOKEN_),
|
||||
baseInput,
|
||||
receiveQuoteAmount,
|
||||
msg.sender
|
||||
msg.sender,
|
||||
assetTo
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ contract DODOIncentive is InitializableOwnable {
|
||||
// ============ Storage ============
|
||||
address public immutable _DODO_TOKEN_;
|
||||
address public _DODO_PROXY_;
|
||||
uint256 public dodoPerBlock = 10 * 10**18;
|
||||
uint256 public dodoPerBlock;
|
||||
uint256 public defaultRate = 10;
|
||||
mapping(address => uint256) public boosts;
|
||||
|
||||
@@ -44,7 +44,6 @@ contract DODOIncentive is InitializableOwnable {
|
||||
// ============ Events ============
|
||||
|
||||
event SetBoost(address token, uint256 boostRate);
|
||||
event SetSwitch(bool isOpen);
|
||||
event SetNewProxy(address dodoProxy);
|
||||
event SetPerReward(uint256 dodoPerBlock);
|
||||
event SetDefaultRate(uint256 defaultRate);
|
||||
@@ -63,6 +62,7 @@ contract DODOIncentive is InitializableOwnable {
|
||||
emit SetBoost(_token, _boostRate);
|
||||
}
|
||||
|
||||
//switch
|
||||
function changePerReward(uint256 _dodoPerBlock) public onlyOwner {
|
||||
_updateTotalReward();
|
||||
dodoPerBlock = _dodoPerBlock;
|
||||
@@ -110,8 +110,8 @@ contract DODOIncentive is InitializableOwnable {
|
||||
}
|
||||
|
||||
function _updateTotalReward() internal {
|
||||
lastRewardBlock = uint32(block.number);
|
||||
totalReward = uint112(_getTotalReward());
|
||||
lastRewardBlock = uint32(block.number);
|
||||
}
|
||||
|
||||
function _update(uint256 _totalReward, uint256 _totalDistribution) internal {
|
||||
@@ -127,7 +127,7 @@ contract DODOIncentive is InitializableOwnable {
|
||||
}
|
||||
|
||||
function _getTotalReward() internal view returns (uint256) {
|
||||
if (block.number < lastRewardBlock || lastRewardBlock == 0) {
|
||||
if (lastRewardBlock == 0) {
|
||||
return totalReward;
|
||||
} else {
|
||||
return totalReward + (block.number - lastRewardBlock) * dodoPerBlock;
|
||||
|
||||
@@ -23,6 +23,7 @@ import {DecimalMath} from "../lib/DecimalMath.sol";
|
||||
import {ReentrancyGuard} from "../lib/ReentrancyGuard.sol";
|
||||
import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
|
||||
import {IDODOIncentive} from "./DODOIncentive.sol";
|
||||
import {IDODOAdapter} from "./intf/IDODOAdapter.sol";
|
||||
|
||||
/**
|
||||
* @title DODOV2Proxy01
|
||||
@@ -602,76 +603,70 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
|
||||
emit OrderHistory(_fromToken, _toToken, msg.sender, fromTokenAmount, returnAmount);
|
||||
}
|
||||
|
||||
function mixSwapV1(
|
||||
|
||||
function mixSwap(
|
||||
address fromToken,
|
||||
address toToken,
|
||||
uint256 fromTokenAmount,
|
||||
uint256 minReturnAmount,
|
||||
address[] memory mixAdapters,
|
||||
address[] memory mixPairs,
|
||||
uint256[] memory directions,
|
||||
address[] memory portionPath,
|
||||
uint256 directions,
|
||||
bool isIncentive,
|
||||
uint256 deadLine
|
||||
) external override payable judgeExpired(deadLine) returns (uint256 returnAmount) {
|
||||
require(mixPairs.length == directions.length, "DODOV2Proxy01: PARAMS_LENGTH_NOT_MATCH");
|
||||
require(mixPairs.length > 0, "DODOV2Proxy01: PAIRS_EMPTY");
|
||||
require(mixPairs.length == mixAdapters.length, "DODOV2Proxy01: ADAPTER_PAIR_NOT_MATCH");
|
||||
require(minReturnAmount > 0, "DODOV2Proxy01: RETURN_AMOUNT_ZERO");
|
||||
|
||||
uint256 toTokenOriginBalance = IERC20(toToken).universalBalanceOf(msg.sender);
|
||||
|
||||
|
||||
{
|
||||
address _fromToken = fromToken;
|
||||
address _toToken = toToken;
|
||||
_deposit(msg.sender, address(this), _fromToken, fromTokenAmount, _fromToken == _ETH_ADDRESS_);
|
||||
_deposit(msg.sender, mixPairs[0], _fromToken, fromTokenAmount, _fromToken == _ETH_ADDRESS_);
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < mixPairs.length; i++) {
|
||||
address curPair = mixPairs[i];
|
||||
if (directions[i] == 0) {
|
||||
address curDodoBase = IDODOV1(curPair)._BASE_TOKEN_();
|
||||
uint256 curAmountIn = IERC20(curDodoBase).balanceOf(address(this));
|
||||
IERC20(curDodoBase).universalApproveMax(curPair, curAmountIn);
|
||||
IDODOV1(curPair).sellBaseToken(curAmountIn, 0, "");
|
||||
} else if(directions[i] == 1){
|
||||
address curDodoQuote = IDODOV1(curPair)._QUOTE_TOKEN_();
|
||||
uint256 curAmountIn = IERC20(curDodoQuote).balanceOf(address(this));
|
||||
IERC20(curDodoQuote).universalApproveMax(curPair, curAmountIn);
|
||||
uint256 canBuyBaseAmount = IDODOSellHelper(_DODO_SELL_HELPER_).querySellQuoteToken(
|
||||
curPair,
|
||||
curAmountIn
|
||||
);
|
||||
IDODOV1(curPair).buyBaseToken(canBuyBaseAmount, curAmountIn, "");
|
||||
address assetTo = toToken == _ETH_ADDRESS_ ? address(this): msg.sender;
|
||||
for (uint256 i = 0; i < mixPairs.length; i++) {
|
||||
if (i == mixPairs.length - 1) {
|
||||
if (directions & 1 == 0) {
|
||||
IDODOAdapter(mixAdapters[i]).sellBase(assetTo,mixPairs[i]);
|
||||
} else {
|
||||
IDODOAdapter(mixAdapters[i]).sellQuote(assetTo,mixPairs[i]);
|
||||
}
|
||||
} else {
|
||||
uint256 curAmountIn = IERC20(portionPath[0]).balanceOf(address(this));
|
||||
IERC20(portionPath[0]).universalApproveMax(curPair, curAmountIn);
|
||||
IUni(curPair).swapExactTokensForTokens(curAmountIn,0,portionPath,address(this),deadLine);
|
||||
if (directions& 1 == 0) {
|
||||
IDODOAdapter(mixAdapters[i]).sellBase(mixPairs[i + 1],mixPairs[i]);
|
||||
} else {
|
||||
IDODOAdapter(mixAdapters[i]).sellQuote(mixPairs[i + 1],mixPairs[i]);
|
||||
}
|
||||
}
|
||||
directions = directions >> 1;
|
||||
}
|
||||
|
||||
IERC20(_toToken).universalTransfer(
|
||||
msg.sender,
|
||||
IERC20(_toToken).universalBalanceOf(address(this))
|
||||
);
|
||||
|
||||
// {
|
||||
// uint256 toBalance;
|
||||
// if (_toToken == _ETH_ADDRESS_) {
|
||||
// toBalance = IWETH(_WETH_).balanceOf(address(this));
|
||||
// IWETH(_WETH_).withdraw(toBalance);
|
||||
// } else {
|
||||
// toBalance = IERC20(_toToken).tokenBalanceOf(address(this));
|
||||
// }
|
||||
// IERC20(_toToken).universalTransfer(msg.sender,toBalance);
|
||||
// }
|
||||
if(toToken == _ETH_ADDRESS_) {
|
||||
returnAmount = IWETH(_WETH_).balanceOf(address(this));
|
||||
IWETH(_WETH_).withdraw(returnAmount);
|
||||
msg.sender.transfer(returnAmount);
|
||||
}else {
|
||||
returnAmount = IERC20(toToken).tokenBalanceOf(msg.sender).sub(toTokenOriginBalance);
|
||||
}
|
||||
|
||||
returnAmount = IERC20(_toToken).universalBalanceOf(msg.sender).sub(toTokenOriginBalance);
|
||||
require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough");
|
||||
|
||||
|
||||
_externalGasReturn();
|
||||
|
||||
|
||||
if(isIncentive) {
|
||||
IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(_fromToken,_toToken,msg.sender);
|
||||
IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(fromToken,toToken,msg.sender);
|
||||
}
|
||||
|
||||
emit OrderHistory(_fromToken, _toToken, msg.sender, fromTokenAmount, returnAmount);
|
||||
|
||||
emit OrderHistory(
|
||||
fromToken,
|
||||
toToken,
|
||||
msg.sender,
|
||||
fromTokenAmount,
|
||||
returnAmount
|
||||
);
|
||||
}
|
||||
|
||||
//============ CrowdPooling Functions (create & bid) ============
|
||||
|
||||
52
contracts/SmartRoute/adapter/DODOV1Adapter.sol
Normal file
52
contracts/SmartRoute/adapter/DODOV1Adapter.sol
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
import {IERC20} from "../../intf/IERC20.sol";
|
||||
import {IDODOV1} from "../intf/IDODOV1.sol";
|
||||
import {IDODOSellHelper} from "../helper/DODOSellHelper.sol";
|
||||
import {UniversalERC20} from "../lib/UniversalERC20.sol";
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
import {IDODOAdapter} from "../intf/IDODOAdapter.sol";
|
||||
|
||||
contract DODOV1Adapter is IDODOAdapter {
|
||||
using SafeMath for uint256;
|
||||
using UniversalERC20 for IERC20;
|
||||
|
||||
address public immutable _DODO_SELL_HELPER_;
|
||||
|
||||
constructor(address dodoSellHelper) public {
|
||||
_DODO_SELL_HELPER_ = dodoSellHelper;
|
||||
}
|
||||
|
||||
function sellBase(address to, address pool) external override {
|
||||
address curBase = IDODOV1(pool)._BASE_TOKEN_();
|
||||
uint256 curAmountIn = IERC20(curBase).balanceOf(address(this));
|
||||
IERC20(curBase).universalApproveMax(pool, curAmountIn);
|
||||
IDODOV1(pool).sellBaseToken(curAmountIn, 0, "");
|
||||
if(to == msg.sender) {
|
||||
address curQuote = IDODOV1(pool)._QUOTE_TOKEN_();
|
||||
IERC20(curQuote).transfer(to,IERC20(curQuote).balanceOf(address(this)));
|
||||
}
|
||||
}
|
||||
|
||||
function sellQuote(address to, address pool) external override {
|
||||
address curQuote = IDODOV1(pool)._QUOTE_TOKEN_();
|
||||
uint256 curAmountIn = IERC20(curQuote).balanceOf(address(this));
|
||||
IERC20(curQuote).universalApproveMax(pool, curAmountIn);
|
||||
uint256 canBuyBaseAmount = IDODOSellHelper(_DODO_SELL_HELPER_).querySellQuoteToken(
|
||||
pool,
|
||||
curAmountIn
|
||||
);
|
||||
IDODOV1(pool).buyBaseToken(canBuyBaseAmount, curAmountIn, "");
|
||||
if(to == msg.sender) {
|
||||
address curBase = IDODOV1(pool)._BASE_TOKEN_();
|
||||
IERC20(curBase).transfer(to,IERC20(curBase).balanceOf(address(this)));
|
||||
}
|
||||
}
|
||||
}
|
||||
21
contracts/SmartRoute/adapter/DODOV2Adapter.sol
Normal file
21
contracts/SmartRoute/adapter/DODOV2Adapter.sol
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
import {IDODOV2} from "../intf/IDODOV2.sol";
|
||||
import {IDODOAdapter} from "../intf/IDODOAdapter.sol";
|
||||
|
||||
contract DODOV2Adapter is IDODOAdapter {
|
||||
function sellBase(address to, address pool) external override {
|
||||
IDODOV2(pool).sellBase(to);
|
||||
}
|
||||
|
||||
function sellQuote(address to, address pool) external override {
|
||||
IDODOV2(pool).sellQuote(to);
|
||||
}
|
||||
}
|
||||
49
contracts/SmartRoute/adapter/UniAdapter.sol
Normal file
49
contracts/SmartRoute/adapter/UniAdapter.sol
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
import {IDODOAdapter} from "../intf/IDODOAdapter.sol";
|
||||
import {IUni} from "../intf/IUni.sol";
|
||||
import {IERC20} from "../../intf/IERC20.sol";
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
|
||||
contract UniAdapter is IDODOAdapter {
|
||||
using SafeMath for uint;
|
||||
|
||||
//fromToken == token0
|
||||
function sellBase(address to, address pool) external override {
|
||||
address baseToken = IUni(pool).token0();
|
||||
(uint reserveIn, uint reserveOut,) = IUni(pool).getReserves();
|
||||
require(reserveIn > 0 && reserveOut > 0, 'UniAdapter: INSUFFICIENT_LIQUIDITY');
|
||||
|
||||
uint balance0 = IERC20(baseToken).balanceOf(pool);
|
||||
uint sellBaseAmount = balance0 - reserveIn;
|
||||
|
||||
uint sellBaseAmountWithFee = sellBaseAmount.mul(997);
|
||||
uint numerator = sellBaseAmountWithFee.mul(reserveOut);
|
||||
uint denominator = reserveIn.mul(1000).add(sellBaseAmountWithFee);
|
||||
uint receiveQuoteAmount = numerator / denominator;
|
||||
IUni(pool).swap(0, receiveQuoteAmount, to, new bytes(0));
|
||||
}
|
||||
|
||||
//fromToken == token1
|
||||
function sellQuote(address to, address pool) external override {
|
||||
address quoteToken = IUni(pool).token1();
|
||||
(uint reserveOut, uint reserveIn,) = IUni(pool).getReserves();
|
||||
require(reserveIn > 0 && reserveOut > 0, 'UniAdapter: INSUFFICIENT_LIQUIDITY');
|
||||
|
||||
uint balance1 = IERC20(quoteToken).balanceOf(pool);
|
||||
uint sellQuoteAmount = balance1 - reserveIn;
|
||||
|
||||
uint sellQuoteAmountWithFee = sellQuoteAmount.mul(997);
|
||||
uint numerator = sellQuoteAmountWithFee.mul(reserveOut);
|
||||
uint denominator = reserveIn.mul(1000).add(sellQuoteAmountWithFee);
|
||||
uint receiveBaseAmount = numerator / denominator;
|
||||
IUni(pool).swap(receiveBaseAmount, 0, to, new bytes(0));
|
||||
}
|
||||
}
|
||||
16
contracts/SmartRoute/intf/IDODOAdapter.sol
Normal file
16
contracts/SmartRoute/intf/IDODOAdapter.sol
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
interface IDODOAdapter {
|
||||
|
||||
function sellBase(address to, address pool) external;
|
||||
|
||||
function sellQuote(address to, address pool) external;
|
||||
}
|
||||
@@ -138,14 +138,14 @@ interface IDODOV2Proxy01 {
|
||||
uint256 deadLine
|
||||
) external payable returns (uint256 returnAmount);
|
||||
|
||||
function mixSwapV1(
|
||||
function mixSwap(
|
||||
address fromToken,
|
||||
address toToken,
|
||||
uint256 fromTokenAmount,
|
||||
uint256 minReturnAmount,
|
||||
address[] memory mixAdapters,
|
||||
address[] memory mixPairs,
|
||||
uint256[] memory directions,
|
||||
address[] memory portionPath,
|
||||
uint256 directions,
|
||||
bool isIncentive,
|
||||
uint256 deadLine
|
||||
) external payable returns (uint256 returnAmount);
|
||||
|
||||
@@ -9,4 +9,12 @@ interface IUni {
|
||||
address to,
|
||||
uint deadline
|
||||
) external returns (uint[] memory amounts);
|
||||
|
||||
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
|
||||
|
||||
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
|
||||
|
||||
function token0() external view returns (address);
|
||||
|
||||
function token1() external view returns (address);
|
||||
}
|
||||
@@ -16,9 +16,6 @@ contract FeeRateModelLogic is ReentrancyGuard,InitializableOwnable {
|
||||
uint256 public _FEE_RATE_;
|
||||
mapping(address => uint256) feeMapping;
|
||||
|
||||
|
||||
event Log(string str, bool result);
|
||||
|
||||
function setSpecificFeeRate(address trader, uint256 feeRate) external onlyOwner {
|
||||
require(trader != address(0), "INVALID ADDRESS!");
|
||||
feeMapping[trader] = feeRate;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {ReentrancyGuard} from "../lib/ReentrancyGuard.sol";
|
||||
import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
|
||||
|
||||
//for test update
|
||||
contract FeeRateModelLogicUpdate is ReentrancyGuard ,InitializableOwnable{
|
||||
//DEFAULT
|
||||
uint256 public _FEE_RATE_;
|
||||
mapping(address => uint256) feeMapping;
|
||||
|
||||
|
||||
event Log(string str, bool result);
|
||||
|
||||
function setSpecificFeeRate(address trader, uint256 feeRate) external onlyOwner {
|
||||
require(trader != address(0), "INVALID ADDRESS!");
|
||||
feeMapping[trader] = 0;
|
||||
}
|
||||
|
||||
function setFeeRate(uint256 newFeeRate) external onlyOwner {
|
||||
_FEE_RATE_ = _FEE_RATE_+ newFeeRate;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user