Project - Building a DEX

https://github.com/Lane689/Dex-project.git

Hey @Lane11

Please upload the files inside the right folder, I cannot deploy with truffle if the files are all mixed :slight_smile:

https://github.com/Lane689/Dex-project.git

1 Like

Hey coders,
I have just completed Etherenum Smart Contract course here. I want to build a Crypto wallet app in flutter where users can deposit their any coin or token and withdraw. I want to do this for my Country wehre people struggle to buy crypto in an easy way.

Features :slight_smile:

  1. Any coin and token including Bitcoin, XRP, ETH, ERC token and BEP tokens
  2. deposit and withdraw
  3. other standard features as luno or safemoon wallet app.

Please help me which course should I take to learn simple wallet app building or any simple wallet app template to learn the structure. Any recommendations would be highly appreciated.

Waiting codersā€¦

1 Like

For my last test on the sell limit order, which is obviously similar to the buy limit order, Iā€™m running into this ERROR : VM Exception while processing transaction: out of gas

Iā€™m not sure what going on here? My buy order works, but my sell order fails.

This is the full text of the error:

  1. Contract: Dex
    Sell order book must be ordered from low to high startin at index[0]:
    Error: Returned error: VM Exception while processing transaction: out of gas
    at Context. (test/Dex_test.js:79:15)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)

And here is my code for my buy and sell tests :

it("Buy order book must be ordered from high to low startin at index[0]", async () => {
let dex = await Dex.deployed();
let link = await Link.deployed();

await dex.depositETH({ value: 3000 });
await link.approve(dex.address, 700);

await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 300, 1);
await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 100, 1);
await dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 200, 1);

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

assert(orderBook.length > 0, "Orderbook Empty");

for (let count = 0; count < orderBook.length - 1; count++) {
  assert(
    orderBook[count].price > orderBook[count + 1].price,
    "NOT IN RIGHT ORDER!"
  );
}

});

it(ā€œSell order book must be ordered from low to high startin at index[0]ā€, async () => {
let dex = await Dex.deployed();
let link = await Link.deployed();

await dex.addEthToken();
await dex.addToken(web3.utils.fromUtf8("LINK"), Link.address, {
  from: accounts[0],
});

await dex.depositETH({ value: 300000 });
await link.approve(dex.address, 700);
await dex.deposit(web3.utils.fromUtf8("LINK"), 700);

await dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 200, 1);
await dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 100, 1);
await dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 300, 1);

let orderBook = await dex.getOrderbook(web3.utils.fromUtf8("LINK"), 1);
console.log(orderBook);

// assert(orderBook.length > 0);

for (let count = 0; count < orderBook.length - 1; count++) {
  assert(
    orderBook[count].price < orderBook[count + 1].price,
    "NOT IN RIGHT ORDER!"
  );
}

});






and here is the createLimitOrder function :





function createLimitOrder(side orderSide, bytes32 _ticker, uint _price, uint _amount) public {

    if (orderSide == side.BUY) {
    require(balances[msg.sender]["ETH"] >= _amount.mul(_price), "ETH Balance too low");
    }
    else if (orderSide == side.SELL) {   
    require(balances[msg.sender][_ticker] >= _amount.mul(_price), 
    " Token Balance too low");
    }

    Order[] storage orders =  Orderbook[_ticker][uint(orderSide)];

    orders.push( Order(nextOrderId,msg.sender,orderSide,_ticker,_amount,_price));
 

    uint i = orders.length > 0 ? orders.length-1 : 0; 

    if (orderSide == side.BUY) {

    while (i>0) {

    if (orders[i].price > orders[i-1].price) {
        Order memory  orderToMove = orders[i];
        orders[i] = orders[i-1];
        orders[i-1] = orderToMove;
    }
    i--;        
}

    }

if (orderSide == side.SELL) {  
    
 while (i>0) {

    if (orders[i].price < orders[i-1].price) {
        Order memory  orderToMove = orders[i];
        orders[i] = orders[i-1];
        orders[i-1] = orderToMove;
         i--;  
    }
      
} 

}
nextOrderId ++;
}
}

