Project - Building a DEX

I was missing the await key thanks for the help. I eyes where to close to the issue.

1 Like

no worries at all. yeah you need the await because its an async function so all of the functions your calling run in parallel. where as in your former line, namely

wallet.addToken(web3.utils.fromUtf8("LINK"), link.address)

without the await keyword this means that his function has to execute before the proceeding lines can run. so the deposit function ends up running before your addToken call finishes and hence the error gets thrown on this line

How to get the error message when running truffle test ?
I only get the following message when a test fails :

Error: Returned error: VM Exception while processing transaction: revert

I would like to know why and where the revert happened.

You might need to check, which is the executed function on the test that triggers the revert, then you can add a error message to the require of that function.

Example:

require(balance[msg.sender] > amount, "not enough balance")

This one check if the balance of the msg.sender is higher than requested amount. When this condition fails, it will show the same message you are receiving plus the error message, that way we can have an idea on which condition is failing.

Try always to add a error message in your require from all functions, just to have a clear picture on which is triggering when this happens.

Carlos Z

I am continuing to get an error in VSCode for this project with the following line and can’t figure out what i am doing wrong? Initially i had solidity set to ^0.8.0 which was throwing the error and so i thought perhaps i needed to use the version Philip is using in the project so I am swtiched to pragma solidity >= 0.6.0 < 0.8.0; but it is still throwing the error so I am guessing it is not due to something deprecated in solidtity. Carlos or anyone do you know why I might be getting a problem/error in the following line…

mapping(bytes32 => mapping(uint256 => Order[]));

The error points the semicolon at the end and says… “expected identifier but got ;”
Of course i have the struct set up correctly too.

1 Like

Can you share the entire code in the following way? Apparently you have a typo error somewhere.

Carlos Z

1 Like

I figured it out Carlos. Forgot to give the mapping visibility and an actual name. Very silly mistake. Thanks for the response. Much appreciated.

2 Likes

Hi everyone!

I’m facing this problem. The contract doesn’t recognize the imported modifier OnlyOwner and throws an error.

pragma solidity 0.8.13;

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 {
    using SafeMath for uint256;

    struct Token { 
        bytes32 ticker;
        address tokenAddress;
    }

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

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

    modifier tokenExists(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) tokenExists(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)  tokenExists(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);
    }
} 

What could be wrong?

1 Like

yeah so you need to inherit the contract. i believe its called Ownable you can double check in the file in node modules. so change your contract declaration to

contract Wallet is Ownable {
}
1 Like

ohhh, you’re right. resolved. thanks a lot !

2 Likes

no worries, glad i could help

Hoping someone can help explain something in this Dex project. Isn’t the function cost getting the price at each iteration and multiplying it times the quantity?

uint cost = filled.mul(orders[i].price)

For example you have…
quantity price
5 $1.25
20 $1
45 $.75

So doesn’t the cost formula need to be revised so it adds each iteration (each price level and each quantity) all together? Isnt the current formula only summing one iteration at one price level. For example it is currently only calculating quantity of 5 at $1.25 instead of adding all 3 iterations i have listed together (assuming we want to fill all 70)? I sure i am wrong but if someone can explain this better or simply explain the cost formula better it would be a great help.

1 Like

no. so the way this dex work is known as an orderbook style dex. here traders come to trade and they basically place bids which are fullfileed by other traders. so for example i have 10 eth i want to sell at 100 euro. well then i come to the DEX and and i submit a sell order for the 10 eth at that price of 100. the only way i will be able to sell my eth is under two circumstances.

  1. another person who wants to buy exactly 10 eth at 100 euro cones to the dex and also submites and order

  2. someone comes to the dex just wanting eth but doest care about the price at all (market buy)

so the way that the current price of an asset is derermined in a orderbook style dex is that the price of an asset is always going to be the price of the order that is at the top of the order book. so in the case of a sell the price will be determined by the least amount someone is willing to sell their asset at. thats why the sell orderbook is ordered from smallest to largest. this has the effect of discouring users from asking for an outragous pric per token as if they do so there order book swill be ordered way down the list and will likely never get settled because i a dex ever time and order is executed its always the order at the top of the order book.

