Project - Building a DEX

no worries. however are you able to push with github in your terminal. im missing nessecary files such as your package.json, and truffle.config etc. you can push easy with github using

git add --all
git commit -m "commit message"
git push -u origin main

if you have never used git before let me know and ill show you how to do it

Yes please show me how to do it. I only know how to copy and paste codes into Github.

1 Like

yeah u up for a quick call, its easier to show u over there. have u google meets?

I think I did do google meets b4. I donā€™t remember. It should be not hard to use.

1 Like

cool coming in 5 ill dm u a link now

5pm today? What time zone?

1 Like

meant 5 mins lol. dmd u the link there

Hereā€™s my link https://github.com/cyl2chan/ETH201-Building-DEX

Hey Iā€™m getting his error :


the test is not running, before this it did run the test but still the error was there, since I changed wallet to Dex this error came and I donā€™t think any test was run.
Hereā€™s my code :
3_token_migration.js -

const Link = artifacts.require("Link");
const Dex = artifacts.require("Dex");

module.exports = async function (deployer,network , accounts) {
  await deployer.deploy(Link);
  let dex = await Dex.deployed();
  let link = await Link.deployed();
  await dex.addToken(web3.utils.fromUtf8("LINK"),link.address)
  await link.approve(dex.address,500);
  await dex.deposit(100,web3.utils.fromUtf8("LINK"));
  let balanceOfLink = await dex.balances(accounts[0],web3.utils.fromUtf8("LINK"));
  console.log(balanceOfLink);
};

wallettest.js -

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

contract("Dex", accounts => {
    it("should inly be possible for owner to add tokens", async () => {
        let dex = await Dex.deployed();
        let link = await Link.deployed();
        await truffleAssert.passes(
            dex.addToken(web3.utils.fromUtf8("LINK"),link.address, {from: accounts[0]})
        )
        await truffleAssert.reverts(
            dex.addToken(web3.utils.fromUtf8("LINK"),link.address, {from: accounts[0]})
        )
    
    })
})

Iā€™m stuck here so do let me know if any other code files are required to be checked to get it running.

@thecil could you please look into it

hi, i am getting the same issue. i see itā€™s been awhile since you posted this. did you end up figuring it out? Thanks.

@mcgrane5 So I tried some new things to it , in 2_dex_migration.js , I changed ā€œWalletā€ to ā€œDexā€.
2_dex_migration.js -

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

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

so now Iā€™m getting this error -


Iā€™m sorry but Iā€™m really desperate finding a solution , would appreciate help fast as Iā€™m stuck at this for a while now.
Iā€™m at creating wallet test video in the course.

In your wallettest.js you have:

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

{from: accounts[0]} is the owner of the contract, so the transaction did not fail because the address of account[0] is the owner of the contract, you might want to try it from a different address and it should fail.

Carlos Z

ok, so I understand that but how do I get this test to pass?
in the cmd prompt I just run truffle test.
@thecil

Hi, i am following the dex course and unfortunatly i spent a lot of time trying to solve an issue during the first test: ā€œshould throw an error if ETH balance is too low when creating BUY limit orderā€.
I saw and compare with the final code and i still get this error : AssertionError: Failed with Error: Returned error: VM Exception while processing transaction.

Did someone find what does it means ?
There is my code

Blockquote

Blockquote

pragma solidity >=0.4.22 <0.9.0;
pragma experimental ABIEncoderV2;

import ā€œ./Wallet.solā€;

contract Dex is Wallet {
using SafeMath for uint256;

enum Side {
	BUY, 
	SELL 
}

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

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

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), "ETH balance is too low");
	}else if (side == Side.SELL) {
		require(balances[msg.sender][ticker] >= amount, "Low token balance");
	}
}

}

Blockquote

