@gnosis.pm/dex-contracts
Version:
Contracts for dFusion multi-token batch auction exchange
676 lines (675 loc) • 24.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.utilityOverflow = exports.marginalTrade = exports.stableXExample = exports.smallExample = exports.tooSmallBuyAmountTrade = exports.tooSmallSellAmountTrade = exports.exampleOrderWithUnlimitedAmount = exports.shortRingBetterTrade = exports.largeRing30 = exports.basicRingTrade = exports.biggieSmallTrade = exports.advancedTrade = exports.basicTrade = void 0;
const bn_js_1 = __importDefault(require("bn.js"));
const math_1 = require("../math");
const generate_1 = require("./generate");
__exportStar(require("./generate"), exports);
const ZERO = new bn_js_1.default(0);
exports.basicTrade = generate_1.generateTestCase({
name: "Basic Trade",
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(math_1.toETH(20)).add(math_1.ERROR_EPSILON),
buyAmount: math_1.toETH(10),
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(10),
buyAmount: math_1.feeSubtracted(math_1.toETH(20)).sub(math_1.ERROR_EPSILON),
user: 1,
},
],
solutions: [
{
name: "Full Solution",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [math_1.toETH(10), math_1.feeSubtracted(math_1.toETH(20))],
},
{
name: "Partial Solution",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [math_1.toETH(9), math_1.feeSubtracted(math_1.toETH(18))],
},
],
});
exports.advancedTrade = generate_1.generateTestCase({
name: "Advanced Trade",
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(math_1.toETH(20)).add(math_1.ERROR_EPSILON),
buyAmount: math_1.toETH(10),
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(10),
buyAmount: math_1.feeSubtracted(math_1.toETH(20)).sub(math_1.ERROR_EPSILON),
user: 1,
},
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(math_1.toETH(20)).add(math_1.ERROR_EPSILON),
buyAmount: math_1.toETH(10),
user: 2,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(10),
buyAmount: math_1.feeSubtracted(math_1.toETH(20)).sub(math_1.ERROR_EPSILON),
user: 3,
},
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(math_1.toETH(20)).add(math_1.ERROR_EPSILON),
buyAmount: math_1.toETH(10),
user: 4,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(10),
buyAmount: math_1.feeSubtracted(math_1.toETH(20)).sub(math_1.ERROR_EPSILON),
user: 5,
},
],
solutions: [
{
name: "Match 1 Pair",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [math_1.toETH(10), math_1.feeSubtracted(math_1.toETH(20)), ZERO, ZERO, ZERO, ZERO],
},
{
name: "Match 2 Pairs",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [
math_1.toETH(10),
math_1.feeSubtracted(math_1.toETH(20)),
math_1.toETH(10),
math_1.feeSubtracted(math_1.toETH(20)),
ZERO,
ZERO,
],
},
{
name: "Match 3 Pairs",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [
math_1.toETH(10),
math_1.feeSubtracted(math_1.toETH(20)),
math_1.toETH(10),
math_1.feeSubtracted(math_1.toETH(20)),
math_1.toETH(10),
math_1.feeSubtracted(math_1.toETH(20)),
],
},
],
});
exports.biggieSmallTrade = generate_1.generateTestCase({
name: "Biggie Small",
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.toETH(185),
buyAmount: math_1.toETH(1),
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(1000),
buyAmount: math_1.toETH(184000),
user: 1,
},
],
solutions: [
{
name: "Max Fulfillment",
prices: [math_1.toETH(1), math_1.feeAdded(math_1.toETH(184))],
buyVolumes: [1, 184].map(math_1.toETH),
},
],
});
exports.basicRingTrade = generate_1.generateTestCase({
name: "Basic Ring",
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 0,
},
{
sellToken: 1,
buyToken: 2,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 1,
},
{
sellToken: 2,
buyToken: 0,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 2,
},
],
solutions: [
{
name: "Ring Around the Rosie",
prices: [1, 1, 1].map(math_1.toETH),
buyVolumes: [
math_1.feeSubtracted(math_1.toETH(1), 1),
math_1.feeSubtracted(math_1.toETH(1), 2),
math_1.feeSubtracted(math_1.toETH(1), 3),
],
},
],
});
const n = 30;
exports.largeRing30 = generate_1.generateTestCase({
name: "Longest Ring Trade",
orders: Array.from(Array(n).keys())
.map((i) => ({
sellToken: i % n,
buyToken: (i + 1) % n,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: i % 2,
}))
.concat(Array.from(Array(n).keys()).map((i) => ({
sellToken: i % n,
buyToken: (i + 1) % n,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 2 + (i % 2),
}))),
solutions: [
{
name: "Solution filling ~90% of the available volume",
prices: [
new bn_js_1.default("1000000000000000000"),
new bn_js_1.default("999000000079933840"),
new bn_js_1.default("998001000078845135"),
new bn_js_1.default("997002999140535506"),
new bn_js_1.default("996005996035392883"),
new bn_js_1.default("995009990083786472"),
new bn_js_1.default("994014980130495716"),
new bn_js_1.default("993020965086898658"),
new bn_js_1.default("992027944164247585"),
new bn_js_1.default("991035916140546385"),
new bn_js_1.default("990044880290088817"),
new bn_js_1.default("989054835391299816"),
new bn_js_1.default("988065780510318410"),
new bn_js_1.default("987077714823955022"),
new bn_js_1.default("986090637068828536"),
new bn_js_1.default("985104546427501883"),
new bn_js_1.default("984119441847563266"),
new bn_js_1.default("983135322401663687"),
new bn_js_1.default("982152187132755565"),
new bn_js_1.default("981170034910294548"),
new bn_js_1.default("980188864899078269"),
new bn_js_1.default("979208676045659066"),
new bn_js_1.default("978229467305820489"),
new bn_js_1.default("977251237858427284"),
new bn_js_1.default("976273986614832057"),
new bn_js_1.default("975297712672815304"),
new bn_js_1.default("974322414953157214"),
new bn_js_1.default("973348092529574952"),
new bn_js_1.default("982063340537758779"),
new bn_js_1.default("990991090090097194"),
],
buyVolumes: Array(30)
.fill(new bn_js_1.default(0))
.concat([
new bn_js_1.default("899999909927988434"),
new bn_js_1.default("899999909928898147"),
new bn_js_1.default("899999909873138748"),
new bn_js_1.default("899999909968923181"),
new bn_js_1.default("899999909928736570"),
new bn_js_1.default("899999909895423467"),
new bn_js_1.default("899999909952944811"),
new bn_js_1.default("899999909914445655"),
new bn_js_1.default("899999909986676388"),
new bn_js_1.default("899999909926967303"),
new bn_js_1.default("899999909943800566"),
new bn_js_1.default("899999909985327246"),
new bn_js_1.default("899999909899485749"),
new bn_js_1.default("899999909936269665"),
new bn_js_1.default("899999909940159650"),
new bn_js_1.default("899999909970806338"),
new bn_js_1.default("899999909974515710"),
new bn_js_1.default("899999909925496645"),
new bn_js_1.default("899999909957902274"),
new bn_js_1.default("899999909936146659"),
new bn_js_1.default("899999909925595398"),
new bn_js_1.default("899999909984286761"),
new bn_js_1.default("899999909965948230"),
new bn_js_1.default("899999909971236827"),
new bn_js_1.default("899999909930081941"),
new bn_js_1.default("899999909936534371"),
new bn_js_1.default("899999909944513216"),
new bn_js_1.default("891120914814366045"),
new bn_js_1.default("882209793797187023"),
new bn_js_1.default("873387783197991000"),
]),
},
{
name: "Full solution to large ring trade",
prices: [
new bn_js_1.default("1000000000000000000"),
new bn_js_1.default("999000000080932527"),
new bn_js_1.default("998001000163952351"),
new bn_js_1.default("997002999153048099"),
new bn_js_1.default("996005996120621788"),
new bn_js_1.default("995009990197501127"),
new bn_js_1.default("994014980201782351"),
new bn_js_1.default("993020965255715327"),
new bn_js_1.default("992027944249700231"),
new bn_js_1.default("991035916321243854"),
new bn_js_1.default("990044880335294951"),
new bn_js_1.default("989054835476903275"),
new bn_js_1.default("988065780622280566"),
new bn_js_1.default("987077714922662489"),
new bn_js_1.default("986090637193173669"),
new bn_js_1.default("985104546487832659"),
new bn_js_1.default("984119441958561945"),
new bn_js_1.default("983135322499977058"),
new bn_js_1.default("982152187194035945"),
new bn_js_1.default("981170035069292740"),
new bn_js_1.default("980188864985054793"),
new bn_js_1.default("979208676167400239"),
new bn_js_1.default("978229467438980960"),
new bn_js_1.default("977251237967802060"),
new bn_js_1.default("976273986723981212"),
new bn_js_1.default("975297712793135196"),
new bn_js_1.default("974322415061859070"),
new bn_js_1.default("973348092626909555"),
new bn_js_1.default("982063340537758779"),
new bn_js_1.default("990991090090097095"),
],
buyVolumes: [
new bn_js_1.default("999999900018987366"),
new bn_js_1.default("999999899935720167"),
new bn_js_1.default("999999899946492752"),
new bn_js_1.default("999999899979899439"),
new bn_js_1.default("999999899906533389"),
new bn_js_1.default("999999899912087908"),
new bn_js_1.default("999999899877713252"),
new bn_js_1.default("999999899918800176"),
new bn_js_1.default("999999899902864002"),
new bn_js_1.default("999999899973191776"),
new bn_js_1.default("999999899951005325"),
new bn_js_1.default("999999899970382379"),
new bn_js_1.default("999999899888317721"),
new bn_js_1.default("999999899903089341"),
new bn_js_1.default("999999899972267613"),
new bn_js_1.default("999999899954772667"),
new bn_js_1.default("999999899971684198"),
new bn_js_1.default("999999899954824426"),
new bn_js_1.default("999999899891175087"),
new bn_js_1.default("999999899941337511"),
new bn_js_1.default("999999899893002057"),
new bn_js_1.default("999999899946416798"),
new bn_js_1.default("999999899950243776"),
new bn_js_1.default("999999899956239066"),
new bn_js_1.default("999999899898945833"),
new bn_js_1.default("999999899917915929"),
new bn_js_1.default("999999899938348141"),
new bn_js_1.default("990134349892753397"),
new bn_js_1.default("980233104317120013"),
new bn_js_1.default("970430870317033000"),
].concat(Array(30).fill(new bn_js_1.default(0))),
},
],
});
exports.shortRingBetterTrade = generate_1.generateTestCase({
orders: [
// ring trade orders
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 0,
},
{
sellToken: 1,
buyToken: 2,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 1,
},
{
sellToken: 2,
buyToken: 0,
sellAmount: math_1.toETH(1),
buyAmount: math_1.toETH(0.99),
user: 2,
},
// biggie small orders
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.toETH(185),
buyAmount: math_1.toETH(1),
user: 3,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(1000),
buyAmount: math_1.toETH(184000),
user: 4,
},
],
solutions: [
{
name: "Ring Trade Solution",
prices: [1, 1, 1].map(math_1.toETH),
buyVolumes: [
math_1.feeSubtracted(math_1.toETH(1), 1),
math_1.feeSubtracted(math_1.toETH(1), 2),
math_1.feeSubtracted(math_1.toETH(1), 3),
ZERO,
ZERO,
],
},
{
name: "Biggie Small Trade",
prices: [math_1.toETH(1), math_1.feeAdded(math_1.toETH(184)), ZERO],
buyVolumes: [ZERO, ZERO, ZERO, math_1.toETH(1), math_1.toETH(184)],
},
],
});
const maxUint128 = new bn_js_1.default(2).pow(new bn_js_1.default(128)).sub(new bn_js_1.default(1));
exports.exampleOrderWithUnlimitedAmount = generate_1.generateTestCase({
deposits: [
{ amount: math_1.feeAdded(math_1.toETH(10)), token: 0, user: 0 },
{ amount: math_1.feeAdded(math_1.toETH(10)), token: 1, user: 1 },
],
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: maxUint128,
buyAmount: math_1.feeSubtracted(maxUint128.div(new bn_js_1.default(4))),
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(10),
buyAmount: math_1.feeSubtracted(math_1.toETH(5)),
user: 1,
},
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(maxUint128.div(new bn_js_1.default(2))),
buyAmount: maxUint128,
user: 0,
},
],
solutions: [
{
prices: [1, 0.5].map(math_1.toETH),
buyVolumes: [ZERO, math_1.feeSubtracted(math_1.toETH(5)), math_1.toETH(10)],
},
{
prices: [1, 1].map(math_1.toETH),
buyVolumes: [math_1.toETH(10), math_1.feeSubtracted(math_1.toETH(10)), ZERO],
},
],
}, false, false);
const fiveThousand = new bn_js_1.default("5000");
const tenThousand = new bn_js_1.default("10000");
exports.tooSmallSellAmountTrade = generate_1.generateTestCase({
deposits: [
{ amount: math_1.feeAdded(tenThousand), token: 0, user: 0 },
{ amount: math_1.feeAdded(tenThousand), token: 1, user: 1 },
],
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(tenThousand),
buyAmount: fiveThousand,
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.feeAdded(tenThousand),
buyAmount: fiveThousand,
user: 1,
},
],
solutions: [
{
name: "Small sell amount",
prices: [1, 0.9].map(math_1.toETH),
buyVolumes: [tenThousand, tenThousand],
},
],
}, false, true);
exports.tooSmallBuyAmountTrade = generate_1.generateTestCase({
deposits: [
{ amount: math_1.feeAdded(tenThousand), token: 0, user: 0 },
{ amount: math_1.feeAdded(tenThousand), token: 1, user: 1 },
],
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(tenThousand),
buyAmount: fiveThousand,
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.feeAdded(tenThousand),
buyAmount: fiveThousand,
user: 1,
},
],
solutions: [
{
name: "Small buy amounts",
prices: [1, 1].map(math_1.toETH),
buyVolumes: [10000, 9990].map((val) => new bn_js_1.default(val)),
},
],
}, false, true);
const fiftyThousand = new bn_js_1.default("50000");
const hundredThousand = new bn_js_1.default("100000");
exports.smallExample = generate_1.generateTestCase({
deposits: [
{ amount: math_1.feeAdded(hundredThousand), token: 0, user: 0 },
{ amount: new bn_js_1.default(190), token: 1, user: 1 },
{ amount: new bn_js_1.default(9), token: 0, user: 1 },
{ amount: math_1.feeAdded(hundredThousand), token: 1, user: 2 },
],
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(hundredThousand),
buyAmount: fiftyThousand,
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.feeAdded(hundredThousand),
buyAmount: fiftyThousand,
user: 1,
},
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(hundredThousand),
buyAmount: fiftyThousand,
user: 1,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.feeAdded(hundredThousand),
buyAmount: fiftyThousand,
user: 2,
},
],
solutions: [
{
name: "Small Solution",
prices: [1, 1].map(math_1.toETH),
buyVolumes: [100000, 99900, 99810, 99711].map((val) => new bn_js_1.default(val)),
},
],
});
exports.stableXExample = generate_1.generateTestCase({
deposits: [
{ amount: math_1.toETH(3000), token: 0, user: 0 },
{ amount: math_1.toETH(3000), token: 1, user: 0 },
],
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.toETH(2000),
buyAmount: math_1.toETH(999),
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(999),
buyAmount: math_1.toETH(1996),
user: 1,
},
],
solutions: [
{
name: "Naive Solver",
prices: [math_1.toETH(1), new bn_js_1.default("1999998997996995993")],
buyVolumes: [math_1.toETH(999), new bn_js_1.default("1996000999999999998010")],
},
],
});
exports.marginalTrade = generate_1.generateTestCase({
name: "Marginal Trade",
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(math_1.toETH(20)).add(math_1.ERROR_EPSILON),
buyAmount: math_1.toETH(10),
user: 0,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(10),
buyAmount: math_1.feeSubtracted(math_1.toETH(20)).sub(math_1.ERROR_EPSILON),
user: 1,
},
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.feeAdded(math_1.toETH(200000)).add(math_1.ERROR_EPSILON),
buyAmount: math_1.toETH(100000),
user: 2,
},
{
sellToken: 1,
buyToken: 0,
sellAmount: math_1.toETH(100000),
buyAmount: math_1.feeSubtracted(math_1.toETH(200000)).sub(math_1.ERROR_EPSILON),
user: 3,
},
],
solutions: [
{
name: "First Solution",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [math_1.toETH(10), math_1.feeSubtracted(math_1.toETH(20)), ZERO, ZERO],
},
{
name: "Marginally Solution",
prices: [1, 2].map(math_1.toETH),
buyVolumes: [ZERO, ZERO, math_1.toETH(100000), math_1.feeSubtracted(math_1.toETH(200000))],
},
],
});
exports.utilityOverflow = generate_1.generateTestCase({
deposits: [
{ amount: math_1.toETH(10), token: 0, user: 0 },
{ amount: math_1.toETH(1), token: 1, user: 1 },
{ amount: math_1.toETH(100), token: 2, user: 2 },
],
orders: [
{
sellToken: 0,
buyToken: 1,
sellAmount: math_1.toETH(10),
buyAmount: new bn_js_1.default("10000000000000000"),
user: 0,
},
{
sellToken: 1,
buyToken: 2,
sellAmount: math_1.toETH(1),
buyAmount: new bn_js_1.default("1000"),
user: 1,
},
{
sellToken: 2,
buyToken: 1,
sellAmount: math_1.toETH(100),
buyAmount: math_1.toETH(1),
user: 2,
},
],
solutions: [
{
name: "Utility Overflow",
prices: [
"1000000000000000000",
"998999900119977150048",
"10000000000198528574",
].map((val) => new bn_js_1.default(val)),
buyVolumes: [
"1998999800099984",
"99800080039994614733",
"998000900199892164",
].map((val) => new bn_js_1.default(val)),
},
],
});