Assignment - Limit Order Test

Post your solutions and questions to the Limit Order Test Assignment below

Here are my tests:


// The user must have ETH deposited such that deposited eth >= buy order value
// The user must have enough tokens deposited such that token balance >= sell order amount
// The BUY order book should be ordered on price from highest to lowest starting at index 0
// The SELL order book should be ordered on price from lowest to highest starting at index 0
// The User should not be able to create for not supported tokens

const Dex = artifacts.require("Dex")
const Link = artifacts.require("Link")
const truffleAssert = require('truffle-assertions')

contract("Dex", accounts => {

    let dex;
    let link;

    before(async function(){
        dex = await Dex.deployed();
        link = await Link.deployed();
    });


    it("should only be possible to create a BUY limit order that the user can afford", async () => {
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 3,1)
        );

        await dex.depositETH({value: 3});

        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 3,1)
        );
    })

    it("should only be possible to create a SELL limit order that the user can afford", async () => {
        
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5,1)
        );

        await dex.addtoken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await link.approve(dex.address, 5)
      
        await dex.deposit(5, web3.utils.fromUtf8("LINK"));

        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5,1)
        );
    })
    it("should order the BUY order book in decending order", async () => {
        const invalidOrder = [12,2,5,9,45,3];
        await link.approve(dex.address, 1000);
        await dex.depositETH({value: 1000});
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));

        for (let i = 0; i< invalidOrder.length; i++){
            await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, invalidOrder[i], 1);
        }

        const orderBook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 0);
        assert.equals(orderBook.length, invalidOrder.length, "Missing orders in the order book");
        for (let i = 0; i< orderBook.length -1; i++){
            assert(orderBook[i].price >= orderBook[i+1].price, "Invalid price order")
        }
    })

    it("should order the SELL order book in ascending order", async () => {
        const invalidOrder = [12,2,5,9,45,3];
        await link.approve(dex.address, 1000);

        for (let i = 0; i< invalidOrder.length; i++){
            await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, invalidOrder[i], 1);
        }

        const orderBook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1);
        assert.equals(orderBook.length, invalidOrder.length, "Missing orders in the order book");
        for (let i = 0; i< orderBook.length -1; i++){
            assert(orderBook[i].price <= orderBook[i+1].price, "Invalid price order")
        }
    })

    it("should only be possible for the user to create orders for supported tokens", async () => {
        await link.approve(dex.address, 1000);
        await dex.deposit(1000, web3.utils.fromUtf8("LINK"));
        await truffleAssert.passes(dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 10, 1));
        await truffleAssert.passes(dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 500, 10, 2));
        await truffleAssert.reverts(dex.createLimitOrder(web3.utils.fromUtf8("ADA"), 0, 10, 1));
        await truffleAssert.reverts(dex.createLimitOrder(web3.utils.fromUtf8("ADA"), 500, 10, 2));
    })
})
2 Likes

My tests, finally:



const Dex = artifacts.require("Dex")
const Link = artifacts.require("Link")
const truffleAssert = require('truffle-assertions');

contract("Dex", accounts => {
    //Check that buyer has enough ETH to submit order
    it("should throw an error if ETH balance is too low when creating BUY limit order", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await truffleAssert.reverts(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)
        )
        dex.depositEth({value: 10})         //ETH deposit so Order will now pass!
        await truffleAssert.passes(
          dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)
        )
    })
    //Check that buyer has enough LINK to submit Sell order
    it("should throw an error if token balance is too low when creating SELL limit order", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]}) //Token needs to be added first as this is a new instance!
        await truffleAssert.reverts(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 10, 1) //Shoud revert because no allowance and no link deposit!
        )
        await link.approve(dex.address, 500);
        await dex.deposit(10, web3.utils.fromUtf8("LINK"));
        await truffleAssert.passes(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 10, 1) //should pass, because allowance is set and tokens are deposited!
        )
    })
    //Check that sort is right: index 0 = highest price, then decreasing
    it("The BUY order book should be ordered on price from highest to lowest starting at index 0", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await link.approve(dex.address, 500); 
        await dex.depositEth({value: 3000});
       //submit orders with random price
        await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 1, 300)
        await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 1, 100)
        await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 1, 200)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 0); //set variable for Link orderbook and initialize with getter function
        assert(orderbook.length > 0);  //check that there are more than 1 orders
        console.log(orderbook);  //log the book to check visually check that sorting works
        for (let i = 0; i < orderbook.length - 1; i++) {  //loop with assert check that sorting is right!
            assert(orderbook[i].price >= orderbook[i+1].price, "Order book is not sorted!")
        }
    })
       //Check that sort is right: index 0 = lowest price, then decreasing
    it("The SELL order book should be ordered on price from lowest to highest starting at index 0", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await link.approve(dex.address, 500);
        await dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 1, 300)
        await dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 1, 100)
        await dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 1, 200)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1);
        assert(orderbook.length > 0);
        for (let i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i].price <= orderbook[i+1].price, "Order book not sorted!")
        }
    })
})
1 Like

Wasn’t able to really test the test since we haven’t implemented the functions yet but should probably be something like this:

const Dex = artifacts.require("Dex");
const Link = artifacts.require("Link");
const truffleAssert = require('truffle-assertions');

//user must have eth deposited so that eth >= buy order value
//user must have enough tokens deposited so that token balance >= sell order amount
//the BUY order book should be ordered on price from highest to lowest starting at index 0
//the SELL order book should be ordered on price from lowest to highest starting at index 0
//if an order is placed for the same price by the same user the order should be merged with the existing order - not implemented

