Assignment - Limit Order Test

hey @bargerinare u still facing issues. if so drop me a dm or explain your post here ill look into it for u

Sadly i had to check out Filips code for help : (

//The user must have ETH deopsited 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 ot highest starting at index 0


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

//The user must have ETH deopsited such that deposited eth >= buy order value
contract("Dex", accounts => { //Side side, bytes32 ticker, uint256 amount, uint256 price 
    it("TheThe user must have ETH deopsited such that deposited eth >= buy order value user must have more ETH than the buy order value", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await truffleAssert.reverts(
               dex.createLimitOrder(0,web3.utils.fromUtf8("LINK"),20,1))
        })
          dex.deposit({value:20})
          await truffleAssert.passes(
          dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"),20,1))
      })
     
//The user must have enough tokens deposited such that token balance >= sell order amount
    it("TheThe user must have ETH deopsited such that deposited eth >= buy order value user must have more ETH than the buy order value", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await truffleAssert.revert( 
              dex.createLimitOrder(1,web3.utils.fromUtf8("LINK"),20,1)
        )
        })
        await link.approve(dex.address,500);
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address)
        await dex.deposit({value:20});
        await truffleAssert.passes(
            dex.createLimitOrder(1,web3.utils.fromUtf8("LINK"),20,1)
            
        )
        
    

//The BUY order book should be ordered on price from highest to lowest starting at index 0
    it("The user must have more ETH than the buy order value", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await link.approve(dex.address,500);
        await dex.deposit({value: 3000});
        await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 3, 300)
        await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 3, 100)
        await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 3, 200)
      
             let viewbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 0);
             for(let i=0;i < viewbook.length -1;i++){
                assert(viewbook[i].price >= viewbook[i+1].price, "The price order for 'BUY' is wrong") //-1 means the fist instance in the array, +1 is the next number inline. position 1 must be larger than position 2
             }
        }) 
  //The SELL order book should be ordered on price from lowest to highest starting at index 0
        it("The user must have more ETH than the buy order value", async () => {
            let dex = await Dex.deployed()
            let link = await Link.deployed()
            await link.approve(dex.address,500);
            await dex.deposit({value: 3000});
            await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 3, 300)
            await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 3, 100)
            await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 3, 200)

            let viewbook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 0);
            for(let i=0;i < viewbook.length -1;i++){
               assert(viewbook[i].price <= viewbook[i+1].price, "The price order for 'SELL' is wrong")
    
            }

        })
    



hi there, i can’t seem to get my code to pass as one. Separately both truffleAssert.reverts and truffleAssert.passes, pass, but when executed at the same time they fail.

contract("Dex", accounts => {
    //The user must have ETH deposited such that deposited eth >= buy order value
    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()
       
        truffleAssert.reverts(
           dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)
        )
        
        await dex.depositEth({value: 10})
           truffleAssert.passes(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)
        )
    })

error message

1) Contract: Dex
       should throw an error if ETH balance is too low when creating BUY limit order:
     Uncaught AssertionError: Did not fail
      at fails (node_modules/truffle-assertions/index.js:161:9)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)



UnhandledRejections detected
Promise {
  <rejected> AssertionError: Did not fail
      at fails (node_modules/truffle-assertions/index.js:161:9)
      at processTicksAndRejections (node:internal/process/task_queues:96:5) {
    showDiff: false,
    uncaught: true
  }
} AssertionError: Did not fail
    at fails (node_modules/truffle-assertions/index.js:161:9)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  showDiff: false,
  uncaught: true
}

Is there a break type function like in javascript
that i can use to stop the code running after it passes the truffleAssert.reverts?

I hope my question makes sense.

you might need to use await at the start of each function call of the contract instance.

Carlos Z

hi Carlos,

Unfortunately I’ve already tried this. The error message I get from this is as follows:

1) Contract: Dex
       should throw an error if ETH balance is too low when creating BUY limit order:
     Uncaught AssertionError: Did not fail
      at fails (node_modules/truffle-assertions/index.js:161:9)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)

When i remove the await keyword from the dex.createLimitOrder the test then passes.

 Contract: Dex
    ✔ should throw an error if ETH balance is too low when creating BUY limit order (3080ms)

  Contract: Dex
    - should only be possible for the owner to add tokens
    - should handle deposits correctly
    - should handle faulty withdrawls correctly
    - should handle correct withdrawls correctly


  1 passing (4s)
  4 pending

