UNPKG

@melonproject/protocol

Version:

Technology Regulated and Operated Investment Funds

326 lines (325 loc) 20.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const initTestEnvironment_1 = require("../utils/initTestEnvironment"); const deployAndGetSystem_1 = require("../utils/deployAndGetSystem"); const randomHexOfSize_1 = require("../../utils/helpers/randomHexOfSize"); const orderSignatures_1 = require("../../utils/constants/orderSignatures"); const token_math_1 = require("@melonproject/token-math"); const updateTestingPriceFeed_1 = require("../utils/updateTestingPriceFeed"); const getAllBalances_1 = require("../utils/getAllBalances"); const beginSetup_1 = require("../../contracts/factory/transactions/beginSetup"); const getToken_1 = require("../../contracts/dependencies/token/calls/getToken"); const Contracts_1 = require("../../Contracts"); const completeSetup_1 = require("../../contracts/factory/transactions/completeSetup"); const createAccounting_1 = require("../../contracts/factory/transactions/createAccounting"); const createFeeManager_1 = require("../../contracts/factory/transactions/createFeeManager"); const createParticipation_1 = require("../../contracts/factory/transactions/createParticipation"); const createPolicyManager_1 = require("../../contracts/factory/transactions/createPolicyManager"); const createShares_1 = require("../../contracts/factory/transactions/createShares"); const createTrading_1 = require("../../contracts/factory/transactions/createTrading"); const createVault_1 = require("../../contracts/factory/transactions/createVault"); const getFundComponents_1 = require("../../utils/getFundComponents"); const withDifferentAccount_1 = require("../../utils/environment/withDifferentAccount"); const increaseTime_1 = require("../../utils/evm/increaseTime"); const precisionUnits = token_math_1.power(new token_math_1.BigInteger(10), new token_math_1.BigInteger(18)); let s = {}; beforeAll(() => __awaiter(this, void 0, void 0, function* () { s.environment = yield initTestEnvironment_1.initTestEnvironment(); s.accounts = yield s.environment.eth.getAccounts(); const { addresses, contracts } = yield deployAndGetSystem_1.deployAndGetSystem(s.environment); s.addresses = addresses; s = Object.assign(s, contracts); [s.deployer, s.manager, s.investor] = s.accounts; s.exchanges = [s.matchingMarket]; s.gas = 8000000; s.numberofExchanges = 1; s.exchanges = [s.matchingMarket]; s.mlnTokenInterface = yield getToken_1.getToken(s.environment, s.mln.options.address); s.wethTokenInterface = yield getToken_1.getToken(s.environment, s.weth.options.address); const exchangeConfigs = { [Contracts_1.Exchanges.MatchingMarket]: { adapter: s.matchingMarketAdapter.options.address, exchange: s.matchingMarket.options.address, takesCustody: true, }, }; const envManager = withDifferentAccount_1.withDifferentAccount(s.environment, s.manager); yield beginSetup_1.beginSetup(envManager, s.version.options.address, { defaultTokens: [s.wethTokenInterface], exchangeConfigs, fees: [], fundName: 'Test fund', quoteToken: s.wethTokenInterface, }); yield createAccounting_1.createAccounting(envManager, s.version.options.address); yield createFeeManager_1.createFeeManager(envManager, s.version.options.address); yield createParticipation_1.createParticipation(envManager, s.version.options.address); yield createPolicyManager_1.createPolicyManager(envManager, s.version.options.address); yield createShares_1.createShares(envManager, s.version.options.address); yield createTrading_1.createTrading(envManager, s.version.options.address); yield createVault_1.createVault(envManager, s.version.options.address); const hubAddress = yield completeSetup_1.completeSetup(envManager, s.version.options.address); s.fund = yield getFundComponents_1.getFundComponents(envManager, hubAddress); yield updateTestingPriceFeed_1.updateTestingPriceFeed(s, s.environment); const [referencePrice] = Object.values(yield s.priceSource.methods .getReferencePriceInfo(s.weth.options.address, s.mln.options.address) .call()).map(e => new token_math_1.BigInteger(e)); const sellQuantity1 = token_math_1.power(new token_math_1.BigInteger(10), new token_math_1.BigInteger(20)); s.trade1 = { buyQuantity: token_math_1.divide(token_math_1.multiply(referencePrice, sellQuantity1), precisionUnits), sellQuantity: sellQuantity1, }; const sellQuantity2 = new token_math_1.BigInteger(5 * Math.pow(10, 16)); s.trade2 = { buyQuantity: token_math_1.divide(token_math_1.multiply(referencePrice, sellQuantity2), precisionUnits), sellQuantity: sellQuantity2, }; // Register price tolerance policy const priceTolerance = s.priceTolerance; yield expect(s.fund.policyManager.methods .register(orderSignatures_1.makeOrderSignatureBytes, priceTolerance.options.address) .send({ from: s.manager })).resolves.not.toThrow(); yield expect(s.fund.policyManager.methods .register(orderSignatures_1.takeOrderSignatureBytes, priceTolerance.options.address) .send({ from: s.manager })).resolves.not.toThrow(); })); test('Transfer ethToken to the investor', () => __awaiter(this, void 0, void 0, function* () { const initialTokenAmount = token_math_1.power(new token_math_1.BigInteger(10), new token_math_1.BigInteger(21)); const pre = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); yield s.weth.methods .transfer(s.investor, `${initialTokenAmount}`) .send({ from: s.deployer }); const post = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); expect(post.investor.weth).toEqual(token_math_1.add(pre.investor.weth, initialTokenAmount)); })); Array.from(Array(s.numberofExchanges).keys()).forEach(i => { test(`fund gets ETH Token from investment [round ${i + 1}]`, () => __awaiter(this, void 0, void 0, function* () { const wantedShares = token_math_1.power(new token_math_1.BigInteger(10), new token_math_1.BigInteger(20)); // const pre = await getAllBalances(s, s.accounts, s.fund, s.environment); const preTotalSupply = yield s.fund.shares.methods.totalSupply().call(); yield s.weth.methods .approve(s.fund.participation.options.address, wantedShares) .send({ from: s.investor, gas: s.gas }); yield s.fund.participation.methods .requestInvestment(`${wantedShares}`, `${wantedShares}`, s.weth.options.address) .send({ from: s.investor, gas: s.gas, value: '10000000000000000' }); yield updateTestingPriceFeed_1.updateTestingPriceFeed(s, s.environment); yield updateTestingPriceFeed_1.updateTestingPriceFeed(s, s.environment); yield s.fund.participation.methods .executeRequestFor(s.investor) .send({ from: s.investor, gas: s.gas }); // const post = await getAllBalances(s, s.accounts, s.fund, s.environment); const postTotalSupply = yield s.fund.shares.methods.totalSupply().call(); expect(postTotalSupply).toEqual(token_math_1.add(token_math_1.toBI(preTotalSupply), wantedShares)); })); test(`Exchange ${i + 1}: manager makes order, sellToken sent to exchange`, () => __awaiter(this, void 0, void 0, function* () { const pre = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePreMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePreEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); const preIsMlnInAssetList = yield s.fund.accounting.methods .isInAssetList(s.mln.options.address) .call(); yield s.fund.trading.methods .callOnExchange(i, orderSignatures_1.makeOrderSignature, [ randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), s.weth.options.address, s.mln.options.address, randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), ], [ `${s.trade1.sellQuantity}`, `${s.trade1.buyQuantity}`, 0, 0, 0, 0, 0, 0, ], randomHexOfSize_1.randomHexOfSize(20), '0x0', '0x0', '0x0') .send({ from: s.manager, gas: s.gas }); const exchangePostMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePostEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); const post = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const postIsMlnInAssetList = yield s.fund.accounting.methods .isInAssetList(s.mln.options.address) .call(); const openOrdersAgainstMln = yield s.fund.trading.methods .openMakeOrdersAgainstAsset(s.mln.options.address) .call(); expect(exchangePostMln).toEqual(exchangePreMln); expect(exchangePostEthToken).toEqual(token_math_1.add(exchangePreEthToken, token_math_1.toBI(s.trade1.sellQuantity))); expect(post.fund.weth).toEqual(pre.fund.weth); expect(post.deployer.mln).toEqual(pre.deployer.mln); expect(postIsMlnInAssetList).toBeTruthy(); expect(preIsMlnInAssetList).toBeFalsy(); expect(Number(openOrdersAgainstMln)).toEqual(1); })); test(`Exchange ${i + 1}: anticipated taker asset is not removed from owned assets`, () => __awaiter(this, void 0, void 0, function* () { yield s.fund.accounting.methods .performCalculations() .send({ from: s.manager, gas: s.gas }); yield s.fund.accounting.methods .updateOwnedAssets() .send({ from: s.manager, gas: s.gas }); const isMlnInAssetList = yield s.fund.accounting.methods .isInAssetList(s.mln.options.address) .call(); expect(isMlnInAssetList).toBeTruthy(); })); test(`Exchange ${i + 1}: third party takes entire order, allowing fund to receive mlnToken`, () => __awaiter(this, void 0, void 0, function* () { const orderId = yield s.exchanges[i].methods.last_offer_id().call(); const pre = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePreMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePreEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); yield s.mln.methods .approve(s.exchanges[i].options.address, `${s.trade1.buyQuantity}`) .send({ from: s.deployer, gasPrice: 8000000 }); yield s.exchanges[i].methods .buy(orderId, `${s.trade1.sellQuantity}`) .send({ from: s.deployer, gas: s.gas }); yield s.fund.trading.methods .returnBatchToVault([s.mln.options.address, s.weth.options.address]) .send({ from: s.manager, gas: s.gas }); const exchangePostMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePostEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); const post = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); expect(exchangePostMln).toEqual(exchangePreMln); expect(exchangePostEthToken).toEqual(token_math_1.subtract(exchangePreEthToken, token_math_1.toBI(s.trade1.sellQuantity))); expect(post.fund.weth).toEqual(token_math_1.subtract(pre.fund.weth, token_math_1.toBI(s.trade1.sellQuantity))); expect(post.fund.mln).toEqual(token_math_1.add(pre.fund.mln, token_math_1.toBI(s.trade1.buyQuantity))); expect(post.deployer.weth).toEqual(token_math_1.add(pre.deployer.weth, token_math_1.toBI(s.trade1.sellQuantity))); expect(post.deployer.mln).toEqual(token_math_1.subtract(pre.deployer.mln, token_math_1.toBI(s.trade1.buyQuantity))); })); test(`Exchange ${i + // tslint:disable-next-line:max-line-length 1}: third party makes order (sell ETH-T for MLN-T),and ETH-T is transferred to exchange`, () => __awaiter(this, void 0, void 0, function* () { const pre = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePreMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePreEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); yield s.weth.methods .approve(s.exchanges[i].options.address, `${s.trade2.sellQuantity}`) .send({ from: s.deployer, gas: s.gas }); yield s.exchanges[i].methods .offer(`${s.trade2.sellQuantity}`, s.weth.options.address, `${s.trade2.buyQuantity}`, s.mln.options.address) .send({ from: s.deployer, gas: s.gas }); const exchangePostMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePostEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); const post = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); expect(exchangePostMln).toEqual(exchangePreMln); expect(exchangePostEthToken).toEqual(token_math_1.add(exchangePreEthToken, token_math_1.toBI(s.trade2.sellQuantity))); expect(post.deployer.weth).toEqual(token_math_1.subtract(pre.deployer.weth, token_math_1.toBI(s.trade2.sellQuantity))); expect(post.deployer.mln).toEqual(pre.deployer.mln); })); test(`Exchange ${i + 1}: manager takes order (buys ETH-T for MLN-T)`, () => __awaiter(this, void 0, void 0, function* () { const pre = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePreMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePreEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); const orderId = yield s.exchanges[i].methods.last_offer_id().call(); yield s.fund.trading.methods .callOnExchange(i, orderSignatures_1.takeOrderSignature, [ randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), s.weth.options.address, s.mln.options.address, randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), ], [0, 0, 0, 0, 0, 0, `${s.trade2.buyQuantity}`, 0], `0x${Number(orderId) .toString(16) .padStart(64, '0')}`, '0x0', '0x0', '0x0') .send({ from: s.manager, gas: s.gas }); const post = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePostMln = new token_math_1.BigInteger(yield s.mln.methods.balanceOf(s.exchanges[i].options.address).call()); const exchangePostEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); expect(exchangePostMln).toEqual(exchangePreMln); expect(exchangePostEthToken).toEqual(token_math_1.subtract(exchangePreEthToken, token_math_1.toBI(s.trade2.sellQuantity))); expect(post.deployer.mln).toEqual(token_math_1.add(pre.deployer.mln, token_math_1.toBI(s.trade2.buyQuantity))); expect(post.fund.mln).toEqual(token_math_1.subtract(pre.fund.mln, token_math_1.toBI(s.trade2.buyQuantity))); expect(post.fund.weth).toEqual(token_math_1.add(pre.fund.weth, token_math_1.toBI(s.trade2.sellQuantity))); expect(post.fund.ether).toEqual(pre.fund.ether); })); test(`Exchange ${i + 1}: manager makes an order and cancels it`, () => __awaiter(this, void 0, void 0, function* () { yield increaseTime_1.increaseTime(s.environment, 60 * 30); const pre = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePreEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); yield s.fund.trading.methods .returnBatchToVault([s.mln.options.address, s.weth.options.address]) .send({ from: s.manager, gas: s.gas }); yield s.fund.accounting.methods .updateOwnedAssets() .send({ from: s.manager, gas: s.gas }); yield s.fund.trading.methods .callOnExchange(i, orderSignatures_1.makeOrderSignature, [ randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), s.weth.options.address, s.mln.options.address, randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), ], [ `${s.trade2.sellQuantity}`, `${s.trade2.buyQuantity}`, 0, 0, 0, 0, 0, 0, ], randomHexOfSize_1.randomHexOfSize(20), '0x0', '0x0', '0x0') .send({ from: s.manager, gas: s.gas }); const orderId = yield s.exchanges[i].methods.last_offer_id().call(); yield s.fund.trading.methods .callOnExchange(i, orderSignatures_1.cancelOrderSignature, [ randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), s.weth.options.address, s.mln.options.address, randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), ], [0, 0, 0, 0, 0, 0, 0, 0], `0x${Number(orderId) .toString(16) .padStart(64, '0')}`, '0x0', '0x0', '0x0') .send({ from: s.manager, gas: s.gas }); const orderOpen = yield s.exchanges[i].methods.isActive(orderId).call(); const post = yield getAllBalances_1.getAllBalances(s, s.accounts, s.fund, s.environment); const exchangePostEthToken = new token_math_1.BigInteger(yield s.weth.methods.balanceOf(s.exchanges[i].options.address).call()); expect(orderOpen).toBeFalsy(); expect(exchangePostEthToken).toEqual(exchangePreEthToken); expect(post.fund.mln).toEqual(pre.fund.mln); expect(post.fund.weth).toEqual(pre.fund.weth); })); test(`Exchange ${i + 1}: Risk management prevents from taking an ill-priced order`, () => __awaiter(this, void 0, void 0, function* () { yield s.weth.methods .approve(s.exchanges[i].options.address, `${s.trade2.sellQuantity}`) .send({ from: s.deployer, gas: s.gas }); yield s.exchanges[i].methods .offer(`${token_math_1.divide(s.trade2.sellQuantity, 2)}`, s.weth.options.address, `${s.trade2.buyQuantity}`, s.mln.options.address) .send({ from: s.deployer, gas: s.gas }); const orderId = yield s.exchanges[i].methods.last_offer_id().call(); yield expect(s.fund.trading.methods .callOnExchange(i, orderSignatures_1.takeOrderSignature, [ randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), s.weth.options.address, s.mln.options.address, randomHexOfSize_1.randomHexOfSize(20), randomHexOfSize_1.randomHexOfSize(20), ], [0, 0, 0, 0, 0, 0, `${s.trade2.buyQuantity}`, 0], `0x${Number(orderId) .toString(16) .padStart(64, '0')}`, '0x0', '0x0', '0x0') .send({ from: s.manager, gas: s.gas })).rejects.toThrow(); })); });