contract("Dex", accounts =>{
    it("Should only be possible to place a buy order with sufficient eth", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await dex.depositEther({value: web3.utils.toWei("3", "ether")});
        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 1, web3.utils.toWei("2", "ether"))
        )
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 1, web3.utils.toWei("4", "ether"))
        )
    })
    it("Should only be possible to place sell order with sufficient tokens", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        
        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 1, web3.utils.toWei("2", "ether"))
        )
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 200, web3.utils.toWei("2", "ether"))
        )
    })
    it("BUY orderbook should be ordered on price from highest to lowest starting at index 0", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"),0);
        //add some orders in unordered price sequence
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 1, web3.utils.toWei("2", "mwei"));
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 1, web3.utils.toWei("1", "mwei"));
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, 1, web3.utils.toWei("4", "mwei"));
        //traverse orderbook and make sure each element.price is <= the next
        var i;
        var lastprice = orderbook[0].price;
        for (i = 0; i < orderbook.length; i++) {
        assert(orderbook[i].price <= lastprice, "BUY Orderbook prices not descending");
        lastprice = orderbook[i].price
        }
    })
    it("SELL orderbook should be ordered on price from highest to lowest starting at index 0", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"),1);
        //add some orders in unordered price sequence
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 1, web3.utils.toWei("2", "mwei"));
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 1, web3.utils.toWei("1", "mwei"));
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 1, web3.utils.toWei("4", "mwei"));
        //traverse orderbook and make sure each element.price is <= the next
        var i;
        var lastprice = orderbook[0].price;
        for (i = 0; i < orderbook.length; i++) {
        assert(orderbook[i].price >= lastprice, "SELL Orderbook prices not ascending");
        lastprice = orderbook[i].price
        }
    })
})

Forgot to post mine:

My solution:

3_Dex_test.js
//Contracts
const ERC20 = {
    link: artifacts.require("Link"),
    dai: artifacts.require("Dai")
}

const Dex = artifacts.require("Dex");
const truffleAssert = require('truffle-assertions');

const orderType ={
    buy: 0,
    sell: 1
}

const {
    BN,           // Big Number support
    constants,    // Common constants, like the zero address and largest integers
    expectEvent,  // Assertions for emitted events
    expectRevert, // Assertions for transactions that should fail
  } = require('@openzeppelin/test-helpers');
  
//track balance
const balance = require('@openzeppelin/test-helpers/src/balance');
const { web3 } = require('@openzeppelin/test-helpers/src/setup');
const { assertion } = require('@openzeppelin/test-helpers/src/expectRevert');

// Main function that is executed during the test
contract.skip("DEX", ([owner, alfa, beta, charlie]) => {
            // Global variable declarations
    let linkInstance;
    let daiInstance;
    let dexInstance;
    let _ticker;
    let _qtyEth = function(_amount) {
        return (web3.utils.toWei(_amount.toString(), "ether"))
    }
    async function _symbol(_tokenInstance){
        let _res = await _tokenInstance.symbol();
        _res = web3.utils.fromUtf8(_res);
        return _res;
    }

    //set contracts instances
    before(async function() {
        // Deploy tokens to testnet
        linkInstance = await ERC20.link.new(_qtyEth(1000));
        daiInstance = await ERC20.dai.new(_qtyEth(1000));
        dexInstance = await Dex.new();
    });

    describe("DEX", () => {

        it("1. DEPOSIT TOKEN: addToken, approve, deposit tokens correctly, emit Approval event", async function (){
            _ticker = await _symbol(linkInstance);
            await dexInstance.addToken( _ticker, linkInstance.address);

            const _linkApprove = await linkInstance.approve( dexInstance.address , _qtyEth(100) ,{from: owner}) ;
            await dexInstance.depositToken( _qtyEth(1) , _ticker ,{from: owner});

            expectEvent(_linkApprove, 'Approval', {
                owner: owner,
                spender: dexInstance.address,
                value: _qtyEth(100)
            });

        });

        it("2. WITHDRAW TOKEN correctly", async function (){

            await dexInstance.withdrawToken( _qtyEth(1), _ticker, {from: owner});

            await expectRevert(
                dexInstance.withdrawToken( _qtyEth(1), _ticker, {from: alfa}),
                "Balance not sufficient"
            );

        });

        //The user must have ETH deposited such that deposited eth >= buy order value
        it("3. REVERT: createLimitOrder(BUY), not enough ETH Balance", async () => {

            await expectRevert(
            dexInstance.createLimitOrder(orderType.buy, _ticker, _qtyEth(1), _qtyEth(1), {from: owner}),
            "createLimitOrder: Not enough ETH Balance deposited"
            );

            await dexInstance.depositEth({value: _qtyEth(1), from: owner});
        })
        it("4. REVERT: createLimitOrder(SELL), not enough Token Balance", async () => {

            await expectRevert(
            dexInstance.createLimitOrder(orderType.sell, _ticker, _qtyEth(1), _qtyEth(1), {from: owner}),
            "createLimitOrder: Not enough Token Balance deposited"
            );
            await dexInstance.depositToken( _qtyEth(1), _ticker, {from: owner});
        })

        // Sorting BUY(low to high) and SELL(high to low)
        it("5. The BUY order book should be ordered on price from highest to lowest starting at index 0", async function (){
            await dexInstance.createLimitOrder(orderType.buy, _ticker, _qtyEth(1), _qtyEth(0.3), {from: owner});
            await dexInstance.createLimitOrder(orderType.buy, _ticker, _qtyEth(1), _qtyEth(0.1), {from: owner});
            await dexInstance.createLimitOrder(orderType.buy, _ticker, _qtyEth(1), _qtyEth(0.2), {from: owner});
        
            const buyOrderBook = await dexInstance.getOrderBook(_ticker, orderType.buy);
            assert(buyOrderBook.length > 0);
            for(let _i = 0; _i < buyOrderBook.length -1; _i++){
                assert(buyOrderBook[_i].price >= buyOrderBook[_i+1].price, "BUY shorting inccorect");
            }
        });

        it("6. The SELL order book should be ordered on price from lowest to highest starting at index 0", async function (){
            await dexInstance.createLimitOrder(orderType.sell, _ticker, _qtyEth(1), _qtyEth(3), {from: owner});
            await dexInstance.createLimitOrder(orderType.sell, _ticker, _qtyEth(1), _qtyEth(1), {from: owner});
            await dexInstance.createLimitOrder(orderType.sell, _ticker, _qtyEth(1), _qtyEth(2), {from: owner});
        
            const sellOrderBook = await dexInstance.getOrderBook(_ticker, orderType.sell);
            assert(sellOrderBook.length > 0);
            for(let _i = 0; _i < sellOrderBook.length -1; _i++){
                assert(sellOrderBook[_i].price <= sellOrderBook[_i+1].price, "SELL shorting inccorect");
            }
        });

    }); //end describe
}); // end contract