1 Like

Hey @DavidV, the problem is not your tests. The problenm is that there is a runtime error in your code. Judging from yoour tests it is most likley a code bug in your limit order function.

From looking at your create limit order function there is an error in your bubble sort. your code has the following format

uint i = orders.length > 0 ? orders.length-1 : 0; 

    if (orderSide == side.BUY) {

        while (i>0) {

            if (orders[i].price > orders[i-1].price) {
                Order memory  orderToMove = orders[i];
                orders[i] = orders[i-1];
                orders[i-1] = orderToMove;
            }
        i--;        
}

you are never breaking out of the code loop thus it will never end as there is no stopping condition. Also your incrementation, or rather deincrementation of the ā€œiā€ variable should be inside the brackert. change your code to be

 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--;
        }
    } 

The same holds treu for your bubble sort on the sell side. I have fixed your limit order function. Use this code

function createLimitOrder( Side side, bytes32 ticker, uint amount, uint price) public {
if(side == Side.BUY) {
    require(balance[msg.sender]["ETH"] >= amount * price );
}
if(side == Side.SELL) {
    require(balance[msg.sender][ticker] >= amount);
}
Order[] storage orders = orderBook[ticker][uint(side)];
 orders.push(Order(nextOrderId, msg.sender, side, ticker, amount, price, 0));

    //Bubble sort
   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++;

}

This should get rid of the runtime error however there still may be syntax issues in your tests that you may have to fix but the main thing is that your limit oprder function will now work. Also since you have not provided the rest of your code there may be other issues. If this is the case let me know

I will give you a tip on how to find the location of errors when testing. So to start you know that there is a runtime error from your tyest that failed. Anytime you getb a runtime error it means there is a fatal bug or error in your code (i.e the logic doest make sense).What you should do is comment out everline in your test execpt fro the first. run the test if ity passes uncomment out the next line and run it again. keep doing this until you reach the line your test fails. now you have identified the line or area where the bug is. then proceed to fix the bug from there. 9 times out of ten you will realise that the fix is a typo or something rather easy.

Hope this helps,
Evan

1 Like

Sorry made a mistake

1 Like

Iā€™m having trouble testing the bubble sort test on Dextest.js

assert(ā€¦) part of the test fails and I cannot understand why, as when i consolelog the Orderbook, everything is in correct order and i am unsure why this is failing.

What am i doing wrong to get an assertion error when orderBook bubble sort is done correctly?

Here is the code;

//the user must have ETH deposted such that deposted eth >= buy order value
// the user must have enough tokens deposited such that token balance >= sell order amount
// the BUY order book should be ordred on pirce from highest to lowest starting at index 0

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

