flash loan test

This commit is contained in:
mingda
2020-11-27 01:42:46 +08:00
parent 68c377807b
commit d4569fe099
6 changed files with 98 additions and 34 deletions

View File

@@ -25,7 +25,10 @@ contract DPPTrader is DPPVault {
}
modifier isSellAllow(address trader) {
require(!_SELLING_CLOSE_ && _TRADE_PERMISSION_.isAllowed(trader),"TRADER_SELL_NOT_ALLOWED");
require(
!_SELLING_CLOSE_ && _TRADE_PERMISSION_.isAllowed(trader),
"TRADER_SELL_NOT_ALLOWED"
);
_;
}
@@ -75,7 +78,10 @@ contract DPPTrader is DPPVault {
uint256 newQuoteTarget;
PMMPricing.RState newRState;
(receiveBaseAmount, mtFee, newRState, newQuoteTarget) = querySellQuote(tx.origin,quoteInput);
(receiveBaseAmount, mtFee, newRState, newQuoteTarget) = querySellQuote(
tx.origin,
quoteInput
);
_transferBaseOut(to, receiveBaseAmount);
_transferBaseOut(_MAINTAINER_, mtFee);
@@ -105,15 +111,15 @@ contract DPPTrader is DPPVault {
uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this));
uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this));
// no output -> pure profit
if (baseBalance >= _BASE_RESERVE_ && quoteBalance >= _QUOTE_RESERVE_) return;
// no input -> pure loss
require(
baseBalance >= _BASE_RESERVE_ || quoteBalance >= _QUOTE_RESERVE_,
"FLASH_LOAN_FAILED"
);
// no output -> pure profit
if (baseBalance >= _BASE_RESERVE_ && quoteBalance >= _QUOTE_RESERVE_) return;
// sell quote case
// quote input + base output
if (baseBalance < _BASE_RESERVE_) {
@@ -223,4 +229,9 @@ contract DPPTrader is DPPVault {
function getMidPrice() public view returns (uint256 midPrice) {
return PMMPricing.getMidPrice(getPMMState());
}
function _syncReserve() internal {
_BASE_RESERVE_ = _BASE_TOKEN_.balanceOf(address(this));
_QUOTE_RESERVE_ = _QUOTE_TOKEN_.balanceOf(address(this));
}
}

View File

@@ -51,12 +51,6 @@ contract DPPVault is DPPStorage {
_setRState();
}
function _syncReserve() internal {
_BASE_RESERVE_ = _BASE_TOKEN_.balanceOf(address(this));
_QUOTE_RESERVE_ = _QUOTE_TOKEN_.balanceOf(address(this));
_setRState();
}
function _resetTargetAndReserve() internal {
_BASE_TARGET_ = _BASE_TOKEN_.balanceOf(address(this));
_QUOTE_TARGET_ = _QUOTE_TOKEN_.balanceOf(address(this));

View File

@@ -48,7 +48,7 @@ contract DVMTrader is DVMVault {
returns (uint256 receiveQuoteAmount)
{
uint256 baseInput = getBaseInput();
require(baseInput > 0, 'INSUFFICIENT_BASE_INPUT');
require(baseInput > 0, "INSUFFICIENT_BASE_INPUT");
uint256 mtFee;
(receiveQuoteAmount, mtFee) = querySellBase(tx.origin, baseInput);
_transferQuoteOut(to, receiveQuoteAmount);
@@ -65,7 +65,7 @@ contract DVMTrader is DVMVault {
returns (uint256 receiveBaseAmount)
{
uint256 quoteInput = getQuoteInput();
require(quoteInput > 0, 'INSUFFICIENT_QUOTE_INPUT');
require(quoteInput > 0, "INSUFFICIENT_QUOTE_INPUT");
uint256 mtFee;
(receiveBaseAmount, mtFee) = querySellQuote(tx.origin, quoteInput);
_transferBaseOut(to, receiveBaseAmount);
@@ -88,33 +88,35 @@ contract DVMTrader is DVMVault {
if (data.length > 0)
IDODOCallee(assetTo).DVMFlashLoanCall(msg.sender, baseAmount, quoteAmount, data);
(uint256 baseReserve, uint256 quoteReserve) = getVaultReserve();
(uint256 baseBalance, uint256 quoteBalance) = getVaultBalance();
uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(tx.origin);
uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(tx.origin);
if (baseBalance < baseReserve) {
uint256 validBaseOut = DecimalMath.divCeil(
baseReserve - baseBalance,
DecimalMath.ONE.sub(mtFeeRate).sub(lpFeeRate)
);
baseBalance = baseReserve.sub(validBaseOut);
_transferBaseOut(_MAINTAINER_, DecimalMath.mulFloor(validBaseOut, mtFeeRate));
}
if (quoteBalance < quoteReserve) {
uint256 validQuoteOut = DecimalMath.divCeil(
quoteReserve - quoteBalance,
DecimalMath.ONE.sub(mtFeeRate).sub(lpFeeRate)
);
quoteBalance = quoteReserve.sub(validQuoteOut);
_transferQuoteOut(_MAINTAINER_, DecimalMath.mulFloor(validQuoteOut, mtFeeRate));
}
// no input -> pure loss
require(
calculateBase0(baseBalance, quoteBalance) >= calculateBase0(baseReserve, quoteReserve),
baseBalance >= _BASE_RESERVE_ || quoteBalance >= _QUOTE_RESERVE_,
"FLASH_LOAN_FAILED"
);
// no output -> pure profit
if (baseBalance >= _BASE_RESERVE_ && quoteBalance >= _QUOTE_RESERVE_) return;
if (baseBalance < _BASE_RESERVE_) {
(uint256 receiveBaseAmount, uint256 mtFee) = querySellQuote(
tx.origin,
quoteBalance.sub(_QUOTE_RESERVE_)
);
require(_BASE_RESERVE_.sub(baseBalance) <= receiveBaseAmount, "FLASH_LOAN_FAILED");
_transferBaseOut(_MAINTAINER_, mtFee);
}
if (quoteBalance < _QUOTE_RESERVE_) {
(uint256 receiveQuoteAmount, uint256 mtFee) = querySellBase(
tx.origin,
baseBalance.sub(_BASE_RESERVE_)
);
require(_QUOTE_RESERVE_.sub(quoteBalance) <= receiveQuoteAmount, "FLASH_LOAN_FAILED");
_transferQuoteOut(_MAINTAINER_, mtFee);
}
_sync();
}

View File

@@ -178,7 +178,35 @@ describe("DPP Trader", () => {
it("flash loan", async () => {
// buy
await ctx.transferQuoteToDPP(trader, decimalStr("200"))
// buy failed
await truffleAssert.reverts(ctx.DPP.methods.flashLoan("1946763594380080788", "0", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED")
// buy succeed
await ctx.DPP.methods.flashLoan("1946763594380080787", "0", trader, "0x").send(ctx.sendParam(trader))
// trader balances
assert.equal(
await ctx.BASE.methods.balanceOf(trader).call(),
"11946763594380080787"
);
// sell
await ctx.transferBaseToDPP(trader, decimalStr("1"))
// sell failed
await truffleAssert.reverts(ctx.DPP.methods.flashLoan("0", "103421810640399874604", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED")
// sell succeed
await ctx.DPP.methods.flashLoan("0", "103421810640399874603", trader, "0x").send(ctx.sendParam(trader))
// trader balances
assert.equal(
await ctx.QUOTE.methods.balanceOf(trader).call(),
"903421810640399874603"
);
})
it("revert cases", async () => {

View File

@@ -168,6 +168,35 @@ describe("Trader", () => {
});
it("flash loan", async () => {
// buy
await ctx.transferQuoteToDVM(trader, decimalStr("200"))
// buy failed
await truffleAssert.reverts(ctx.DVM.methods.flashLoan("1946763594380080788", "0", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED")
// buy succeed
await ctx.DVM.methods.flashLoan("1946763594380080787", "0", trader, "0x").send(ctx.sendParam(trader))
// trader balances
assert.equal(
await ctx.BASE.methods.balanceOf(trader).call(),
"11946763594380080787"
);
// sell
await ctx.transferBaseToDVM(trader, decimalStr("1"))
// sell failed
await truffleAssert.reverts(ctx.DVM.methods.flashLoan("0", "103421810640399874604", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED")
// sell succeed
await ctx.DVM.methods.flashLoan("0", "103421810640399874603", trader, "0x").send(ctx.sendParam(trader))
// trader balances
assert.equal(
await ctx.QUOTE.methods.balanceOf(trader).call(),
"903421810640399874603"
);
})