Carlos Z

2 Likes

Hi, here’s how my function header looks like:

function createLimitOrder(bytes32 ticker, Side side, address trader, uint price, uint amount) public {}

And here’s my conceptual take on the testing file (probably far of functional):

// buy order value <= user deposited ETH
// sell order amount <= User token balance
// Buy order book ordered from highest to lowest price
// Sell order book ordered from lowest to highest price

const Dex = artifacts.require("Dex")
const Link = artifacts.require("Link")
const truffleAssert = require('truffle-assertions');

contract("Dex", accounts => {
    it("should revert if buy order value <= user deposited ETH, pass otherwise", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, accounts[0], 4, 5)
        )

        await dex.depositETH({value: 6});

        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, accounts[0], 4, 5)
        )
    })

    it("should revert if token sell order amount > user token balance, pass otherwise", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await link.approve(dex.address, 500);

        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, accounts[0], 4, 5)
        )    
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, accounts[0], 4, 5)
        )    
    })

    it("should have the buy order book ordered from highest to lowest price", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, accounts[0], 4, 5)
        dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, accounts[0], 2, 8)
        dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 0, accounts[0], 8, 3)

        truffleAssert(orderBook[web3.utils.fromUtf8("LINK")][0][0].price > orderBook[web3.utils.fromUtf8("LINK")][0][1].price)
        truffleAssert(orderBook[web3.utils.fromUtf8("LINK")][0][1].price > orderBook[web3.utils.fromUtf8("LINK")][0][2].price)
    })

    it("should have the sell order book ordered from lowest to highest price", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, accounts[0], 4, 5)
        dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, accounts[0], 2, 8)
        dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, accounts[0], 8, 3)

        truffleAssert(orderBook[web3.utils.fromUtf8("LINK")][1][0].price > orderBook[web3.utils.fromUtf8("LINK")][1][1].price)
        truffleAssert(orderBook[web3.utils.fromUtf8("LINK")][1][1].price > orderBook[web3.utils.fromUtf8("LINK")][1][2].price)
    })

    
})
1 Like

Okay! Here is my solution

const Dex = artifacts.require("Dex")
const Link = artifacts.require("Link")
const truffleAssert = require('truffle-assertions')

contract("Dex", accounts => {
    it("should have suffice ETH deposit to place buy order", async () => {
        let dex = await Dex.deployed()

        dex.deposit(1000, web3.utils.fromUtf8("ETH"), {from: accounts[0]})
        dex.deposit(1000, web3.utils.fromUtf8("ETH"), {from: accounts[1]})

        truffleAssert.passes(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 5, 100, {from: accounts[0]})
        )
        truffleAssert.reverts(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 5, 300, {from: accounts[1]})

        )
    })
    it("should have suffice token deposit to place sell order", async () => {
        let dex = await Dex.deployed()

        dex.deposit(1000, web3.utils.fromUtf8("LINK"), {from: accounts[0]})
        dex.deposit(1000, web3.utils.fromUtf8("LINK"), {from: accounts[1]})

        truffleAssert.passes(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 100, 100, {from: accounts[0]})
        )
        truffleAssert.reverts(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 2000, 300, {from: accounts[1]})

        )
    })
    it("should sort orders correctly", async () => {
        let dex = await Dex.deployed()

        dex.deposit(10000, web3.utils.fromUtf8("LINK"), {from: accounts[0]})
        dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 100, 400, {from: accounts[0]})
        dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 100, 300, {from: accounts[0]})
        dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 100, 100, {from: accounts[0]})
        
        assert.equal(dex.orderBook[web3.utils.fromUtf8("LINK")][1][0].price, 100)
        assert.equal(dex.orderBook[web3.utils.fromUtf8("LINK")][1][1].price, 300)
        assert.equal(dex.orderBook[web3.utils.fromUtf8("LINK")][1][2].price, 400)
        
    })
})
1 Like