contract ("Dex", accounts => {
    it("ETH balance should be >= order buy value", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        let eth2 = await Eth2.deployed();
        await link.approve(dex.address,500);
        await eth2.approve(dex.address,500);
        dex.addToken(web3.utils.fromUtf8("Link"),link.address,{from: accounts[0]});
        dex.addToken(web3.utils.fromUtf8("ETH2"),eth2.address,{from: accounts[0]});
        await truffleAssert.reverts(
            dex.createLimitOrder(0,web3.utils.fromUtf8("Link"),1,1)
        )
        await dex.deposit(100,web3.utils.fromUtf8("ETH2"));
        await truffleAssert.passes(
            dex.createLimitOrder(0,web3.utils.fromUtf8("Link"),1,1)
        )
    })
    it("User should have enough tokens to sell", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        await link.approve(dex.address,500);
        dex.addToken(web3.utils.fromUtf8("Link"),link.address,{from: accounts[0]});
        await truffleAssert.reverts(
            dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,1)
        )
        await dex.deposit(100,web3.utils.fromUtf8("Link"));
        await truffleAssert.passes(
            dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,1)
        )
    })
    
    
    it("the BUY order book should be ordred on pirce 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);
        dex.addToken(web3.utils.fromUtf8("Link"),link.address,{from: accounts[0]});
        await dex.deposit(100,web3.utils.fromUtf8("Link"));
        
        await dex.createLimitOrder(0,web3.utils.fromUtf8("Link"),1,10);
        await dex.createLimitOrder(0,web3.utils.fromUtf8("Link"),1,100);
        await dex.createLimitOrder(0,web3.utils.fromUtf8("Link"),1,30);
        await dex.createLimitOrder(0,web3.utils.fromUtf8("Link"),1,50);
        let orderBook = await dex.getOrderBook(web3.utils.fromUtf8("Link"),0);
        console.log(orderBook);
        for (i = 0; i < orderBook.length -1;i++) {
            assert(orderBook[i].price >= orderBook[i+1].price, "not the right BUY Book order")
        }
    })
    

    
    it("the SELL order book should be ordred on pirce 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.deposit(100,web3.utils.fromUtf8("Link"));
        dex.addToken(web3.utils.fromUtf8("Link"),link.address,{from: accounts[0]});
        
        await dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,10);
        await dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,50);
        await dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,40);
        await dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,100);
        await dex.createLimitOrder(1,web3.utils.fromUtf8("Link"),1,20);
        let orderBook = await dex.getOrderBook(web3.utils.fromUtf8("Link"),1);
        
        
        console.log(orderBook);
        for (i = 0; i < orderBook.length -1;i++) {
            assert(orderBook[i].price <= orderBook[i+1].price,"not the right SELL book order")
        }
    })

    
    //When creating a SELL market order, the seller needs to have enough tokens for the trade
    it("When creating a SELL market Order, the seller needs to have enough tokens for the trade", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        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"), {to: accounts[0]});

    } )
    
 
})

and my test returns the following results

 Contract: Dex
    āˆš ETH balance should be >= order buy value (1539ms)
    āˆš User should have enough tokens to sell (961ms)
[
  [
    '3',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '0',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '100',
    id: '3',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '0',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '100'
  ],
  [
    '5',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '0',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '50',
    id: '5',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '0',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '50'
  ],
  [
    '4',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '0',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '30',
    id: '4',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '0',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '30'
  ],
  [
    '2',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '0',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '10',
    id: '2',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '0',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '10'
  ],
  [
    '0',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '0',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '1',
    id: '0',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '0',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '1'
  ]
]
    1) the BUY order book should be ordred on pirce from highest to lowest starting at index 0

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

    IERC20.Approval(
      owner: <indexed> 0x5C6a528cC482409E005fdcd45E2694c615a58e63 (type: address),
      spender: <indexed> 0x3954850EA5fbffe55047afc75c039132b125438B (type: address),
      value: 500 (type: uint256)
    )

    IERC20.Transfer(
      from: <indexed> 0x5C6a528cC482409E005fdcd45E2694c615a58e63 (type: address),
      to: <indexed> 0x3954850EA5fbffe55047afc75c039132b125438B (type: address),
      value: 100 (type: uint256)
    )

    IERC20.Approval(
      owner: <indexed> 0x5C6a528cC482409E005fdcd45E2694c615a58e63 (type: address),
      spender: <indexed> 0x3954850EA5fbffe55047afc75c039132b125438B (type: address),
      value: 400 (type: uint256)
    )


    ---------------------------