contract Wallet is Ownable {
using SafeMath for uint256;

struct Token {
    bytes32 ticker;
    address tokenAddress;
}

mapping(bytes32 => Token) public tokenMapping; 
bytes32[] public tokenList;

/**
* bytes32 pour faciliter les comparaisons car en solidity elles ne fonctionnent pas avec des string
*/
mapping(address => mapping(bytes32 => uint256)) public balances;

modifier tokenExist(bytes32 ticker) {
    require(tokenMapping[ticker].tokenAddress != address(0), "Token doen't exist"); //  check if the address exist so different to 0
    _;
}

function addToken(bytes32 ticker, address tokenAddress) external onlyOwner {
    tokenMapping[ticker] = Token(ticker, tokenAddress);
    tokenList.push(ticker);
}

function deposit(uint amount, bytes32 ticker) public payable tokenExist(ticker)  returns (uint)  {
    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) external tokenExist(ticker) returns (uint){
    require(balances[msg.sender][ticker] >= amount, "Balance not sufficient"); // check the sufficient fund

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

function depositEth() payable external {
    balances[msg.sender][bytes32("ETH")] = balances[msg.sender][bytes32("ETH")].add(msg.value);
}

function withdrawEth(uint amount) external {
    require(balances[msg.sender][bytes32("ETH")] >= amount,'Insuffient balance'); 
    balances[msg.sender][bytes32("ETH")] = balances[msg.sender][bytes32("ETH")].sub(amount);
    msg.sender.call{value:amount}("");
}

}

const Dex = artifacts.require(ā€œdexā€);
const Link = artifacts.require(ā€œLinkā€);

const truffleAssert = require(ā€˜truffle-assertionsā€™);

contract(ā€œdexā€, function (accounts) {
it(ā€œshould throw an error if ETH balance is too low when creating BUY limit orderā€, async function () {
let dex = await Dex.deployed();
let link = await Link.deployed();

await truffleAssert.reverts(
	dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1), "ETH balance is too low"
)
dex.depositEth({value: 10})
await truffleAssert.passes(
	dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1)
)

});

it(ā€œshould throw an error if token balance is too low when creating SELL limit orderā€, async function () {
let dex = await Dex.deployed();
let link = await Link.deployed();

await truffleAssert.reverts(
	dex.createLimitOrder(1, web3.utils.fromUtf8("LINK"), 10, 1)
)
await link.approve(dex.address, 500)
await dex.addToken(web3.utils.fromUtf8("LINK"), link.address, {from: accounts[0]})
await dex.deposit(10, web3.utils.fromUtf8("LINK"));
await truffleAssert.passes(
	dex.createLimitOrder(1, web3.utils.fromUtf8, 10, 1)
)

});

it(ā€œThe BUY order should be ordered on price from highest to lowest starting at index 0ā€, async function () {
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.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)
console.log(orderbook)
for (let i = 0; i < orderbook.length - 1; i++) {
	assert(orderbook[i].price >= orderbook[i+1].price, "not the right order in buy book")
}

});

it(ā€œThe SELL order should be ordered on price from lowest to highest starting at index 0ā€, async function () {
let dex = await Dex.deployed();
let link = await Link.deployed();
await link.approve(dex.address, 500)
await dex.depositEth({value: 3000});
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)
console.log(orderbook)
for (let i = 0; i < orderbook.length - 1; i++) {
	assert(orderbook[i].price <= orderbook[i+1].price, "not the right order in buy book")
}

});
});

1 Like

I think the error is related to the truffleAssertions methods, instead of using it, you can also use the truffle internal method expectRevert.

            await expectRevert(
            dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1),
            "ETH balance is too low"
            );

You can check my repo if you want to see how I use those methods on my unit tests instead of truffleAssertions

https://github.com/thecil/Project-Dex

Carlos Z

Thanks for responding and I appreciate you taking the time, but I used the expectRevert() method and still got the error.
I cloned the tutorial authorā€™s repository (https://github.com/filipmartinsson/dex), ran the tests and all passed except the test ā€œshould throw an error if the ETH balance is too much low when creating the buy limit orderā€.
The same test that doesnā€™t work in my project so I thought maybe it was a truffle version issue or npm or something else but to no avail
I donā€™t know why this test is not working.

your test code with truffleAssert.reverts is working on version ^0.9.2.

 await truffleAssert.reverts(
        dex.createLimitOrder(0, web3.utils.fromUtf8("LINK"), 10, 1),
        "ETH balance is too low"
      );

Maybe try comparing the package versions with Thecilā€™s GitHub repo for a mismatch.
https://github.com/thecil/Project-Dex

In the file wallettest.js, is there a way we can avoid to write the 2 following lines in each function it()?
I understand we need to deploy the contracts, but as we do it in the first implementation of the it() function, I would have thought there should be a way to deploy them once for all it() function.

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

Hi @fsicard

.deployed() only gets the reference instance of an already deployed contract. So you can use these two lines outside the it() scope so they are globally available to use in any test.

I hope this helps.

1 Like