OKay heres my homework, pretty bad compared to the others but hey, truffle is hard to get used to-.- okay?-.- xD

DexTest.js
// The user must have ETH deposited such that deposited eth >= buy order value  X
// The user must have enough tokens  such that tokens balance >= sell order amount
// The buy order book should be ordered on price from highest to lowest starting at index 0
// The sell order book should be ordered on price from lowest to highest at index 0
// The buy orders price should be lower than current price 
// The sell orders price should be higher than current price

const Dex = artifacts.require("Dex")
const Ethereum = artifacts.require("Ethereum")
const Link = artifacts.require("Link")
const { reverts } = require('truffle-assertions');
const truffleAssert = require('truffle-assertions');

contract("Dex", accounts => { 
    it("should only be possible to buy if you have enough ETH", async () => {
        let dex = await Dex.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await eth.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ETH"));
        await truffleAssert.reverts(
            dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),200, 4)
        ) 

    })

    it("should have enough tokens such that tokens balance >= sell order amount ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        await truffleAssert.reverts(
            dex.limitSell(web3.utils.fromUtf8("LINK"), 150, 6)
        ) 

    })

    it("The buy order book should be ordered on price from highest to lowest starting at index 0 ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await eth.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ETH"));
        await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),1, 4)
        await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),1, 3)
        let buyOrder0 = await dex.getBuys(0)
        let buyOrder1 = await dex.getBuys(1)
            assert(buyOrder0 >  buyOrder1, "value at index 0 should be greater than value at 1") 
  
    })

    it("The sell order book should be ordered on price from lowest to highest at index 0 ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        await dex.limitSell(web3.utils.fromUtf8("LINK"),1, 6)
        await dex.limitSell(web3.utils.fromUtf8("LINK"),1, 7)
        let sellOrder0 = await dex.getSells(0)
        let sellOrder1 = await dex.getSells(1)
         assert(sellOrder0 <  sellOrder1, "value at index 0 should be smaller than value at 1")
        

    })

    it("buy orders price should be lower than current price ", async () => {
        let dex = await Dex.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await eth.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ETH"));
        await truffleAssert.reverts(
            dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),5, 6)
        ) 

    })

    it("The sell orders price should be higher than current price ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        await truffleAssert.reverts(
            dex.limitSell(web3.utils.fromUtf8("LINK"), 10 , 4)
        ) 

    })

})
Dex.sol
pragma solidity ^0.8.0;

pragma abicoder v2;

import "../contracts/wallet.sol";

contract Dex is Wallet{

struct Order{
    uint id;
    address trader;
    bool buySell;
    bytes32 ticker;
    uint amount;
    uint price;
}

mapping(bytes32 =>mapping(bool =>Order[])) public orderBook;


//function getOrderBook(bytes32 ticker, bool buysell )public view returns(Order[]memory){

//}

uint [] sellOrders;

uint[] buyOrders;

uint linkPrice = 5; 

function limitSell(bytes32 ticker, uint256 amount,uint256 price)public{
    require(amount <= balances[msg.sender][ticker], "not enough funds");
    require(price > linkPrice, "Do not sell it for that little");
    sellOrders.push(price);   
}

function limitBuy(bytes32 ticker,bytes32 buyWith, uint256 amount, uint256 price)public{
    require(price < linkPrice, "Do not buy it for that much");
    require(amount*price <= balances[msg.sender][buyWith], "not enough funds");
    buyOrders.push(price); 
} 

function getBuys(uint _index) public view returns(uint){
    return buyOrders[_index];
}

function getSells(uint _index) public view returns(uint){
    return sellOrders[_index];
}

}

My testing skills are superlooow, but ayayy too many new lines of code to learn, plus im gonna keep practicing my testing.

I just finished whatching filips video, im copying some stuff xp

DExTest #2
// The user must have ETH deposited such that deposited eth >= buy order value  X
// The user must have enough tokens  such that tokens balance >= sell order amount
// The buy order book should be ordered on price from highest to lowest starting at index 0
// The sell order book should be ordered on price from lowest to highest at index 0
// The buy orders price should be lower than current price 
// The sell orders price should be higher than current price

const Dex = artifacts.require("Dex")
const Ethereum = artifacts.require("Ethereum")
const Link = artifacts.require("Link")
const { reverts } = require('truffle-assertions');
const truffleAssert = require('truffle-assertions');

contract("Dex", accounts => { 
    it.skip("should only be possible to buy if you have enough ETH", async () => {
        let dex = await Dex.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await eth.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ETH"));
        await truffleAssert.reverts(
            dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),200, 4)
        ) 

    })

    it.skip("should have enough tokens such that tokens balance >= sell order amount ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        await truffleAssert.reverts(
            dex.limitSell(web3.utils.fromUtf8("LINK"), 150, 6)
        ) 

    })

    it.skip("The BUY order book should be ordered on price from highest to lowest starting at index 0", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await eth.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ETH"));
        await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),1, 4)
        await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),1, 2)
        await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),1, 3)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), true);
        for (let i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i] >= orderbook[i+1], "should be in the right order")
        }
    })

    it.skip("The sell order book should be ordered on price from lowest to highest at index 0 ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        await dex.limitSell(web3.utils.fromUtf8("LINK"),1, 6)
        await dex.limitSell(web3.utils.fromUtf8("LINK"),1, 8)
        await dex.limitSell(web3.utils.fromUtf8("LINK"),1, 7)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), false);
        for (let i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i] >= orderbook[i+1], "should be in the right order")
        }
    })

    it("buy order price should be lower than current price ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await eth.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ETH"));
        await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),1, 4)
        await truffleAssert.reverts(
            await dex.limitBuy(web3.utils.fromUtf8("LINK"), web3.utils.fromUtf8("ETH"),5, 2)
        ) 

    })

    it("The sell orders price should be higher than current price ", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        let eth = await Ethereum.deployed()
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await dex.addToken(web3.utils.fromUtf8("ETH"), eth.address, {from: accounts[0]})
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"));
        await dex.limitSell(web3.utils.fromUtf8("LINK"),1, 6)
        await truffleAssert.reverts(
            await dex.limitSell(web3.utils.fromUtf8("LINK"), 5 , 3)
        ) 

    })

})
Dex #2
pragma solidity ^0.8.0;