[
  [
    '1',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '1',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '1',
    id: '1',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '1',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '1'
  ],
  [
    '6',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '1',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '10',
    id: '6',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '1',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '10'
  ],
  [
    '10',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '1',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '20',
    id: '10',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '1',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '20'
  ],
  [
    '8',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '1',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '40',
    id: '8',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '1',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '40'
  ],
  [
    '7',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '1',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '50',
    id: '7',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '1',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '50'
  ],
  [
    '9',
    '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    '1',
    '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    '1',
    '100',
    id: '9',
    trader: '0x5C6a528cC482409E005fdcd45E2694c615a58e63',
    side: '1',
    ticker: '0x4c696e6b00000000000000000000000000000000000000000000000000000000',
    amount: '1',
    price: '100'
  ]
]
    2) the SELL order book should be ordred on pirce from lowest to highest starting at index 0

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

    IERC20.Approval(
      owner: <indexed> 0x5C6a528cC482409E005fdcd45E2694c615a58e63 (type: address),
      spender: <indexed> 0x3954850EA5fbffe55047afc75c039132b125438B (type: address),
      value: 500 (type: uint256)
    )

    IERC20.Transfer(
      from: <indexed> 0x5C6a528cC482409E005fdcd45E2694c615a58e63 (type: address),
      to: <indexed> 0x3954850EA5fbffe55047afc75c039132b125438B (type: address),
      value: 100 (type: uint256)
    )

    IERC20.Approval(
      owner: <indexed> 0x5C6a528cC482409E005fdcd45E2694c615a58e63 (type: address),
      spender: <indexed> 0x3954850EA5fbffe55047afc75c039132b125438B (type: address),
      value: 400 (type: uint256)
    )


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

  Contract: Dex
    āˆš should only be possible for owner to add tokens (571ms)
    āˆš It should handle faulty withdrawls correctly (289ms)
    āˆš It should handle correct withdrawls correctly (734ms)


  5 passing (15s)
  2 failing

  1) Contract: Dex
       the BUY order book should be ordred on pirce from highest to lowest starting at index 0:
     AssertionError: not the right BUY Book order
      at Context.<anonymous> (test\dextest.js:56:13)
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (internal/process/task_queues.js:95:5)

  2) Contract: Dex
       the SELL order book should be ordred on pirce from lowest to highest starting at index 0:
     AssertionError: Unspecified AssertionError
      at Context.<anonymous> (test\dextest.js:79:13)
      at processTicksAndRejections (internal/process/task_queues.js:95:5)

1 Like

strange your logic looks fine. Have you tried restarting your terminal

Yes, I restarted my terminal and still get an error.

1 Like

can you push to github ill clone it and see if i van if for you

Hello, I am currently in the finishing wallet section. Whenever I try compiling the contract I get this error message for some reason :

Compiling your contractsā€¦

Compiling .\contracts\Migrations.sol
Compiling .\contracts\wallet.sol
Compiling .\node_modules@openzeppelin\contracts\token\ERC20\IERC20.sol
Compiling .\node_modules@openzeppelin\contracts\utils\math\SafeMath.sol
Compiling .\node_modules@openzeppelin\upgrades\contracts\ownership\Ownable.sol