the opposite is true for buying. the buy orders are ordered opposite from largest to smallest so this discourages ppl from trying to buy below market price because again their order will be down the book and will likely not get settled.

so the orderbook is always ordered based on the price. and the next concept is what happens if someone wants to sell 10 eth at 100 euro. but then someone comes along and wants to buy 20 eth at 100 euro, well in this case the order at the top will get completely filled but the buyer still wants 10 eth that the forst ordder hasnt fulfilled, so what happens now is the second order moves to the top and it gets settled. and this is the flow for a dex. this concept is a little more advanced but it is covered in the videos so if you have any more question sdo ping me and ill be glad to help

I am assuming this reply was meant for me so thank you for the response. I understand how the order book works and how orders are sorted, but i am a confused about how the “cost” formula (uint cost = filled.mul(orders[i].price) of an order is being calculated. Like i said, i would have thought the overall cost is the qauntity filled times the price at each iteration (orders[i].price), but don’t we need to add each qauntity filled (filled) x each price it was filled at (order[i].price) and then sum it all together to get the total cost ? Its the summing it all together part that i feel is missing.

1 Like

@Bitborn ohh this is easily explained with a example test case. imagiine the orderbook looks as such (sell side)

[ALICE => amount: 5eth, price: 10$,
BOBY => amount: 6eth, price: 20$,
JOHN => amount: 9eth, price: 30$,]

and say now someone comes along and they want to buy 20 eth. which will clear out the orderbook. well since in order to completell fill this order of 20eth based on the current state of the orderbbok we will have to go three orders deep. so the minimum amount of $'s a the person will need to buy is 5 * 10 dollars to cover the first trade (as were buying 5 eth each at 10 dollars each), then anohter 6 * 20 dollars to cover the first trade (as were buying 6 eth each at 20 dollars each) and lastly another * 30 dollars to cover the first trade (as were buying 9 eth each at 30 dollars each) therefore in order to be able to afford the trade the user will need 5 * 10 + 6 * 20 + 9 * 30 = 440 dollars. so this is where the forumal comes from

Ohh so it is adding them together? I didn’t realize it was adding them together and that was precisely the problem I was tyring to explain. So in this formula… uint cost = filled.mul(orders[i].price) where is the addition part? Its the quantity filled times the price at each level but where is it adding them all together? I am sure there is something i am missing or not taking into consideration probably.
thanks again for your help btw. appreciate you trying to explain this.

Or wait… this forumula is happening inside the loop right? So is it looping again and adding to the cost that way? So each time it loops it basically adds each level (quantity x price)? Like in our example, the first loop is 5 *10 so the cost is $50. The second loop/iteration is 6x20 which is $120 so now cost is ($50 + $120) = $170, and so on? Is that how its adding each iteration together in the cost formual? via the loop?

1 Like

Can anyone tell me how to properly set the Ropsten network with a .env file using Moralis Nodes? I believe the problematic line here is… provider: () => new HDWalletProvider(mnemonic, https://speedy-nodes-nyc.moralis.io/${process.env.ROPSTEN_MORALIS_PROJECT_ID}/eth/ropsten), I don’t believe i am formatting this correcty. Anyone know how to correctly format this and set this up?

const dotenv = require("dotenv");
dotenv.config();

const HDWalletProvider = require("@truffle/hdwallet-provider");
const mnemonic = process.env.ROPSTEN_MNEMONIC;

module.exports = {

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

    ropsten: {
      provider: () => new HDWalletProvider(mnemonic, `https://speedy-nodes-nyc.moralis.io/${process.env.ROPSTEN_MORALIS_PROJECT_ID}/eth/ropsten`),
      network_id: 3,       // Ropsten's id
      gas: 5500000,        // Ropsten has a lower block limit than mainnet
      confirmations: 2,    // # of confs to wait between deployments. (default: 0)
      timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
      skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    },
  },
1 Like

hey @Bitborn it shoud work the way you have it set up there yes. what is the actualy error that your getting when trying to deploy?

I ended up using Infura this go around. Next project i will try Moralis nodes again and if i run into the same error i will copy and paste the error message. Thanks.

1 Like

no wories. i wish u the est of luck. and yes please do come here if youve any errors ill be here