Project - Building a DEX

Hi @wilsonlee123

The method _msgSender() returns the msg.sender.
With that clarification let’s check the transfer functions.

Consider the transfer() function:

function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
       ...
}

Consider the _transfer() function:

function _transfer(address sender, address recipient, uint256 amount) internal virtual {

The first parameter is the sender (_msg.sender());
The 2nd parameter is the recipient;
The 3rd parameter is the amount;

function _transfer(address sender, address recipient, uint256 amount) internal virtual {
       ...
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

Should make sense now :slight_smile:

Happy learning,
Dani

@dan-i Please look at withdraw() in the wallet contract - it’s passing in msg.sender, amount. So what would show up in the _transfer would be (_msgSender, msg.sender, amount)? Is that right?

Hey @wilsonlee123

Keep in mind that you are calling an external contract.

function _transfer(address sender, address recipient, uint256 amount)

sender = your contract address (msg.sender is not the user but your contract as you are calling an external contract).

recipient = the user address

I wrote for you a simple example hoping to clarify your ideas:

A.sol

pragma solidity 0.8.0;

interface B {
    function r() external view returns (address);    
}

contract Test {
    
    function go (address _contractB) public returns(address){
        address result = B(_contractB).r();
        return result;
    }
}

B.sol

pragma solidity 0.8.0;

contract Test {
    
    function r () public returns(address){
        return msg.sender;
    }
}
  • Deploy B and copy its address;
  • Deploy Al
  • Call go() by giving the contract B address as param
  • Check the returned value.

Cheers,
Dani

2 Likes

Great example! I think it finally makes sense to me now.
The contract calling the external contract is the _msgSender, and then in the contract itself msg.sender is the address of the user.
thanks again, @dan-i!

Good day @dan-i,

I’ve written out the basic tests now and about to start on the limit order test assignment. It doesn’t want to compile my contracts though. I keep getting this:

image

In truffle-config.js the compiler is set up like this:

// Configure your compilers
  compilers: {
    solc: {
       version: "0.7.0",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }

I have a feeling it has to do with my compile, but I’m not sure, what would you recommend checking?

Hey @wilsonlee123

This looks like a node issue tbh.
Follow this faq and let me know: FAQ - How to downgrade Node.Js

@dan-i I downgraded and it’s still giving me the error. I started a new folder with just wallet.sol and it wouldn’t even let me compile that. So definitely something weird with the compiler. What would you recommend trying from here on?
image

Hey @wilsonlee123

Seems to be an issue with truffle https://github.com/trufflesuite/truffle/issues/2702
Update truffle to the latest version and retry sudo npm i -g truffle

cheers,
Dani

Thanks, that did it! I can move on now.

1 Like

Happy Friday @dan-i,

I’m stuck again. Everything compiles except I keep getting this:
image

There’s something going on with the Wallet contract - I can’t compile it and therefore my test doesn’t work either.

The js file with my test is here:

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

contract("Dex", accounts => {
    it("Should only be possible for owner to add token", 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("AAVE"), link.address, {from: accounts[1]})
        )
    
    })
    it("should handle deposits correctly", 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"));
        await dex.balance(accounts[0], web3.utils.fromUtf8("LINK"));
        let balance = await dex.balances(account[0], web3.utils.fromUtf8("LINK"))
        assert.equal(balance.toNumber(), 100)
    })
})

I’m just following along right now, but before I attempt the order limit assignment I want to be make sure everything runs smoothly. Any ideas?

1 Like

Okay so this is my deposit function, iim pretty sure that im missing 1000 things, but i was looking at the _transfer function from ERC20.sol and i felt like there wasnt any require that i could add to make it more secure, im pretty sure that im wrong in my assumption xD (among other things because the finishing wallet video lasts almost 15 minutes so, sounds like theres gonna be a lot of explaining there) anyways i felt like i wasnt doing enough so i put an assert at the end, that balance should be equal to balance + amount, in case something goes wrong with the deposit??? but okay heres the code:

Summary
pragma solidity 0.8.2;

import "../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../node_modules/@openzeppelin/contracts/utils/math/SafeMath.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;

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

    function deposit(uint amount, bytes32 ticker) external{
        ERC20(msg.sender).transfer(tokenMapping[ticker].tokenAddress, amount);
        assert(balances[msg.sender][ticker] == balances[msg.sender][ticker] + amount);
    }

    function withdrawal(uint amount, bytes32 ticker) external{
        require(tokenMapping[ticker].tokenAddress != address(0));
        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);
    }

}

also i was thinking that if i am going to keep using the ERC20s _transfer function, then i should change Filips example of the withdraw function, but first i have to watch filips video, cause im pretty sure i needed to put some requires and who knows what else :thinking:

Hey @wilsonlee123

I think I totally missed your question sorry!
Would you please push your project in a GitHub repo and send me the link to it? I would like to deploy and double check.

Thanks,
Dani

Hey @Carlosvh96

Your code is correct and you are not missing any crucial require statement.
You could check that the balance is > than 0 in your deposit function if you want, or maybe that _tokenAddress is not address(0).
But still the code is correct.

Well done,
Dani

Good day @dan-i,

No worries! Any help is appreciated. Still stuck lol.
https://github.com/wilson-lee88/DEX

Hi @wilsonlee123

You are not deploying Wallet but you are trying to create an instance of it.
In 3_token_migration.js add await deployer.deploy(Wallet); before let wallet = await Wallet.deployed().

There is another issue in that file with dex check it out :slight_smile:

Cheers,
Dani

@dan-i, I think I fixed it.
It’s getting through the migration. But looks like truffle-assertions is not found? I don’t see Fillip importing it in the video though. What am I missing?
image

1 Like

@dani-i Following up on this. Please advise :blush:

1 Like

you probably forgot to install the module, you should try with:

npm install truffle-assertions

https://github.com/rkalis/truffle-assertions

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

3 Likes

@thecil Thanks Carlos, that was it :sweat_smile:

Everything can be tested now finally lol.

2 Likes

Hi!

Maybe I’m missing something but when writing the createLimitOrder tests there is a call to a function called “depositEth” that was never added to the wallet or dex, nor is it part of the ERC20 token. I took a stab at building it but was curious if this was something that was missed when building the dex project.

Thanks!!

2 Likes