pragma abicoder v2;

import "../contracts/wallet.sol";

contract Dex is Wallet{

struct Order{
   // uint id;
   // address trader;
   // bool buySell;
   // bytes32 ticker;
   // uint amount;
    uint price;
}

mapping(bytes32 =>mapping(bool =>Order[])) public orderBook;


function getOrderBook(bytes32 ticker, bool buysell )public view returns(Order [] memory){
 return orderBook[ticker][buysell];
}

function limitSell(bytes32 ticker, uint256 amount,uint256 price)public{
    if(orderBook[ticker][false].length > 0){
        require(price >= orderBook[ticker][false][0].price, "Do not sell it for that little");
    }
    require(amount <= balances[msg.sender][ticker], "not enough funds");
    orderBook[ticker][false].push(Order(price));   
}

function limitBuy(bytes32 ticker,bytes32 buyWith, uint256 amount, uint256 price)public{
    if(orderBook[ticker][true].length > 0){
        require(price <= orderBook[ticker][true][0].price, "Do not buy for that much");
    } 
    require(amount*price <= balances[msg.sender][buyWith], "not enough funds");
    orderBook[ticker][true].push(Order(price)); 
} 

}

Im getting a weird error with my revert assertion, my last two revert assertions, they are not passing even tho the functions are failling where they are expected to fail and i even receive the error message that i planted there, also i have tested the scenario where they dont fail and i get the error message saying that my revert assertion did not fail, idk whats going on there but imma leave it there and if the error hunts me again in the future then im gonna have to something about it, but as of right now i cant see why is this failing -.-

Hi @Carlosvh96

What are the two tests failing?

the last two tests, of my DexTest#2, my little brain cant comprehend what happening there xD

Took me a while but i think i got it

const Dex = artifacts.require("Dex");
const ADA = artifacts.require("ADA");
const truffleAssert = require("truffle-assertions");

contract ("Dex", accounts => {
    // the user must have eth deposited such that deposited eth is >= to buy order value
    it("user's deposited ETH is >= buy order", async () => {
        let dex = await Dex.deployed()
        let ada = await ADA.deployed()

        await truffleAssert.reverts( //buy will not be created due to no ETH
            dex.createLimitOrder(0, web3.utils.fromUtf8("ADA"), 10, 1)
        )
        dex.depositEth({value: 10}) //Eth deposited so will be created
        await truffleAssert.passes( 
            dex.createLimitOrder(0, web3.utils.fromUtf8("ADA"), 10, 1)
        )
        //createLimitOrder(Side side, bytes32 ticker, uint amount, uint price) public {
    })
    // the user must have enough tokens deposited such that token balance is >= to sell order amount
    it("user's token balance is >= sell order amount", async () => {
        let dex = await Dex.deployed()
        let ada = await ADA.deployed()
        await dex.addToken(web3.utils.fromUtf8("ADA"), ada.address, {from: accounts[0]})
        await truffleAssert.reverts( //reverts because no ADA approved or deposited
            dex.createLimitOrder(1, web3.utils.fromUtf8("ADA"), 10, 1)
        )
        await ada.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("ADA"));
        await truffleAssert.passes( //passes because deposit has been approved and settled
            dex.createLimitOrder(1, web3.utils.fromUtf8("ADA"), 10, 1)
        )

        //createLimitOrder(Side side, bytes32 ticker, uint amount, uint price) public {
    })

    // the buy order should be ordered on price from highest to lowest from index 0
    it("(Buy Order)should be in order from highest to lowest", async ()=> {
        let dex = await Dex.deployed()
        let ada = await ADA.deployed()
        await ada.approve(dex.address, 500);
        await dex.depositEth({value: 1000}, web3.utils.fromUtf8("ADA"));
        
        dex.createLimitOrder(0, web3.utils.fromUtf8("ADA"), 1, 100)
        dex.createLimitOrder(0, web3.utils.fromUtf8("ADA"), 1, 300)
        dex.createLimitOrder(0, web3.utils.fromUtf8("ADA"), 1, 250)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("ADA"), 0)
        assert(orderbook.length > 0)
        var i;
        for(i = 0; i < orderbook.length -1; i++){
            assert (orderbook[i].price >= orderbook[i+1].price, "Buy order Book has not bee sorted")
        }
    })

    // the sell order should be ordered on price from highest to lowest from index 0
    it("(Sell Order)should be in order from highest to lowest", async ()=> {
        let dex = await Dex.deployed()
        let ada = await ADA.deployed()
        await ada.approve(dex.address, 500);
        await dex.depositEth({value: 1000}, web3.utils.fromUtf8("ADA"));
        
        dex.createLimitOrder(1, web3.utils.fromUtf8("ADA"), 1, 100)
        dex.createLimitOrder(1, web3.utils.fromUtf8("ADA"), 1, 300)
        dex.createLimitOrder(1, web3.utils.fromUtf8("ADA"), 1, 250)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("ADA"), 0)
        assert(orderbook.length > 0)
        var i;
        for(i = 0; i < orderbook.length; i++){
            assert (orderbook[i].price <= orderbook[i+1].price, "Sell order Book has not bee sorted")
        }
    })
});
1 Like