project:/node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol:22:9: ParserError: Expected primary expression.
unchecked {
^-------^

Compilation failed. See above.
(node:15924) V8: C:\Users\Admin1.config\truffle\compilers\node_modules\soljson-v0.5.0+commit.1d4f565a.js:3 Invalid asm.js: Invalid member of stdlib
(Use node --trace-warnings ... to show where the warning was created)

I am not sure why this error is coming up, since my code is exactly how phillip did it in the video.

Please help me with this issue if possible.

Hi - I just wrote my market order function and when I go to run it with the test file, Iā€™m getting errors related to the toNumber() function in the test file. Iā€™ve tried googling and havenā€™t had much luckā€¦ was hoping someone here could help me. Here is the error;

Capture

Here is the test code;

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

contract("Dex", accounts => {

    //When creating a SELL market order, the seller needs to have enough tokens for the trade
    it("should not allow market sell orders for more tokens than seller has in balance", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

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

        let balance = await dex.balances(accounts[0], web3.utils.fromUtf8("LINK"))
        assert.equal(balance.toNumber(), 0, "Initial LINK balance is not 0")
        
        truffleAssert.reverts(
            dex.marketOrder(web3.utils.fromUtf8("LINK"), 1, 30)
            )
    })

    //Market orders can be submitted even if the order book is empty
    it("should allow market orders to be placed if order book is empty", async () => {
        let dex = await Dex.deployed()

        await dex.depositEth({value: 50000})

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"),0)
        assert.equal(book.length, 0, "Buy side of orderbook length is not 0")

        truffleAssert.passes(
            dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 20)
            )
    })

   //Market orders should be filled until the order book is empty or the market order is 100% filled
   it("should not fill more limit orders than market order amount", async () => {
        let dex = await Dex.deployed()
        let link = await Link.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should be empty at start of test")

        await link.transfer(accounts[1],150)
        await link.transfer(accounts[2],150)
        await link.transfer(accounts[3],150)

        await link.approve(dex.address, 50, {from: accounts[1]})
        await link.approve(dex.address, 50, {from: accounts[2]})
        await link.approve(dex.address, 50, {from: accounts[3]})

        await dex.deposit(50, web3.utils.fromUtf8("LINK"), {from: accounts[1]})
        await dex.deposit(50, web3.utils.fromUtf8("LINK"), {from: accounts[2]})
        await dex.deposit(50, web3.utils.fromUtf8("LINK"), {from: accounts[3]})

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 20, {from: accounts[2]})
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 30, {from: accounts[3]})

        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 10)

        book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 1, "Sell side of orderbook should have 1 order left")
        assert.equal(book[0].filled, 0, "Sell side of order should have 0 filled")
    })

       //Market orders should be filled until the order book is empty or the market order is 100% filled
   it("should fill limit orders until order book is empty", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 1, "Sell side of orderbook should have 1 order left")

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 20, {from: accounts[2]})

        let balanceBefore = dex.balances(accounts[0], web3.utils.fromUtf8("LINK"))

        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 50)

        let balanceAfter = dex.balances(accounts[0], web3.utils.fromUtf8("LINK"))

        assert.equal(balanceBefore.toNumber() + 15, balanceAfter.toNumber())

        book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should have 0 orders left")
    })
   //The ETH balance of the market buyer should decrease by the filled amount
   it("should deduct eth correctly from buyer wallet balance", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should be empty at start of test")

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        
        let balanceBefore = dex.balances(accounts[0], web3.utils.fromUtf8("ETH"))
        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 5)
        let balanceAfter = dex.balances(accounts[0], web3.utils.fromUtf8("ETH"))

        assert.equal(balanceBefore.toNumber() - 50, balanceAfter.toNumber())
    })
   //The token balance of the market buyer should increase by the filled amount
   it("should increase token amount correctly in buyer wallet balance", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should be empty at start of test")

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        
        let balanceBefore = dex.balances(accounts[0], web3.utils.fromUtf8("LINK"))
        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 5)
        let balanceAfter = dex.balances(accounts[0], web3.utils.fromUtf8("LINK"))

        assert.equal(balanceBefore.toNumber() + 5, balanceAfter.toNumber())
    })
   //The token balances of the limit order sellers should decrease by the filled amounts
   it("should decrease token balances of filled sell limit orders correctly", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should be empty at start of test")

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 15, 20, {from: accounts[2]})
        
        let account1BalanceBefore = dex.balances(accounts[1], web3.utils.fromUtf8("LINK"))
        let account2BalanceBefore = dex.balances(accounts[2], web3.utils.fromUtf8("LINK"))
        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 15)
        let account1BalanceAfter = dex.balances(accounts[1], web3.utils.fromUtf8("LINK"))
        let account2BalanceAfter = dex.balances(accounts[2], web3.utils.fromUtf8("LINK"))

        assert.equal(account1BalanceBefore.toNumber() - 5, account1BalanceAfter.toNumber())
        assert.equal(account2BalanceBefore.toNumber() - 10, account2BalanceAfter.toNumber())
    })
   //The ETH balances of the limit order sellers should increase by the filled amounts
   it("should increase ETH balances of filled sell limit orders correctly", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 1, "Sell side of orderbook should have 1 order at the start of the test")

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        
        let account1BalanceBefore = dex.balances(accounts[1], web3.utils.fromUtf8("ETH"))
        let account2BalanceBefore = dex.balances(accounts[2], web3.utils.fromUtf8("ETH"))
        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 10)
        let account1BalanceAfter = dex.balances(accounts[1], web3.utils.fromUtf8("ETH"))
        let account2BalanceAfter = dex.balances(accounts[2], web3.utils.fromUtf8("ETH"))

        assert.equal(account1BalanceBefore.toNumber() + 50, account1BalanceAfter.toNumber())
        assert.equal(account2BalanceBefore.toNumber() + 100, account2BalanceAfter.toNumber())
    })
   //Filled limit orders should be removed from the orderbook.
   it("should remove filled limit orders correctly", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should by empty at the start of the test")

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 10, {from: accounts[1]})
        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 5)

        book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should by empty at the end of the test")
    })
    //Partly filled limit orders should be modified to represent the filled/remaining amount
    it("Limit orders filled property should be set correctly after a trade", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1);
        assert(book.length == 0, "Sell side Orderbook should be empty at start of test");

        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 30, {from: accounts[1]})
        await dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 2);

        book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1);
        assert.equal(book[0].filled, 2);
        assert.equal(book[0].amount, 5);
    })
    //When creating a BUY market order, the buyer needs to have enough ETH for the trade
    it("should not allow buy orders for more ETH than the buyer has in balance", async () => {
        let dex = await Dex.deployed()

        let book = await dex.getOrderBook(web3.utils.fromUtf8("LINK"), 1)
        assert.equal(book.length, 0, "Sell side of orderbook should by empty at the start of the test")
        
        let balance = await dex.balances(accounts[4], web3.utils.fromUtf8("ETH"))
        assert.equal( balance.toNumber(), 0, "Initial ETH balance is not 0" );
        await dex.createLimitOrder(web3.utils.fromUtf8("LINK"), 1, 5, 300, {from: accounts[1]})

        await truffleAssert.reverts(
            dex.marketOrder(web3.utils.fromUtf8("LINK"), 0, 5, {from: accounts[4]})
        )
    })
})
1 Like