So far, I have tried the following:

  • swapped the positioning of reverts and passes incase the code reverting somehow affects the rest of the tests by being tested first

  • I’ve tested each test individually(all passed) then I tested 2 at a time then 3 at a time and then when adding the last test and it failed.

  • I tested them in reverse order and it seems like the issue is coming from the first test.

  • I’ve played around with adding and removing await on certain functions and in some cases the test passed, especially when removing it from the truffle assert function but again, getting the entire set of tests to pass together isn’t happening.

Let me know if you have any other ideas, I am currently running v0.8.0 of solidity.

1 Like

hey @unwise_guy you wull need the await in the tests usually. can u share a github repo for me to check and look at i will get to the bottom of your errors

1 Like

Sorry for the wait, here is a link to my repo

https://github.com/oscaroneim/Dex2

1 Like

hey @unwise_guy so im cloning your code now. will get back to you shortly

@unwise guy. i notice you have a few files missing from your github repo. can you upload all files from your project to your github repo

1 Like

Sorry for the late reply, i don’t seem to be getting any notifications when you reply. I have uploaded the rest.
Please let me know what you find.

1 Like

ok @unwise_guy do i fixed all of your tests and there were a few things. firstly the main reason they were failing was becaus eyou had no implemented the createLimitOrder function correctly. your function is as follows

function bubbleSort()public pure returns(Order[] memory){

          Order[] memory orders;

          uint length = orders.length;

          for(uint i=0; i<orders.length; i++){
          for(uint j=0; j<orders.length; j++){
              if(side == Side.BUY){
               uint currentValue = orders[j];
               orders[j] = orders[j+1];
               orders[j+1] = currentValue;
              }
             }
          }
         return orders;
              
     }

    function createLimitOrder(Side side, bytes32 ticker, uint price, uint amount)public {
          if(side == Side.BUY){
            require(balances[msg.sender]["ETH"] >= amount.mul(price)); //this makes sure that there is enough ETH in the BUY side account before executing 
          }
          else if(side == Side.SELL){
            require(balances[msg.sender][ticker] >= amount.mul(price)); ////this makes sure that there is enough ETH in the SELL side account before executing
    }
    
     Order[] storage orders = orderBook[ticker][uint(side)]; //created an array to push the limit orders into.

     orders.push(
      Order(nextOrderId, msg.sender, side, ticker, amount, price) //nextOrderId was created to fill the id criteria for the Order struct. This pushes the orders into the array but not in any order.
     );

i think its good that you tried to segregate the bibble sort logic into your own helper function. it shows that your trying to think for yourself by chaning it up from the videos source code. however this is what was causing a lot of your problems. firstly your contract wouldnt compile because of errors in the bubbleSort helper function. i changed your contract. so the new version with my edits are give below

pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;

import "./wallet.sol";

contract Dex is Wallet {
using SafeMath for uint256;
    
    enum Side {
        Buy, //0
        Sell //1
    }

    //order.side = Side.Buy
  

    struct Order {
        uint id;
        address trader;
        Side side;
        bytes32 ticker;
        uint amount;
        uint price; //limit orders
        uint filled;
    }

    uint public nextOrderID = 0;

    mapping(bytes32 => mapping(uint => Order[])) orderBook;

    function getTokenList() public view returns(uint256){
        return tokenList.length;
    }

    function getOrderBook(bytes32 ticker, Side side) view public returns(Order[] memory){
        return orderBook[ticker][uint(side)];
    }

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

        if(side == Side.Buy){
            require(balances[msg.sender]["ETH"] >= amount.mul(price));
        }
        else if(side == Side.Sell){
            require(balances[msg.sender][ticker] >= amount);
        }
        Order[] storage orders = orderBook[ticker][uint(side)];
        orders.push( Order(nextOrderID, msg.sender, side, ticker, amount, price, 0) );

        //Bubble Loop Algorithm to sort Buy and Sell orders
        uint i = orders.length > 0 ? orders.length -1 : 0;

        if(side == Side.Buy){
           while(i > 0){
               if(orders[i-1].price > orders[i].price){
                   break;
               }
               Order memory orderToMove = orders[i-1];
               orders[i - 1] = orders[i];
               orders[i] = orderToMove;
               i--;
           }
        }

        else if(side == Side.Sell){
            while(i > 0){
               if(orders[i - 1].price < orders[i].price){
                   break;
               }
               Order memory orderToMove = orders[i-1];
               orders[i - 1] = orders[i];
               orders[i] = orderToMove;
               i--;
           }
        }
        nextOrderID++;
}


}