Maybe is in this way.

const Dex = artifacts.require("Dex");
const Link = artifacts.require("Link");
const truffleAssert = require('truffle-assertions');

contract("Dex", accounts =>{
    it("The user must have ETH deposited such that deposit eth >= buy order value", async() =>{
        let dex = await Dex.deployed();
        await truffleAssert.reverts(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"),10, 0 ))
        await dex.DepositETH({value: web3.utils.toWei('1', 'ether')}, accounts[0]);
        await truffleAssert.passes(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 10, 0 ))


    })

    it("The user must have enough tokens deposited such that token balance >= sell order amount ", async() =>{
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        await truffleAssert.reverts(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 100, 1 ))
        await link.approve(dex.address, 500 ); 
        await dex.deposit(100, web3.utils.fromUtf8("LINK")); 
        await truffleAssert.passes(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 100, 1 ))

        
    })

    it("The BUY order book should be ordered on price from highest to lowest starting at index 0 ", async() =>{
        let dex = await Dex.deployed();
    
        await dex.DepositETH({value: web3.utils.toWei('1', 'ether')}, accounts[0]);
        await dex.DepositETH({value: web3.utils.toWei('1', 'ether')}, accounts[1]);
        await dex.DepositETH({value: web3.utils.toWei('1', 'ether')}, accounts[2]);
        await truffleAssert.passes(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 10, 0 ))
        await truffleAssert.passes(dex.createLimitOrder(accounts[1],web3.utils.fromUtf8("LINK"), 100, 0 ))
        await truffleAssert.passes(dex.createLimitOrder(accounts[2],web3.utils.fromUtf8("LINK"), 7, 0 ))
        assert.equal(orderBook[web3.utils.fromUtf8("LINK")][0][0].price, 100)
        assert.equal(orderBook[web3.utils.fromUtf8("LINK")][0][1].price, 10)
        assert.equal(orderBook[web3.utils.fromUtf8("LINK")][0][2].price, 7)
        
    })

    it("The SELL order book should be ordered on price from highest to lowest starting at index 0 ", async() =>{
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        await link.approve(dex.address, 500 ); 
        await dex.deposit(100, web3.utils.fromUtf8("LINK")); 
        await truffleAssert.passes(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 10, 1 ))
        await truffleAssert.passes(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 5, 1 ))
        await truffleAssert.passes(dex.createLimitOrder(accounts[0],web3.utils.fromUtf8("LINK"), 20, 1 ))

        assert.equal(orderBook[web3.utils.fromUtf8("LINK")][1][0].price, 20)
        assert.equal(orderBook[web3.utils.fromUtf8("LINK")][1][1].price, 5)
        assert.equal(orderBook[web3.utils.fromUtf8("LINK")][1][2].price, 10)
        
    })

})
1 Like
/*
    User must have ETH deposited such that deposited eth >=buy order val
    user must have enough tokens deposited such that token balance > sell order amount
    first order ([0]) in the BUY order book should have the highest price (order book should be ordered from highest to lowest)
*/

const Dex = artifacts.require("Dex")
const Link = artifacts.require("Link")
const truffleAssert = require('truffle-assertions')

contract("Dex", accounts => {
    
    it("should have enough ETH deposited to cover buy order", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        dex.deposit(100, web3.utils.fromUtf8("ETH"), {from: accounts[0]})
        //function createLimitOrder(address trader, Side side, bytes32 ticker, uint amount, uint price)
        truffleAssert.passes(
            dex.createLimitOrder(accounts[0], 0, web3.utils.fromUtf8("LINK"), 5, 20)
        )
        truffleAssert.reverts(
            dex.createLimitOrder(accounts[0], 0, web3.utils.fromUtf8("LINK"), 5, 200)
        )
    })
    it("should have enough Tokens deposited to cover Sell order", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        dex.deposit(100, web3.utils.fromUtf8("LINK"), {from: accounts[0]})
        truffleAssert.passes(
            dex.createLimitOrder(accounts[0], 1, web3.utils.fromUtf8("LINK"), 5, 20)
        )
        truffleAssert.reverts(
            dex.createLimitOrder(accounts[0], 1, web3.utils.fromUtf8("LINK"), 10, 200)
        )
    })
    it("should sort BUY order book from highest to lowest", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("LINK"), {from: accounts[0]});

        dex.createLimitOrder(accounts[0], 1, web3.utils.fromUtf8("LINK"), 1, 20)
        dex.createLimitOrder(accounts[0], 1, web3.utils.fromUtf8("LINK"), 1, 50)
        dex.createLimitOrder(accounts[0], 1, web3.utils.fromUtf8("LINK"), 1, 30)

        let orderbook = dex.getOrderBook(web3.utils.fromUtf8("LINK"),0) //0 = buy
        
        for(let i=0; i<orderbook.length-1; i++){
            assert(orderbook[i].price >= orderbook[i+1].price,"Prices not in correct order")
        }
    })
})
1 Like
const Dex = artifacts.require("Dex");
const Link = artifacts.require("Link");
const truffleAssert = require("truffle-assertions");