just assert use your balance variable you dont need the .toNumber

I tried using my balance variable without .toNumber and got another error. After a good nights sleep, I took another look at my code and noticed I forgot the await keyword in the declaration of the balance variables. So now it works with the .toNumber. Thank you! @mcgrane5

1 Like

Hi there,

When im trying to set : " let wallet = await wallet.deployed() "
i get the error: " wallet has not been deployed to detected network (network/artifact mismatch) "
There must be something wrong with the wallet.sol contract because when i do :
let token = await link.deployed()
It works fine

please help

node -v : v10.21.0

2_wallet_migration.js
=====================

   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0x724089eab8c079cf35d43d5a4a0bfb551d6ef7e810a68f49c730a560b38666c4
   > Blocks: 0            Seconds: 0
   > contract address:    0xB7712f3AF470F3815c13251E67E40B7F1e8c0077
   > block number:        27
   > block timestamp:     1629551510
   > account:             0xB4bA0A3c079ceE4C239b3cd4A8EdeeAb69e65464
   > balance:             99.984134134
   > gas used:            248854 (0x3cc16)
   > gas price:           2 gwei
   > value sent:          0 ETH
   > total cost:          0.000497708 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:         0.000497708 ETH


3_tokens_migration.js
=====================

   Replacing 'link'
   ----------------
   > transaction hash:    0xea610ffa85a8a7e0adfc7fd255f809f6174048ade7df10233d0ed39b4e1b77aa
   > Blocks: 0            Seconds: 0
   > contract address:    0x60dA7a1D38f3F828C6A45942A5bF7A59c0282a55
   > block number:        29
   > block timestamp:     1629551510
   > account:             0xB4bA0A3c079ceE4C239b3cd4A8EdeeAb69e65464
   > balance:             99.981573246
   > gas used:            1237931 (0x12e3ab)
   > gas price:           2 gwei
   > value sent:          0 ETH
   > total cost:          0.002475862 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:         0.002475862 ETH


Summary
=======
> Total deployments:   3
> Final cost:          0.003471278 ETH


- Fetching solc version list from solc-bin. Attempt #1
- Blocks: 0            Seconds: 0
- Saving migration to chain.
- Blocks: 0            Seconds: 0
- Saving migration to chain.
- Blocks: 0            Seconds: 0
- Saving migration to chain.