the next error was an incorrect import of the ERC20 token contrat in both of your token contracts. in both of these file splease change

import "../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol";

to

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

this was your second mistake. for some reason adding the full path to the openzeppelin library was causing issues with your tests. So the last issue was the tests themselves. there were too many bad issues here. but i decided to completely reqrite your tests because i was actually having some issues debugg yours.

the main thing to think about when your debugging tests is testing line by line. if your test is fialing. comment everything out except for the first line. run the tets and is it passes, comment out the next line and run again. if you keep doing this eventually youll get to the line that fails and from here its much easier to debug because you know where the source of the error is. your fixed tests are given below.

const Dex = artifacts.require("Dex");
const Link = artifacts.require("Link");
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()

        await truffleAssert.reverts( //buy will not be created due to no ETH
            dex.createLimitOrder(0, web3.utils.fromUtf8("Link"), 10, 1)
        )
        await dex.depositEth({value: 10}) //Eth deposited so will be created
        await truffleAssert.passes( 
            dex.createLimitOrder(0, web3.utils.fromUtf8("Link"), 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 link = await Link.deployed()
        await dex.addToken(web3.utils.fromUtf8("Link"), link.address, {from: accounts[0]})
        await truffleAssert.reverts( //reverts because no Link approved or deposited
            dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 10, 1)
        )
        await link.approve(dex.address, 500);
        await dex.deposit(100, web3.utils.fromUtf8("Link"));
        await truffleAssert.passes( //passes because deposit has been approved and settled
            dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 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 link = await Link.deployed()
        await link.approve(dex.address, 500);
        await dex.depositEth({value: 1000});
        
        dex.createLimitOrder(0, web3.utils.fromUtf8("Link"), 1, 10)
        dex.createLimitOrder(0, web3.utils.fromUtf8("Link"), 1, 30)
        dex.createLimitOrder(0, web3.utils.fromUtf8("Link"), 1, 25)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("Link"), 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 link = await Link.deployed()
        await link.approve(dex.address, 500);
        // await dex.depositEth({value: 1000});
        await dex.deposit(100, web3.utils.fromUtf8("Link"));
        dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 1, 10)
        dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 1, 30)
        dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 1, 25)

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

if yu have any frther questions. please let me know

Evan

2 Likes

Hi Evan,

Thanks for looking into to all this.

I have a question about the SELL order test. For some reason the code fails at the assert function that checks that there are orders in the orderbook array. The code works fine for the BUY side test.

// 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 link = await Link.deployed()
        await link.approve(dex.address, 500);
        await dex.depositEth({value: 1000});

        dex.createLimitOrder(1, web3.utils.fromUtf8("ETH"), 1, 10)
        dex.createLimitOrder(1, web3.utils.fromUtf8("ETH"), 1, 30)
        dex.createLimitOrder(1, web3.utils.fromUtf8("ETH"), 1, 25)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("ETH"), 1);

        assert(orderbook.length > 0);

        for(let i = 0; i < orderbook.length - 1; i++){
         assert (orderbook[i].price <= orderbook[i+1].price, "Sell order book has not bee sorted")
        }
    }
    )
}
);
3 passing (15s)
  4 pending
  1 failing

  1) Contract: Dex
       (Sell Order)should be in order from highest to lowest:
     AssertionError: Unspecified AssertionError
      at Context.<anonymous> (test/dexTest.js:77:9)
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)

If you comment out the assert, the code passes

//assert(orderbook.length > 0);
Contract: Dex
    ✔ user's deposited ETH is >= buy order (7353ms)
    ✔ user's token balance is >= sell order amount (4234ms)
    ✔ (Buy Order)should be in order from highest to lowest (2226ms)
    ✔ (Sell Order)should be in order from highest to lowest (2185ms)

  Contract: Dex
    - should only be possible for the owner to add tokens
    - should handle deposits correctly
    - should handle faulty withdrawls correctly
    - should handle correct withdrawls correctly


  4 passing (17s)
  4 pending

Let me know your thoughts.

Cheers,
Oscar

1 Like

hmm this is stranfe. can you console.log() the orderbook. it must be empty and this would make sense as to why your test is passing

1 Like

I’m not sure what i’m doing wrong but i can’t seem to get the console.log to show any information. I’ve placed it underneath the orderbook variable.

