0

I was following a tutorial that can buy erc20 tokens and I'm now stuck with transferring tokens to a buyer account which I need more clarification. So basically, a buyer account is trying to purchase some tokens. That's it.

For example, there's a contract that implements erc20 functions

contract DappToken {
    //...
    mapping(address => uint256) public balanceOf;

    function DappToken (uint256 _initialSupply) public {
        balanceOf[msg.sender] = _initialSupply;
        totalSupply = _initialSupply;
    }

    function transfer(address _to, uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);

        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;

        Transfer(msg.sender, _to, _value);

        return true;
    }
}

and there's another contract that takes DappToken contract as a parameter of its constructor.

contract DappTokenSale {
//...

    function DappTokenSale(DappToken _tokenContract, uint256 _tokenPrice) public {
        admin = msg.sender;
        tokenContract = _tokenContract;
        tokenPrice = _tokenPrice;
    }

    function buyTokens(uint256 _numberOfTokens) public payable {
        require(msg.value == multiply(_numberOfTokens, tokenPrice));
        require(tokenContract.balanceOf(this) >= _numberOfTokens);
        require(tokenContract.transfer(msg.sender, _numberOfTokens));

        tokensSold += _numberOfTokens; 

        Sell(msg.sender, _numberOfTokens);
    }
}

Here's my question, how does a buyer pass below requirement in buyTokens function?

require(tokenContract.transfer(msg.sender, _numberOfTokens));

My understanding is..

  1. When the buyer tries to buy tokens, it will call transfer function in DappToken contract passing buyer's account address (msg.sender) and the number of tokens to purchase (_numberOfTokens).
  2. transfer function in DappToken contract will check if the buyer has existing balance. require(balanceOf[msg.sender] >= _value);

But I don't understand why there's a check to see if a buyer has existing balance? What if it was the buyer's first time purchasing the tokens? then the buyer won't have existing tokens in balanceOf variable initially.

or is the msg.sender in transfer function a DappTokenSale's contract address?

1

Let me explain you a bit but first of all when a contract calls any function of another contract the msg.sender will be the address of the calling function. Now let me explain the follow. When a buyer wants to buy tokens he will call:

   function buyTokens(uint256 _numberOfTokens) public payable {
        require(msg.value == multiply(_numberOfTokens, tokenPrice));
        require(tokenContract.balanceOf(this) >= _numberOfTokens);
        require(tokenContract.transfer(msg.sender, _numberOfTokens));

        tokensSold += _numberOfTokens; 

        Sell(msg.sender, _numberOfTokens);
    }

As indicating the buyer will specify that how much tokens he want to buy in _numberOfTokens. As the function is payable buyer need to send some ether along with the call which will indicate by msg.value, At the first there is check whether the ether send along the call is equal to the actual amount of the tokens. The second line will be confusion for you.

this is the address of the smart contract itself and tokenContract.balanceOf(this) is checking the balance of DappTokenSale contract account from the DappToken contract. In other words how much balance is of DappTokenSale inside the DappToken and it should be equal or more than the _numberOfTokens (line 2).

Lastly, third line is calling a transfer function of DappToken with msg.sender (buyer address) as to parameter, _numberOfTokens as value in the following function:

function transfer(address _to, uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);

        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;

        Transfer(msg.sender, _to, _value);

        return true;
    } 

Now, at first line msg.sender belongs to the DappTokenSale contract address and _value is _numberOfTokens and checking that the DappTokenSale has balance of more or equal than the _numberOfTokens. Then in the following lines just transferring the _numberOfTokens from DappTokenSale account to buyer account.

Note: Contract are also accounts and can be treated as address. Contract account can also have balance in another contract. There is no balance check on buyer address. In the above example DappTokenSale is acting as sender which sending tokens to buyer from DappToken.

Hope it will clear.

  • Thanks for your effort. So my assumption was right or is the msg.sender in transfer function a DappTokenSale's contract address? – bbusdriver Mar 25 at 5:41
  • 1
    when calling transfer function as this tokenContract.transfer(msg.sender, _numberOfTokens), this time msg.sender is buyer. inside the transfer function in DappToken as shown here require(balanceOf[msg.sender] >= _value); the msg.sender is DappTokenSale. – Abdullah Aziz Mar 25 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.