truffle(develop)> let Wallet = await wallet.deployed()
Uncaught:
Error: wallet has not been deployed to detected network (network/artifact mismatch)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at Function.deployed (/usr/local/lib/node_modules/truffle/build/webpack:/packages/contract/lib/contract/constructorMethods.js:83:1)
    at Object.checkNetworkArtifactMatch (/usr/local/lib/node_modules/truffle/build/webpack:/packages/contract/lib/utils/index.js:245:1)
truffle(develop)> let token = await link.deployed()
undefined
truffle(develop)> 

here is my migration file:
2_wallet_migration.js

const wallet = artifacts.require("wallet");

module.exports = function (deployer) {
  deployer.deploy(wallet);
};

and my wallet.sol contract:

pragma solidity ^0.8.0;

import "../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";

contract wallet is Ownable{

    using SafeMath for uint256;
    struct Token {
        bytes32 ticker;
        address tokenAddress;
    }
    mapping (bytes32 => Token)public tokenMapping;

    bytes32 [] public tokenList;

    mapping (address => mapping(bytes32 => uint256)) balances;

    modifier tokenExist(bytes32 ticker){
        require(tokenMapping[ticker].tokenAddress != address(0), "token does not exist");
        _;
    }
    function addToken(bytes32 ticker, address tokenAddress) onlyOwner external {
        tokenMapping[ticker] = Token(ticker, tokenAddress);
        tokenList.push(ticker);
    }


    function deposit(uint amount, bytes32 ticker) tokenExist(ticker) external{
    
        IERC20(tokenMapping[ticker].tokenAddress).transferFrom(msg.sender, address(this), amount);
        balances[msg.sender][ticker] = balances[msg.sender][ticker].add(amount);
        

     
    }

    function withdraw(uint amount, bytes32 ticker)tokenExist(ticker) external{
 
        require(balances[msg.sender][ticker] >= amount, "Balance not sufficient");

        balances[msg.sender][ticker] = balances[msg.sender][ticker].sub(amount);
        IERC20(tokenMapping[ticker].tokenAddress).transfer(msg.sender, amount); 
    }
}
1 Like

can you check your truffle config to make sure that your network is definitely truffle development. Although it should be if your link can deploy. can you push your code to git and i will take a look for you.

i.e in truffle config just confirm that your network is

 development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 8545,             // Standard Ethereum port (default: none)
     gas: 8500000,           
     network_id: "test",       // Any network (default: none)
    },

Actually ok i see what the trouble is. Your wallet is never getting deployed. In your compilation above only your initial migration file and link token contract are getting deployed. Without seeing your code i cannot say but i would imagine the issue is with your migrations. It looks like you initial migration is being deployed by as your wallet_migrations which is weird. Could your try to change your migration files to what i have above.

You should have 3 migrations

1_initial_migration.js
2_wallet_migration.js
3_link_migration.js

the contents should be as follows

1_initial_migration.js

const Migrations = artifacts.require("Migrations");

module.exports = function (deployer) {
  deployer.deploy(Migrations);
};

2_wallet_migration.js

const wallet = artifacts.require("wallet");

module.exports = function (deployer) {
  deployer.deploy(wallet);
};

3_link_migration.js

const link = artifacts.require("link");

module.exports = async function (deployer) {
  await deployer.deploy(link);
};

These should be your migration files. Just be careful if you are gonna try copy these just to see if this is indeed your issue first make sure the capitialisation of the ā€œwalletā€ and ā€œlinkā€ contracts in your code is akin with what i wrote above.

If this is not the issue push your code to github for me

1 Like

I wrote the migration file again and now it looks like the wallet is migrated. Not sure what was wrong but now i get a new error message:

_truffle(develop)> let wallet = await wallet.deployed()
_Uncaught TypeError: Cannot read property ā€˜deployedā€™ of undefined
at evalmachine.:1:16

1 Like

can u push your whole code to github i willl havea look