it("(Sell Order)should be in order from highest to lowest", async () => {

        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await link.approve(dex.address, 500);
        //await dex.depositEth({value: 1000});
        await dex.deposit(100, web3.utils.fromUtf8("Link"));

        dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 1, 10)
        dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 1, 30)
        dex.createLimitOrder(1, web3.utils.fromUtf8("Link"), 1, 25)

        let orderbook = await dex.getOrderBook(web3.utils.fromUtf8("Link"), 1);
        console.log(orderbook);

        assert(orderbook.length > 0)

        for(let i = 0; i < orderbook.length - 1; i++){

            assert (orderbook[i].price <= orderbook[i+1].price, "Sell order book has not bee sorted")

        }

    })

This is the current error message im receiving


  Contract: Dex
    1) (Sell Order)should be in order from highest to lowest

    Events emitted during test:
    ---------------------------

    Ether.Approval(
      owner: <indexed> 0x5738aCDD50664b3A98153E0B8138E4EC90b99510 (type: address),
      spender: <indexed> 0x9E1314298a3Ee17A27d51bb0C59fc3dc411Ed745 (type: address),
      value: 500 (type: uint256)
    )


    ---------------------------

  Contract: Dex
    - should only be possible for the owner to add tokens
    - should handle deposits correctly
    - should handle faulty withdrawls correctly
    - should handle correct withdrawls correctly


  0 passing (2s)
  4 pending
  1 failing

  1) Contract: Dex
       (Sell Order)should be in order from highest to lowest:
     Error: Returned error: VM Exception while processing transaction: revert
      at Context.<anonymous> (test/dexTest.js:74:19)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)

Line 74 is the deopsit function call:

        await dex.deposit(100, web3.utils.fromUtf8("LINK"));

I’ve tested both deposit.eth and deposit, both calls revert.

Link to my github:

https://github.com/oscaroneim/Dex2

Sorry for the ball ache.

Hi Evan, were you able to find out the issue?

regards,
Oscar

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

// Test should be written before the actual code is written

// here are some conditions forcreating a limit order
// 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 first order ([0]) in the buy order book should have the higest price
// the first order ([0]) in the sell order book should have the lowest price
// sell order book should not mix different tokens
// buy order book should not mix different tokens

contract("Dex", accounts => {
    let buy = 0;
    let sell = 1;

    it("should only allow the amount of eth that is greater than or equal to the buy order value", async() => {
        let dex=await Dex.deployed();
        
        await truffleAssert.reverts (
            dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 10, 1)
        );
        
        await dex.depositEth({value: 10});

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

    it("should require the token amount deposited be greater than or equal to the sell order value", async() => {
        let dex=await Dex.deployed();
        let link = await Link.deployed();
        
        await truffleAssert.reverts (
            dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 10, 1)
        );
        
        await link.approve(dex.address, 500);
        await dex.deposit(10, web3.utils.fromUtf8("LINK"));

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

    it("buy orderbook should be sorted from the highest to lowest price", async() => {
        let dex=await Dex.deployed();
        let link = await Link.deployed();
        
        await dex.depositEth({value: 50});

        await link.approve(dex.address, 500);
        await dex.deposit(10, web3.utils.fromUtf8("LINK"));

        await dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 6, 3);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 8, 5);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 4, 2);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 10, 4);

        let buys = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), buy);
        for (let index=0; i < buys.length - 1; index++) {
            assert(orderBook[index].price >= orderBook[index+1].price);
        }
    });

    it("sell orderbook should be sorted from the lowest to highest price", async() => {
        let dex=await Dex.deployed();
        let link = await Link.deployed();
        
        await dex.depositEth({value: 50});

        await link.approve(dex.address, 500);
        await dex.deposit(50, web3.utils.fromUtf8("LINK"));

        await dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 6, 3);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 8, 5);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 4, 2);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 10, 4);

        let buys = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), buy);
        for (let index=0; i < buys.length - 1; index++) {
            assert(orderBook[index].price <= orderBook[index+1].price);
        }
    });

    it("buy orderbook should contain only one type of token", async() => {
        let dex=await Dex.deployed();

        await dex.depositEth({value: 50});

        await dex.createLimitOrder(buy, web3.utils.fromUtf8("AAVE"), 2, 3);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 2, 5);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("AAVE"), 2, 2);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("AAVE"), 2, 4);
        await dex.createLimitOrder(buy, web3.utils.fromUtf8("LINK"), 2, 5);

        let buys = await dex.getOrderBook(web3.utils.fromUtf8("AAVE"), buy);
        for (let index=0; i < buys.length - 1; index++) {
            assert(orderBook[index].ticker == web3.utils.fromUtf8("AAVE"));
        }
        buys = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), buy);
        for (let index=0; i < buys.length - 1; index++) {
            assert(orderBook[index].ticker == web3.utils.fromUtf8("LINK"));
        }
    });
    it("sell orderbook should contain only one type of token", async() => {
        let dex=await Dex.deployed();
        let link = await Link.deployed();
        let aave = await Aave.deployed();

        await link.approve(dex.address, 500);
        await aave.approve(dex.address, 500);
        await dex.deposit(50, web3.utils.fromUtf8("LINK"));
        await dex.deposit(50, web3.utils.fromUtf8("AAVE"));

        await dex.createLimitOrder(sell, web3.utils.fromUtf8("AAVE"), 2, 3);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 2, 5);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("AAVE"), 2, 2);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("AAVE"), 2, 4);
        await dex.createLimitOrder(sell, web3.utils.fromUtf8("LINK"), 2, 5);

        let buys = await dex.getOrderBook(web3.utils.fromUtf8("AAVE"), sell);
        for (let index=0; i < buys.length - 1; index++) {
            assert(orderBook[index].ticker == web3.utils.fromUtf8("AAVE"));
        }
        buys = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), sell);
        for (let index=0; i < buys.length - 1; index++) {
            assert(orderBook[index].ticker == web3.utils.fromUtf8("LINK"));
        }
    });
});
const Dex = artifacts.require("Dex");
const Link = artifacts.require("Link");
const truffleAssert = require("truffle-assertions");

