const Dex = artifacts.require("Dex");
const TestToken = artifacts.require("TestToken");
const truffleAssert = require('truffle-assertions');
contract('Dex', accounts => {
// Deposited ETH > order value of buy order _plus_ any existing buy orders
it("1: should be possible to place BUY order with order value less than ETH balance considering existing buy orders", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.depositETH({value: '50', from: accounts[0]});
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]})
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 10, {from: accounts[0]})
await truffleAssert.passes(
// 2*10 (previous buy order) + 2*10=40 which is less than 50
dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 10, {from: accounts[0]})
);
})
// Deposited ETH < order value of buy order _plus_ any existing buy orders
it("2: should not be possible to place BUY order with order value larger than ETH balance considering existing buy orders", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.depositETH({value: '50', from: accounts[0]});
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]})
await truffleAssert.reverts(
// 200*10=2000 which is larger than 50
dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 200, 10, {from: accounts[0]})
);
})
// Deposited ETH > order value of buy order
it("2a: should not be possible to place BUY order with order value larger than ETH balance. Also considering existing BUY orders!", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.depositETH({value: '50', from: accounts[0]});
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]})
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 5, 10, {from: accounts[0]})
await truffleAssert.reverts(
// 5*10=50 from previous order so the ETH balance is already exhaused. This should fail.
dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 10, {from: accounts[0]})
);
})
// Tokens > sell order ammount
it("3: should be possible to place SELL order with amount less than token balance considering existing order", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]})
await testToken.approve(dex.address, 500);
await dex.deposit(100, web3.utils.fromUtf8("TT"));
await truffleAssert.passes(
dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 20, 10, {from: accounts[0]})
);
})
it("4: should not be possible to place SELL order with amount larger than token balance considering existing order", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]})
await testToken.approve(dex.address, 500);
await dex.deposit(100, web3.utils.fromUtf8("TT"));
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 90, 10, {from: accounts[0]})
await truffleAssert.reverts(
// I only have 100 TT so placing a selling another 15 (105 total) should fail
dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 15, 10, {from: accounts[0]})
);
})
// Buy Orders ordred from high to low
it("5: order book BUY orders should be sorted from high to low", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.depositETH({value: '50', from: accounts[0]});
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 10, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 20, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 5, {from: accounts[0]});
let orderBook = await dex.getOrderBook(web3.utils.fromUtf8("TT"), 0 /* BUY */);
for (let i=0; i<orderBook.length-1; i++) {
currentValue=orderBook[i].price;
nextValue=orderBook[i+1].price;
// Assert that the current price is greater or equal to the next price
assert.isAtLeast(
currentValue, nextValue
);
}
})
it("6: order book SELL orders should be sorted from low to high", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.depositETH({value: '50', from: accounts[0]});
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 2, 10, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 2, 20, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 2, 5, {from: accounts[0]});
let orderBook = await dex.getOrderBook(web3.utils.fromUtf8("TT"), 1 /* SELL */);
for (let i=0; i<orderBook.length-1; i++) {
currentValue=orderBook[i].price;
nextValue=orderBook[i+1].price;
// Assert that the next price is greater or equal to the current price
assert.isAtLeast(
nextValue, currentValue
);
}
})
// It would be fine to allow sell orders with a price lower than the highest buy order however that should execute like a market order.
// We check for that by checking the number of orders in the order book.
it("7: order book SELL with a lower price than the highest buy order should execute as a limit order", async() => {
let dex=await Dex.deployed();
let testToken=await TestToken.deployed();
await dex.depositETH({value: '50', from: accounts[0]});
await dex.addToken(web3.utils.fromUtf8("TT"), testToken.address, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 2, 10, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 2, 20, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */, 2, 30, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 9, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 8, {from: accounts[0]});
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 0 /* BUY */, 2, 7, {from: accounts[0]});
// This should lead to a market order since the sell price is lower than the highes bid. Effectively the 2, 9 limit order should be filled.
await dex.createLimitOrder(web3.utils.fromUtf8("TT"), 1 /* SELL */,2, 8, {from: accounts[0]});
let orderBook = await dex.getOrderBook(web3.utils.fromUtf8("TT"), 1 /* SELL */);
let orderCount=orderBook.length;
// Should be only 5 order since the pervious order should fill the existing limit order
assert.equal(
orderCount, 5
);
})
// It would be fine to allow buy orders with a price higher than the lowes sell order however that should execute like a market order.
// We check for that by checking the number of orders in the order book.
// ToDo: To be implemented
});