@melonproject/protocol
Version:
Technology Regulated and Operated Investment Funds
164 lines (163 loc) • 11 kB
JavaScript
"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 token_math_1 = require("@melonproject/token-math");
const initTestEnvironment_1 = require("../../../tests/utils/initTestEnvironment");
const getToken_1 = require("../../dependencies/token/calls/getToken");
const deploy_1 = require("../../dependencies/token/transactions/deploy");
const approve_1 = require("../../dependencies/token/transactions/approve");
const deployTestingPriceFeed_1 = require("../../prices/transactions/deployTestingPriceFeed");
const update_1 = require("../../prices/transactions/update");
const getContract_1 = require("../../../utils/solidity/getContract");
const deployContract_1 = require("../../../utils/solidity/deployContract");
const Contracts_1 = require("../../../Contracts");
const evm_1 = require("../../../utils/evm");
const thaw_1 = require("./thaw");
const sellAndBurnMln_1 = require("./sellAndBurnMln");
const deployEngine_1 = require("./deployEngine");
describe('sellAndBurnMln', () => {
const shared = {};
beforeAll(() => __awaiter(this, void 0, void 0, function* () {
shared.env = yield initTestEnvironment_1.initTestEnvironment();
shared.accounts = yield shared.env.eth.getAccounts();
const wethAddress = yield deploy_1.deployToken(shared.env, 'ETH');
shared.mln = getContract_1.getContract(shared.env, Contracts_1.Contracts.BurnableToken, yield deployContract_1.deployContract(shared.env, Contracts_1.Contracts.BurnableToken, [
'MLN',
18,
'',
]));
shared.weth = yield getContract_1.getContract(shared.env, Contracts_1.Contracts.StandardToken, wethAddress);
shared.version = getContract_1.getContract(shared.env, Contracts_1.Contracts.MockVersion, yield deployContract_1.deployContract(shared.env, Contracts_1.Contracts.MockVersion));
shared.registry = getContract_1.getContract(shared.env, Contracts_1.Contracts.MockRegistry, yield deployContract_1.deployContract(shared.env, Contracts_1.Contracts.MockRegistry));
const feedAddress = yield deployTestingPriceFeed_1.deployTestingPriceFeed(shared.env, yield getToken_1.getToken(shared.env, wethAddress));
shared.feed = yield getContract_1.getContract(shared.env, Contracts_1.Contracts.TestingPriceFeed, feedAddress);
shared.delay = 30 * 24 * 60 * 60;
shared.engineAddress = yield deployEngine_1.deployEngine(shared.env, {
delay: shared.delay,
registry: shared.registry.options.address,
});
shared.priceSource = yield getContract_1.getContract(shared.env, Contracts_1.Contracts.TestingPriceFeed, feedAddress);
shared.engine = getContract_1.getContract(shared.env, Contracts_1.Contracts.Engine, shared.engineAddress);
yield shared.registry.methods
.setPriceSource(shared.priceSource.options.address)
.send({ from: shared.accounts[0] });
yield shared.registry.methods
.setMlnToken(shared.mln.options.address)
.send({ from: shared.accounts[0] });
yield shared.engine.methods
.setRegistry(shared.registry.options.address)
.send({ from: shared.accounts[0], gas: 8000000 });
yield update_1.update(shared.env, feedAddress, [
token_math_1.createPrice(token_math_1.createQuantity(yield getToken_1.getToken(shared.env, wethAddress), 1), token_math_1.createQuantity(yield getToken_1.getToken(shared.env, wethAddress), 1)),
token_math_1.createPrice(token_math_1.createQuantity(yield getToken_1.getToken(shared.env, shared.mln.options.address), 1), token_math_1.createQuantity(yield getToken_1.getToken(shared.env, wethAddress), 2.94)),
]);
}));
it('directly sending eth fails', () => __awaiter(this, void 0, void 0, function* () {
yield expect(shared.env.eth.sendTransaction({
from: shared.env.wallet.address,
to: shared.engine.options.address,
value: 1,
})).rejects.toThrow('revert');
}));
it('eth sent via contract selfdestruct is not tracked', () => __awaiter(this, void 0, void 0, function* () {
const sendEth = new token_math_1.BigInteger('100000000');
const destructing = getContract_1.getContract(shared.env, Contracts_1.Contracts.SelfDestructing, yield deployContract_1.deployContract(shared.env, Contracts_1.Contracts.SelfDestructing));
const preHeldEth = yield shared.env.eth.getBalance(shared.engine.options.address);
expect(Number(preHeldEth)).toBe(0);
yield shared.env.eth.sendTransaction({
from: shared.env.wallet.address,
to: destructing.options.address,
value: Number(sendEth),
});
yield destructing.methods
.bequeath(shared.engine.options.address)
.send({ from: shared.env.wallet.address });
const postHeldEth = yield shared.env.eth.getBalance(shared.engine.options.address);
const frozenEth = yield shared.engine.methods.frozenEther().call();
const liquidEth = yield shared.engine.methods.liquidEther().call();
expect(token_math_1.isEqual(new token_math_1.BigInteger(postHeldEth), sendEth));
expect(Number(frozenEth)).toBe(0);
expect(Number(liquidEth)).toBe(0);
}));
it('AMGU payment fails when sender not fund', () => __awaiter(this, void 0, void 0, function* () {
const sender = shared.env.wallet.address;
const isFund = yield shared.registry.methods.isFund(sender).call();
expect(isFund).toBe(false);
yield expect(shared.engine.methods
.payAmguInEther()
.send({ from: sender, value: 1000000 })).rejects.toThrow('revert');
}));
it('eth sent as AMGU from a "fund" thaws and can be bought', () => __awaiter(this, void 0, void 0, function* () {
const sender = shared.env.wallet.address;
const sendEth = new token_math_1.BigInteger('100000');
yield shared.registry.methods.setIsFund(sender).send({ from: sender });
const isFund = yield shared.registry.methods.isFund(sender).call();
expect(isFund).toBe(true);
yield shared.engine.methods
.payAmguInEther()
.send({ from: sender, value: Number(sendEth) });
const frozenEth = yield shared.engine.methods.frozenEther().call();
const liquidEth = yield shared.engine.methods.liquidEther().call();
expect(token_math_1.isEqual(new token_math_1.BigInteger(frozenEth), sendEth));
expect(Number(liquidEth)).toBe(0);
yield expect(
// early call to thaw fails
shared.engine.methods.thaw().send({ from: shared.accounts[1] })).rejects.toThrow('revert');
const enginePrice = yield shared.engine.methods.enginePrice().call();
const premiumPercent = new token_math_1.BigInteger(yield shared.engine.methods.premiumPercent().call());
const ethPerMln = new token_math_1.BigInteger((yield shared.feed.methods
.getPrice(shared.mln.options.address)
.call()).price);
const premiumPrice = token_math_1.add(ethPerMln, token_math_1.divide(token_math_1.multiply(ethPerMln, premiumPercent), new token_math_1.BigInteger(100)));
expect(`${enginePrice}`).toBe(`${premiumPrice}`);
const sendMln = token_math_1.createQuantity(yield getToken_1.getToken(shared.env, shared.mln.options.address), token_math_1.divide(token_math_1.multiply(sendEth, new token_math_1.BigInteger('1000000000000000000')), premiumPrice));
yield approve_1.approve(shared.env, {
howMuch: sendMln,
spender: shared.engine.options.address,
});
yield expect(
// throws when trying to burn without liquid ETH
sellAndBurnMln_1.sellAndBurnMln(shared.env, shared.engine.options.address, {
quantity: sendMln,
})).rejects.toThrow('revert');
yield evm_1.increaseTime(shared.env, shared.delay);
yield thaw_1.thaw(shared.env, shared.engine.options.address);
const frozenEthPost = yield shared.engine.methods.frozenEther().call();
const liquidEthPost = yield shared.engine.methods.liquidEther().call();
expect(Number(frozenEthPost)).toBe(0);
expect(token_math_1.isEqual(new token_math_1.BigInteger(liquidEthPost), sendEth));
const burnerPreMln = yield shared.mln.methods.balanceOf(sender).call();
const burnerPreEth = yield shared.env.eth.getBalance(sender);
const enginePreEth = yield shared.env.eth.getBalance(shared.engine.options.address);
const preMlnTotalSupply = yield shared.mln.methods.totalSupply().call();
const ethPurchased = yield shared.engine.methods
.ethPayoutForMlnAmount(`${sendMln.quantity}`)
.call();
const receipt = yield sellAndBurnMln_1.sellAndBurnMln(shared.env, shared.engine.options.address, {
quantity: sendMln,
});
const gasUsed = receipt.gasUsed;
const burnerPostMln = yield shared.mln.methods.balanceOf(sender).call();
const burnerPostEth = yield shared.env.eth.getBalance(sender);
const enginePostMln = yield shared.mln.methods
.balanceOf(shared.engine.options.address)
.call();
const enginePostEth = yield shared.env.eth.getBalance(shared.engine.options.address);
const postMlnTotalSupply = yield shared.mln.methods.totalSupply().call();
expect(burnerPostMln).toBe(`${token_math_1.subtract(token_math_1.toBI(burnerPreMln), sendMln.quantity)}`);
expect(burnerPostEth).toBe(`${token_math_1.subtract(token_math_1.add(token_math_1.toBI(burnerPreEth), token_math_1.toBI(ethPurchased)), token_math_1.multiply(token_math_1.toBI(gasUsed), token_math_1.toBI(shared.env.options.gasPrice)))}`);
expect(enginePostMln).toBe(enginePostMln);
expect(`${enginePostMln}`).toBe('0');
expect(enginePostEth).toBe(`${token_math_1.subtract(token_math_1.toBI(enginePreEth), token_math_1.toBI(ethPurchased))}`);
expect(postMlnTotalSupply).toBe(`${token_math_1.subtract(token_math_1.toBI(preMlnTotalSupply), sendMln.quantity)}`);
}));
it('Other contracts can pay amgu on function calls', () => __awaiter(this, void 0, void 0, function* () { }));
it('Engine price and premium computes at multiple values', () => __awaiter(this, void 0, void 0, function* () { }));
});