//buy = 0
//sell = 1

contract("Dex", accounts => {

    it("should have more ETH deposited than the buy order value", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await dex.addToken(web3.utils.sha3("LINK"), link.address, {from: accounts[0]})

        await truffleAssert.reverts(
            //function createLimitOrder(side, ticker, amount, price)
            dex.createLimitOrder(0, web3.utils.sha3("LINK"), 15, 1))

        await dex.depositEth({value: 25})       

        await truffleAssert.passes(
            //function createLimitOrder(side, ticker, amount, price)
            dex.createLimitOrder(0, web3.utils.sha3("LINK"), 15, 1)) 
    })

    it("Token deposit should be greater than sell order amount", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await dex.addToken(web3.utils.sha3("LINK"), link.address, {from: accounts[0]})

        await truffleAssert.reverts(
            //function createLimitOrder(side, ticker, amount, price)
            dex.createLimitOrder(1, web3.utils.sha3("LINK"), 15, 1))

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

        await dex.deposit(100, web3.utils.sha3("LINK"));

        await truffleAssert.passes(
            //function createLimitOrder(side, ticker, amount, price)
            await dex.createLimitOrder(1, web3.utils.sha3("LINK"), 15, 1))
    })

    it("Buy order book should be ordered highest to lowest", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await link.approve(dex.address, 500);
        await dex.depositEth({value: 3000});
        await dex.createLimitOrder(0, web3.utils.sha3("LINK"), 15, 1);
        await dex.createLimitOrder(0, web3.utils.sha3("LINK"), 16, 3);
        await dex.createLimitOrder(0, web3.utils.sha3("LINK"), 17, 7);

        let orderbook = await dex.getOrderBook(web3.utils.sha3("LINK"), 0);
        assert(orderbook.length > 0);
        console.log(orderbook);
        for (let i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i].price >= orderbook[i + 1].price, "buy book order incorrect")
        } 
    })

    it("Sell order book should be ordered lowest to highest", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        await link.approve(dex.address, 500);
        await dex.createLimitOrder(1, web3.utils.sha3("LINK"), 15, 1);
        await dex.createLimitOrder(1, web3.utils.sha3("LINK"), 16, 3);
        await dex.createLimitOrder(1, web3.utils.sha3("LINK"), 17, 7);

        let orderbook = await dex.getOrderBook(web3.utils.sha3("LINK"), 1);
        assert(orderbook.length > 0);
        for (let i = 0; i < orderbook.length - 1; i++) {
            assert(orderbook[i].price <= orderbook[i + 1].price, "sell book order incorrect")
        }      
    })

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

contract("Dex", accounts => {

//The user must have ETH deposited such as deposited ETH >= buy order value

    it("should ensure that user has enough ETH deposited such as deposited ETH >= buy order value", async() => {
        let dex = await DEX.deployed()
        let link = await Link.deployed()
        //await link.approve (dex.address, 1000);
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from : accounts[0]});
        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 10, 4677,0,{value:web3.utils.toWei('1','ether')}) // price in GWei
        )

        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 10, 499999999,0, {value:web3.utils.toWei('1','ether')}) // price in GWei
        )

    })