contract("Dex", accounts => {
    //deposit(uint256 amount, bytes32 ticker)

    let dex;
    let link;

    before(async function () {
        dex = await Dex.deployed();
        link = await Link.deployed();
    });

    it("user must have enough ETH deposited to afford making the buy order", async () => {
        await truffleAssert.reverts(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), accounts[0], 10)
        );
        await dex.DepositETH({ value: web3.utils.toWei('1', 'ether') }, accounts[0]);

        await truffleAssert.passes(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), accounts[0], 10)
        );

    })

    it("the token balance is not less than the sell order amount", async () => {
        await truffleAssert.reverts(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), accounts[0], 200)
        );
        await link.approve(dex.address, 500);
        await dex.deposit(300, web3.utils.fromUtf8("LINK"));
        await truffleAssert.passes(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), accounts[0], 250)
        );
    })

    it("buy order book should be ordered in descending manner", async () => {
        await dex.depositETH({ value: '5000' });
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 5, 100)
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 6, 200)
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 4, 220)
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 160)

        let orderbook = await dex.getOrderbook(web3.utils.fromUtf8("LINK"), 0);

        for (i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i].price >= orderbook[i + 1].price, "not right order in buy book")
        }
    })


    it("sell order book should be ordered in ascending manner", async () => {
        await link.approve(dex.address, 5000);
        await dex.deposit(5000, web3.utils.fromUtf8("LINK"));
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 5, 190)
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 6, 120)
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 4, 220)
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 160)

        let orderbook = await dex.getOrderbook(web3.utils.fromUtf8("LINK"), 0);

        for (i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i].price <= orderbook[i + 1].price, "not right order in buy book")
        }
    })
})
1 Like

Hey guys,

Are we supposed to build the function and the test file at the same time to run truffle test?

Or we just need to build the test file and not run truffle test yet?

Thanks!

file: dextest.js

const _ = require('lodash');
const Dex = artifacts.require("Dex")
const Link = artifacts.require("Link")
const truffleAssert = require('truffle-assertions');

const Side = {
    BUY: 0,
    SELL: 1,
};

const Tokens = {
    LINK: web3.utils.fromUtf8("LINK"),
}

contract("Dex", accounts => {
    describe("when a user whants make an buy/sell operation", async () => {
        it("should have a positive ETH balance before creating BUY limit order", async () => {
            const dex = await Dex.deployed();
            const link = await Link.deployed();
            await dex.addToken(Tokens.LINK, link.address,  {from: accounts[0]});

            await truffleAssert.reverts(
                dex.createLimitOrder(Side.BUY, Tokens.LINK, 100, 60)
            );
            dex.depositEth({ value: 200 })
            await truffleAssert.passes(
                dex.createLimitOrder(Side.BUY, Tokens.LINK, 100, 60)
            )
        });

        it("should have enough balance before selling the token", async () => {
            const dex = await Dex.deployed();
            const link = await Link.deployed();
            await dex.addToken(Tokens.LINK, link.address,  {from: accounts[0]});

            await truffleAssert.reverts(
                dex.createLimitOrder(Side.SELL, Tokens.LINK, 100, 100)
            )
            await link.approve(dex.address, 1000);
            await dex.deposit(100, Tokens.LINK);
            truffleAssert.passes(
                 await dex.createLimitOrder(Side.SELL, Tokens.LINK, 99, 51)
            )
        });

        it("The BUY order book should be sorted by highest to lowest ascending", async () => {
            const dex = await Dex.deployed();
            const link = await Link.deployed();
            await dex.addToken(Tokens.LINK, link.address,  {from: accounts[0]});
            await link.approve(dex.address, 1000);

            await _.reduce(
                [
                    {side: Side.BUY, token: Tokens.LINK, amount: 120, price: 40},
                    {side: Side.BUY, token: Tokens.LINK, amount: 129, price: 39},
                    {side: Side.BUY, token: Tokens.LINK, amount: 130, price: 30},
                    {side: Side.BUY, token: Tokens.LINK, amount: 140, price: 40},
                ], 
                async (_, order) => dex.createLimitOrder(order.side, order.token, order.amount, order.price), 
                Promise.resolve()
            );

            const orderbook = await dex.getOrderBook(Tokens.LINK, Side.BUY);

            const result = _.find(orderbook, (value, index, array) => index !== 0 && array[index - 1].price <= value.price);
            assert(!result);
        });

        it("The SELL order book should be sorted by lowest to highest ascending", async () => {
            const dex = await Dex.deployed();
            const link = await Link.deployed();
            await dex.addToken(Tokens.LINK, link.address,  {from: accounts[0]});
            await link.approve(dex.address, 1000);
            await dex.deposit(99, Tokens.LINK);
            await _.reduce(
                [
                    {side: Side.SELL, token: Tokens.LINK, amount: 12, price: 10},
                    {side: Side.SELL, token: Tokens.LINK, amount: 19, price: 19},
                    {side: Side.SELL, token: Tokens.LINK, amount: 13, price: 20},
                    {side: Side.SELL, token: Tokens.LINK, amount: 14, price: 10},
                ], 
                async (_, order) => dex.createLimitOrder(order.side, order.token, order.amount, order.price), 
                Promise.resolve()
            );

            const orderbook = await dex.getOrderBook(Tokens.LINK, Side.SELL);
            console.log('orderbook', orderbook);
            const result = _.find(orderbook, (value, index, array) => index !== 0 && array[index - 1].price >= value.price);
            assert(!result);
        });
    });

})

