Project - Building a DEX

My solution for the bubble sort program:

dex.sol

uint n = orders.length;
if(_side == Side.BUY){
  for(uint i=n-1;i>0;i--){ 
    if(orders[i].price > orders[i-1].price){
      Order memory tmp = orders[i];
      orders[i] = orders[i-1];
      orders[i-1] = tmp;
    }else{
      break;
    }
  }
}else if(_side == Side.SELL){
  for(uint i=n-1;i>0;i--){
    if(orders[i].price < orders[i-1].price){
      Order memory tmp = orders[i];
      orders[i] = orders[i-1];
      orders[i-1] = tmp;
    }else{
      break;
    }
  }
}
    
1 Like

Initially when I got the balances from the wallet, the output was the same as in the tutorials:
<BN: 64>
Recently when I wanted to continue the project, I notices that web3 big numbers were returned with a different JSON format, which is:

BN {
  negative: 0,
  words: [ 100, <1 empty item> ],
  length: 1,
  red: null
}

To get the BN representation I need to call the toJSON() method, which in the above instance returns 64 as expected. Is there something wrong in the implementation or was there a change in the library?

Thanks

Ok I think Iā€™m finally understanding the overall structure.

IMG_1116

3 Likes

Hey @bigbill

The error you get is related a a require statement in your contract that fails.
Check for the condition that is not satisfied :slight_smile:

Cheers,
Dani

Hey @karips

If I remember correctly I get <BN: 64> when I interact via truffle, and I get the BN object when I interact via web3.

Nothing to do there, just convert to Json and parseInt

Cheers,
Dani

1 Like

In video 4 of this section (ā€œbetter migrationā€) we move some instructions into the migration file so that we donā€™t have to run them in the terminal. In those instructions we create an allowance of 500, and then we deposit 100. This should leave a remaining allowance of 400, but instead the allowance is 0 after we run the migration. Is this right? Why does this not make it out of the migration, whereas some other things do (e.g. the wallet balance)?

1 Like

Hi @RichJamo

This should leave a remaining allowance of 400, but instead the allowance is 0 after we run the migration. Is this right?

Actually this is something you can verify yourself by checking the value and printing it to the console.
The remaining allowance is 400.

Screenshot 2021-04-20 at 08.34.14

  const allowance = await link.allowance(accounts[0], wallet.address)
  console.log(`The remaining allowance is ${Number(allowance)}`)

Cheers,
Dani

1 Like

Hey guys!

Iā€™m having a problem figuring out what the issue is with my code, it might be really obvious but iā€™m struggling to find it haha.

Blockquote
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;

contract Dex is Wallet {

enum Side {
    BUY,
    SELL
}

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

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

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

}

function createLimitOrder() {


}

}

the line iā€™ve starred is the one iā€™m struggling with, the error iā€™m getting is "Expected identifier but got ā€˜;ā€™ ".

Cheers

I think I have fixed but let me know if this is the wrong thing to do.

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

adding public seemed to make it work for me, i guess its an identifier but iā€™m not sure it is the correct one to use.

Cheers

Without watching any hint videos
Took me almost a day! Debugging is ultra hardā€¦

dex.sol

function createMarketOrder(Side _side, bytes32 _ticker, uint _amount) public{
  Order[] storage orders = orderBook[_ticker][_side==Side.BUY ? 1 : 0];

  uint totalFilled = 0;
  
  if(_side == Side.BUY){
    require(balances[msg.sender]["ETH"] > 0, "insufficient balance");
  }else{
    require(balances[msg.sender][_ticker] >= _amount, "insufficient balance");
  }

  for(uint i=0; i < orders.length && totalFilled < _amount; i++){
    //How much we can fill from order[i]
    if(totalFilled + orders[i].amount >= _amount){
      orders[i].filled = _amount - totalFilled;
    }else{
      orders[i].filled = orders[i].amount;
    }

    //Update totalFilled;
    totalFilled += orders[i].filled;
    orders[i].amount -= orders[i].filled;

    //Execute the trade & shift balances between buyer/seller
    if(_side == Side.BUY){
      //Verify that the buyer has enough ETH to cover the purchase (require)
      require(balances[msg.sender]["ETH"] >= orders[i].filled*orders[i].price, "insufficient balance");
      balances[msg.sender]["ETH"] -= orders[i].filled*orders[i].price;
      balances[msg.sender][_ticker] += orders[i].filled;
      balances[orders[i].trader]["ETH"] += orders[i].filled*orders[i].price;
      balances[orders[i].trader][_ticker] -= orders[i].filled;
    }else{
      //Verify that the seller has enough _ticker to cover the purchase (require)
      require(balances[msg.sender][_ticker] >= orders[i].filled, "insufficient balance");
      balances[msg.sender][_ticker] -= orders[i].filled;
      balances[msg.sender]["ETH"] += orders[i].filled*orders[i].price;
      balances[orders[i].trader][_ticker] += orders[i].filled;
      balances[orders[i].trader]["ETH"] -= orders[i].filled*orders[i].price;
    }
  }

  if(orders.length != 0){
    //Loop through the orderbook and remove 100% filled orders
    uint numOfFilledOrders = 0;
    for(uint i=0; i < orders.length && orders[i].amount == 0;i++){
      numOfFilledOrders++;
    }
    for(uint i=0; numOfFilledOrders!=0 && i< orders.length - numOfFilledOrders; i++){
      orders[i] = orders[i+numOfFilledOrders];
    }
    for(uint i=1; i <= numOfFilledOrders; i++){
      orders.pop();
    }
  }
}

Note: I decided to decrease orders[i].amount as it gets filled. This has to be commented out from the test code.

assert.equal(orderbook[0].amount, 5);
2 Likes

Hey @jakegoode95

You have to specify the mapping name.

mapping (address => uint) public balances;

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

You are declaring the visibility but not the name.

Cheers,
Dani

1 Like

Hi @dan-i

Thanks so much for the help earlier, I figured most of it out and then saw in the following video that he had made errors that I was fixing anyway.

I have a new issue when trying to run the tests iā€™m getting the below

Screenshot 2021-04-20 at 17.41.09

Iā€™m not failing but iā€™m not passing haha!

Do you know how to fix this?

https://github.com/jakegoode95/DEX

Thanks in advance!

Hey @jakegoode95

I cannot open your url, is the repository set to ā€˜privateā€™?
Please double check that and I will take a look!

Cheers,
Dani

Sorry! @dan-i

Should be public now!

Thanks

There are no tests in your test folder :smiley:

image

Oh i see!

I created a seperate Test folder, rather than used the one that is generated.

All working now, thanks for the help @dan-i :slight_smile:

1 Like

You are very welcome!

Hey @dan-i

Sorry for spamming you with soo many questions, truffle has been hard to get my head around!

I have an issue with my tests, iā€™m able to pass 2 but not all 4, iā€™m not sure what iā€™m missing?

Screenshot 2021-04-22 at 21.54.07

https://github.com/jakegoode95/DEX/blob/master/test/dextest.js

Thanks!

1 Like

You could be missing the revert msg, the reverts function needs a message as an argument.

Example:

    await truffleAssert.reverts(
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1),
        "Should be the same revert message has your require"
    );

Advice: try to add a revert message in your require statements, that way you will have a clue on why a function is being revert or failing.

Carlos Z

1 Like

Hi @jakegoode95

I took a look at your code, am looking at the wrong function or you are not sending the right parameter to createLimitOrder?

function createLimitOrder(Side side,uint amount,uint price)
dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)

Check that out,
Dani

1 Like