From 5e6db3e4b601f9fc313e899ab6fa59e85d5ec99f Mon Sep 17 00:00:00 2001 From: owen05 Date: Tue, 24 Nov 2020 16:12:38 +0800 Subject: [PATCH] add proxy test framework --- contracts/SmartRoute/SmartSwap.sol | 6 +- contracts/intf/IDODOV2.sol | 35 ++++--- deploy-detail.txt | 8 -- test/Proxy/proxy.test.ts | 155 +++++++++++++++++++++++++++++ test/utils/Contracts.ts | 6 ++ test/utils/Converter.ts | 6 +- test/utils/ProxyContext.ts | 147 +++++++++++++++++++++++++++ 7 files changed, 334 insertions(+), 29 deletions(-) create mode 100644 test/Proxy/proxy.test.ts create mode 100644 test/utils/ProxyContext.ts diff --git a/contracts/SmartRoute/SmartSwap.sol b/contracts/SmartRoute/SmartSwap.sol index 94a0601..9f00242 100644 --- a/contracts/SmartRoute/SmartSwap.sol +++ b/contracts/SmartRoute/SmartSwap.sol @@ -40,8 +40,6 @@ contract SmartSwap is Ownable { uint256 timeStamp ); - event ExternalRecord(address indexed to, address indexed sender); - constructor( address _smartApprove, address _dodoSellHelper, @@ -76,9 +74,8 @@ contract SmartSwap is Ownable { } for (uint256 i = 0; i < dodoPairs.length; i++) { - uint256 curDirection = directions[i]; address curDodoPair = dodoPairs[i]; - if (curDirection == 0) { + if (directions[i] == 0) { address curDodoBase = IDODO(curDodoPair)._BASE_TOKEN_(); uint256 curAmountIn = IERC20(curDodoBase).balanceOf(address(this)); IERC20(curDodoBase).universalApprove(curDodoPair, curAmountIn); @@ -139,6 +136,5 @@ contract SmartSwap is Ownable { require(returnAmount >= minReturnAmount, "DODO SmartSwap: Return amount is not enough"); IERC20(toToken).universalTransfer(msg.sender, returnAmount); emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount, block.timestamp); - emit ExternalRecord(to, msg.sender); } } diff --git a/contracts/intf/IDODOV2.sol b/contracts/intf/IDODOV2.sol index c9c3e91..fdd58d2 100644 --- a/contracts/intf/IDODOV2.sol +++ b/contracts/intf/IDODOV2.sol @@ -11,21 +11,8 @@ pragma experimental ABIEncoderV2; import {IERC20} from "./IERC20.sol"; interface IDODOV2 { - function createDODOPrivatePool( - address baseToken, - address quoteToken, - address[] memory valueTemplates, //feeRateAddr,mtRateAddr,kAddr,iAddr - uint256[] memory values //feeRate,mtRate,k,i - ) external returns (address newPrivatePool); - function createDODOVendingMachine( - address baseToken, - address quoteToken, - uint256 lpFeeRate, - uint256 mtFeeRate, - uint256 i, - uint256 k - ) external returns (address newVendingMachine); + //========== Common ================== function sellBase(address to) external returns (uint256 receiveQuoteAmount); @@ -35,16 +22,34 @@ interface IDODOV2 { function sellShares(address to) external returns (uint256,uint256); - function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve); function _BASE_TOKEN_() external returns (address); function _QUOTE_TOKEN_() external returns (address); + //========== DODOVendingMachine ======== + + function createDODOVendingMachine( + address baseToken, + address quoteToken, + uint256 lpFeeRate, + uint256 mtFeeRate, + uint256 i, + uint256 k + ) external returns (address newVendingMachine); + //========== DODOPrivatePool =========== + function initTargetAndReserve() external; + function createDODOPrivatePool( + address baseToken, + address quoteToken, + address[] memory valueTemplates, //feeRateAddr,mtRateAddr,kAddr,iAddr + uint256[] memory values //feeRate,mtRate,k,i + ) external returns (address newPrivatePool); + function reset( uint256 newLpFeeRate, uint256 newMtFeeRate, diff --git a/deploy-detail.txt b/deploy-detail.txt index 3946e74..e69de29 100644 --- a/deploy-detail.txt +++ b/deploy-detail.txt @@ -1,8 +0,0 @@ -==================================================== -network type: kovan -Deploy time: 2020/11/20 上午10:58:49 -Deploy type: Smart Route -SmartApprove Address: 0x0E5cf0e4658E371f93a6bDB7E72d6789Aff08666 -DODOSellHelper Address: 0xbdEae617F2616b45DCB69B287D52940a76035Fe3 -SmartSwap Address: 0x767A6FB2f5e908c4E573CaA2bc7f53D468ffd78E -SmartApprovce setSmartSwap tx: 0xc9efe8b60cba3a2d288d487a7e512a3cfcdd017a25a923477323067546fbbec2 diff --git a/test/Proxy/proxy.test.ts b/test/Proxy/proxy.test.ts new file mode 100644 index 0000000..45daa09 --- /dev/null +++ b/test/Proxy/proxy.test.ts @@ -0,0 +1,155 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +// import * as assert from 'assert'; + +import { decimalStr, mweiStr} from '../utils/Converter'; +import { logGas } from '../utils/Log'; +import { ProxyContext, getProxyContext } from '../utils/ProxyContext'; +import { assert } from 'chai'; + +let lp: string; +let project: string; +let trader: string; + +let config = { + lpFeeRate: decimalStr("0.002"), + mtFeeRate: decimalStr("0.001"), + k: decimalStr("0.1"), + i: decimalStr("100"), +}; + +async function init(ctx: ProxyContext): Promise { + lp = ctx.SpareAccounts[0]; + project = ctx.SpareAccounts[1]; + trader = ctx.SpareAccounts[2]; + await ctx.approveProxy(lp); + await ctx.approveProxy(project); + await ctx.approveProxy(trader); + + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("100000")); + await ctx.mintTestToken(project, ctx.DODO, decimalStr("100000")); + await ctx.mintTestToken(trader, ctx.DODO, decimalStr("100000")); + + await ctx.mintTestToken(lp, ctx.USDT, mweiStr("100000")); + await ctx.mintTestToken(project, ctx.USDT, mweiStr("100000")); + + await ctx.mintTestToken(lp, ctx.WETH, decimalStr("70")); + await ctx.mintTestToken(project, ctx.WETH, decimalStr("70")); +} + +async function initCreateDVM(ctx: ProxyContext, token0: any, token1:any, token0Amount: string, token1Amount: string): Promise { + let PROXY = ctx.DODOProxy; + let dvmAddress; + let shares; + (dvmAddress, shares) = await PROXY.methods.createDODOVendingMachine( + token0.options.address, + token1.options.address, + token0Amount, + token1Amount, + config.lpFeeRate, + config.mtFeeRate, + config.i, + config.k, + Math.floor(new Date().getTime()/1000 + 60 * 10); + ).send(ctx.sendParam(project)); + console.log("create dvmAddress: ", dvmAddress); + console.log("create shares: ", shares); +} + +async function initCreateDPP(ctx: ProxyContext, token0: any, token1:any, token0Amount: string, token1Amount: string): Promise { + let PROXY = ctx.DODOProxy; + let dppAddress = await PROXY.methods.createDODOPrivatePool( + token0.options.address, + token1.options.address, + token0Amount, + token1Amount, + config.lpFeeRate, + config.mtFeeRate, + config.i, + config.k, + Math.floor(new Date().getTime()/1000 + 60 * 10); + ).send(ctx.sendParam(project)); + console.log("create dppAddress: ", dppAddress); + console.log("create shares: ", shares); +} + +describe("DODOProxyV2.0", () => { + let snapshotId: string; + let ctx: ProxyContext; + + before(async () => { + ctx = await getProxyContext(); + await init(ctx); + await initCreateDVM(ctx,ctx.DODO,ctx.USDT,decimalStr("10000"),decimalStr("10000")); + await initCreateDVM(ctx,ctx.WETH,ctx.USDT,decimalStr("50"),decimalStr("10000")); + await initCreateDPP(ctx,ctx.DODO,ctx.USDT,decimalStr("10000"),decimalStr("10000")); + await initCreateDPP(ctx,ctx.WETH,ctx.USDT,decimalStr("50"),decimalStr("10000")); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("DODOProxy", () => { + /** + * 1. 创建空池子 + * 2. 创建ERC20 Token DVM + * 3. 创建ETH && ERC20 Token + */ + it("createDVM", async () => { + + }); + + /** + * 1. 添加ERC20 Amount + * 2. 添加ERC20 + ETH + */ + it("addLiquidityToDVM", async () => { + + }); + + + /** + * 1. 移除ERC20 Amount + * 2. 移除ERC20 + ETH + */ + it("removeLiquidityToDVM", async () => { + + }); + + /** + * 1. 创建空池子 + * 2. 创建ERC20 DPP + * 3. 创建ETH && ERC20 Token + */ + it("createDPP", async () => { + + }); + + + /** + * + */ + it("resetDPP", async () => { + + }); + + + /** + * + */ + it("dodoSwap", async () => { + + }); + + }); +}); diff --git a/test/utils/Contracts.ts b/test/utils/Contracts.ts index 4f4efa6..d66d49f 100644 --- a/test/utils/Contracts.ts +++ b/test/utils/Contracts.ts @@ -35,6 +35,12 @@ export const DVM_PROXY_NAME = "DVMProxy" export const CONST_FEE_RATE_MODEL_NAME = "ConstFeeRateModel" export const PERMISSION_MANAGER_NAME = "PermissionManager" export const EXTERNAL_VALUE_NAME = "ExternalValue" +export const DODO_PROXY_NAME = "DODOV2Proxy01" +export const FEE_RATE_MODEL_NAME = "FeeRateModel" +export const DPP_NAME = "DPP" +export const DPP_FACTORY_NAME = "DPPFactory" +export const SMART_APPROVE = "SmartApprove" +export const DODO_SELL_HELPER = "DODOSellHelper" interface ContractJson { abi: any; diff --git a/test/utils/Converter.ts b/test/utils/Converter.ts index ba7269d..53edd17 100644 --- a/test/utils/Converter.ts +++ b/test/utils/Converter.ts @@ -8,4 +8,8 @@ export function decimalStr(value: string): string { export function gweiStr(gwei: string): string { return new BigNumber(gwei).multipliedBy(10 ** 9).toFixed(0, BigNumber.ROUND_DOWN) -} \ No newline at end of file +} + +export function mweiStr(gwei: string): string { + return new BigNumber(gwei).multipliedBy(10 ** 6).toFixed(0, BigNumber.ROUND_DOWN) +}s \ No newline at end of file diff --git a/test/utils/ProxyContext.ts b/test/utils/ProxyContext.ts new file mode 100644 index 0000000..f276df1 --- /dev/null +++ b/test/utils/ProxyContext.ts @@ -0,0 +1,147 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +import BigNumber from 'bignumber.js'; +import Web3 from 'web3'; +import { Contract } from 'web3-eth-contract'; + +import * as contracts from './Contracts'; +import { decimalStr, MAX_UINT256 } from './Converter'; +import { EVM, getDefaultWeb3 } from './EVM'; +import * as log from './Log'; + +BigNumber.config({ + EXPONENTIAL_AT: 1000, + DECIMAL_PLACES: 80, +}); + + +export class ProxyContext { + EVM: EVM; + Web3: Web3; + DODOProxy: Contract; + DVMFactory: Contract; + DPPFactory: Contract; + SmartApprove: Contract; + + //token + DODO: Contract; + USDT: Contract; + WETH: Contract; + + Deployer: string; + Maintainer: string; + SpareAccounts: string[]; + + constructor() { } + + async init() { + this.EVM = new EVM(); + this.Web3 = getDefaultWeb3(); + + var WETH = await contracts.newContract( + contracts.WETH_CONTRACT_NAME + ); + + var cloneFactory = await contracts.newContract( + contracts.CLONE_FACTORY_CONTRACT_NAME + ); + var dvmTemplate = await contracts.newContract(contracts.DVM_NAME) + var dppTemplate = await contracts.newContract(contracts.DPP_NAME) + var feeRateModelTemplate = await contracts.newContract(contracts.FEE_RATE_MODEL_NAME) + var permissionManagerTemplate = await contracts.newContract(contracts.PERMISSION_MANAGER_NAME) + var vauleSource = await contracts.newContract(contracts.EXTERNAL_VALUE_NAME) + + this.DVMFactory = await contracts.newContract(contracts.DVM_FACTORY_NAME, + [ + cloneFactory.options.address, + dvmTemplate.options.address, + feeRateModelTemplate.options.address, + permissionManagerTemplate.options.address, + vauleSource.options.address + ] + ) + + this.DPPFactory = await contracts.newContract(contracts.DPP_FACTORY_NAME, + [ + cloneFactory.options.address, + dppTemplate.options.address, + feeRateModelTemplate.options.address, + permissionManagerTemplate.options.address, + vauleSource.options.address + ] + ) + + this.SmartApprove = await contracts.newContract( + contracts.SMART_APPROVE + ); + + var dodoSellHelper = await contracts.newContract( + contracts.DODO_SELL_HELPER + ); + + this.DODOProxy = await contracts.newContract(contracts.DODO_PROXY_NAME, + [ + dvmFactory.options.address, + dppFactory.options.address, + WETH.options.address, + smartApprove.options.address, + dodoSellHelper.options.address + ] + ); + + this.DODO = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["DODO Token", "DODO", 18] + ); + this.USDT = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["USDT Token", "USDT", 6] + ); + this.WETH = await contracts.newContract( + contracts.WETH_CONTRACT_NAME + ); + + const allAccounts = await this.Web3.eth.getAccounts(); + this.Deployer = allAccounts[0]; + this.Maintainer = allAccounts[1]; + this.SpareAccounts = allAccounts.slice(2, 10); + + console.log(log.blueText("[Init DVM context]")); + } + + sendParam(sender, value = "0") { + return { + from: sender, + gas: process.env["COVERAGE"] ? 10000000000 : 7000000, + gasPrice: process.env.GAS_PRICE, + value: decimalStr(value), + }; + } + + async mintTestToken(to: string, token: Contract, amount: string) { + await token.methods.mint(to, amount).send(this.sendParam(this.Deployer)); + } + + async approveProxy(account: string) { + await this.DODO.methods + .approve(this.SmartApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + await this.USDT.methods + .approve(this.SmartApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + await this.WETH.methods + .approve(this.SmartApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + } +} + +export async function getProxyContext(): Promise { + var context = new ProxyContext(); + await context.init(); + return context; +}