UNPKG

@gnosis.pm/dex-contracts

Version:

Contracts for dFusion multi-token batch auction exchange

676 lines (675 loc) 24.3 kB
"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)), }, ], });