1 Like

In my case I did it, but partially so that I can see green in the tests :smiley:

1 Like

I have a couple of question regarding the dex example

1 - Why do we need an order Id? what is the use case? since storage in the blockchain has a cost why do not just discard it?
2 - Why do we store the buy/sell orders in the blockchain? I would use a database.

Here’s my assignment, tried to do the function but I got stuck on some parts. LOL

btw, I used my name as a Token for fun, I didn’t know that we have to pass it :sweat_smile:

const Dex = artifacts.require("Dex")
const Xyz = artifacts.require("Xyz")
const truffleAssert = require('truffle-assertions')


contract ("Dex", accounts => {

// Assignment Limit Order Tests
    // The user must have ETH deposited such that ETH deposited >= BUY order value
    it("should only allow BUY orders <= deposited ETH", async () =>{
        let dex = await Dex.deployed()
        let xyz = await Xyz.deployed()

        dex.depositETH({value: 100}) //ETH balance is 100

        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 10, 20) //requires 200 ETH
        )
        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 10, 5) //requires 50 ETH
        )
    })

    // The user must have enough deposited tokens such that token balance >= SELL order amount
    it("amount of token to SELL should be <= amount of same token in balances", async () =>{
        let dex = await Dex.deployed()
        let xyz = await Xyz.deployed()

        dex.addToken(web3.utils.fromUtf8("XYZ"), xyz.address, {from: accounts[0]})
        await xyz.approve(dex.address, 100);
        await dex.deposit(50, web3.utils.fromUtf8("XYZ")) //deposit 50 XYZ tokens
        
        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 10, 5) //selling 10 tokens
        )
        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 100, 5) //selling 100 tokens
        )
    })
    // The BUY order book should be ordered in price from highest to lowest starting with index 0
    it("The BUY order book should be ordered in price from highest to lowest starting with index 0", async () =>{
        let dex = await Dex.deployed()
        let xyz = await Xyz.deployed()
        
        await dex.depositETH({value: 1000})
    // create a BUY order book
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 1, 50)  // 50 ETH index 0
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 10, 20) // 200 ETH index 1 (should be 2)
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 10, 30) // 300 ETH index 2 (should be 1)
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 5, 10) // 50 ETH index 3
         
        let buyOrderBook = await dex.getOrderBook(web3.utils.fromUtf8("XYZ"), 0)
        assert(buyOrderBook.length > 0)  

        for(let i = 0; i < buyOrderBook.length - 1; i++){ 
            assert(buyOrderBook[i].price >= buyOrderBook[i + 1].price, "BUY Orders not Sorted")
        }
    })

//Additional tests
    // The SELL order book should be ordered in price from lowest to highest starting with index 0
    it("The SELL order book should be ordered in price from lowest to highest starting with index 0", async () =>{
        let dex = await Dex.deployed()
        let xyz = await Xyz.deployed()
        
        dex.addToken(web3.utils.fromUtf8("XYZ"), xyz.address, {from: accounts[0]})
        await xyz.approve(dex.address, 100);
        await dex.deposit(50, web3.utils.fromUtf8("XYZ"))
    // create a SELL order book
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 1, 50)  // 50 ETH index 0 (should be 3)
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 10, 20) // 200 ETH index 1 
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 10, 30) // 300 ETH index 2 
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 5, 10) // 50 ETH index 3 (should be 0)
     
        let sellOrderBook = await dex.getOrderBook(web3.utils.fromUtf8("XYZ"), 1)
        assert(sellOrderBook.length > 0)  

        for(let i = 0; i < sellOrderBook.length - 1; i++){ 
            assert(sellOrderBook[i].price <= sellOrderBook[i + 1].price, "SELL Orders not Sorted")
        }
    })

    // The lowest price in the SELL order book should be > highest price in the BUY order book
    it("The SELL order book should be ordered in price from lowest to highest starting with index 0", async () =>{
        let dex = await Dex.deployed()
        let xyz = await Xyz.deployed()

        await dex.depositETH({value: 1000})

        dex.addToken(web3.utils.fromUtf8("XYZ"), xyz.address, {from: accounts[0]})
        await xyz.approve(dex.address, 100);
        await dex.deposit(50, web3.utils.fromUtf8("XYZ"))

        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 1, 50)
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 1, 10, 20)
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 10, 20)
        await dex.createLimitOrder(web3.utils.fromUtf8("XYZ"), 0, 5, 10)

        let buyOrderBook = await dex.getOrderBook(web3.utils.fromUtf8("XYZ"), 0)

        let sellOrderBook = await dex.getOrderBook(web3.utils.fromUtf8("XYZ"), 1)

        assert(sellOrderBook[sellOrderBook.length-1] > buyOrderBook[0], "If prices match or buyprice > sellprice, trade should be made")

    })

also, I tried creating and adding other tokens, seems to work just fine! Thanks for the knowledge!

1 Like

Hi @danielmain

Why do we store the buy/sell orders in the blockchain? I would use a database.

The idea is to create a dapp, not a centralised exchange.

Why do we need an order Id? what is the use case? since storage in the blockchain has a cost why do not just discard it?

You can choose not to save the id and just order by price.

Cheers,
Dani