//The user must have enough tokens deposited such that the token balance >= sell order amount
    it("should ensure that user has enough tokens deposited such that the token balance >= sell order amount", async() => {
        let dex = await DEX.deployed()
        let link = await Link.deployed()
        //console.log(dex.address);
        await link.approve (dex.address, 1000);
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from : accounts[0]});
        //let balance = await dex.balances(accounts[0],web3.utils.fromUtf8("LINK"));
        await dex.deposit(500, web3.utils.fromUtf8("LINK"));
        await truffleAssert.passes(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 300, 20,1) // tries to sell 300 out of a balance of 500
        )

        await truffleAssert.reverts(
            dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 600, 20,1) // tries to sell 600 out of a balance of 500
        )
    })

//The BUY order book should be ordered on price from highest to lowest starting at index 0

it("should ensure that the BUY order book is ordered on price from highest to lowest starting at index 0", async() => {
    let dex = await DEX.deployed()
    await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 200, 20,0,{value:web3.utils.toWei('1','ether')});  // creates 3 limit orders with varying prices
    await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 300, 20,0,{value:web3.utils.toWei('1','ether')});
    await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 100, 20,0,{value:web3.utils.toWei('1','ether')});
    let OrderBook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"),0);
    let OrderBookLength= await OrderBook.length;
    var x = 0;
    for(var j = 0; j < OrderBookLength-1; j++) {
        if (OrderBook[j].price<OrderBook[j+1].price){
            x = 1;
            break;
        }
    }
    assert.equal(x,0,"Prices in BUY order book not ordered from highest to lowest");

})

//The SELL order book should be ordered on price from lowest to highest starting at index 0

it("should ensure that the SELL order book is ordered on price from lowest to highest starting at index 0", async() => {
    let dex = await DEX.deployed()
    let OrderBook = await dex.getOrderBook(web3.utils.fromUtf8("LINK"),1);
    let OrderBookLength= await OrderBook.length;
    var x = 0;
    for(var j = 1; j < OrderBookLength-1; j++) {
        if (OrderBook[j].price<OrderBook[j-1].price){
            x = 1;
            break;
        }
        assert.equal(x,0,"Prices in SELL order book not ordered from lowest to highest");
    }
    

})

//Shouldn't be possible to create a limit order for a non existing token
it("Shouldn't be possible to create a BUY limit order for a non existing token", async() => {
let dex = await DEX.deployed()
await truffleAssert.reverts(dex.createLimitOrder(web3.utils.fromUtf8("NONEXIST"), 10, 20,0,{value:web3.utils.toWei('1','ether')}))

})

})

my function createLimitOrder :

modifier balanceChecked (bytes32 ticker, uint amount, uint price, Side side) {
        if (side == Side.BUY) { // Buy order
            require(msg.value >= amount*price*1000000000, "ether balance not sufficient");
        }
        else { // Sell order
            require(balances[msg.sender][ticker] >= amount, "Your balance is too low to sell that amount");
        }
         _;
    }

function createLimitOrder(bytes32 ticker, uint amount, uint price, Side side)  payable public balanceChecked (ticker, amount, price, side) tokenExist(ticker) {

It appears as my solution is very different in many ways. Any problems with it ?

1 Like

DEX TEST:

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

contract('Dex', accounts => {
  let dex, link;
  const LINK = web3.utils.fromUtf8('LINK');
  const BUY = 0;
  const SELL= 1;

it("The deposited crypto must be more than buy order", async() =>{
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await truffleAssert.reverts      
            dex.limitOrder(true, web3.utils.fromUtf8("LINK"), 10, 1, {from: accounts[0]})
        await dex.deposit({value: 20, from:accounts[0]})    
        await truffleAssert.passes(
limitOrder(bool buyOrder, bytes32 ticker, uint amount, uint price)
            dex.limitOrder(true, web3.utils.fromUtf8("LINK"), 10, 1, {from: accounts[0]})
        )
    })

 it("balance must be greater than or equal to sell order", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()
        await truffleAssert.reverts(
            dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 20, 1)     
        )
        await link.approve(dex.address, 1000)
        await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
        await dex.deposit(20, web3.utils.fromUtf8("LINK")) 
        await truffleAssert.passes(
            dex.limitOrder(1, web3.utils.fromUtf8("LINK"), 10, 1)     
        )
    })