From the buy/sell example on ethereum.org:

function buy() payable returns (uint amount){
    amount = msg.value / buyPrice;                    // calculates the amount
    _transfer(this, msg.sender, amount);
    return amount;

function sell(uint amount) returns (uint revenue){
    require(balanceOf[msg.sender] >= amount);         // checks if the sender has enough to sell
    balanceOf[this] += amount;                        // adds the amount to owner's balance
    balanceOf[msg.sender] -= amount;                  // subtracts the amount from seller's balance
    revenue = amount * sellPrice;
    msg.sender.transfer(revenue);                     // sends ether to the seller: it's important to do this last to prevent recursion attacks
    Transfer(msg.sender, this, amount);               // executes an event reflecting on the change
    return revenue;                                   // ends function and returns

In the sell function, I understand that Ether is transferred from the contract to the caller via:


But in the buy function, I see nothing equivalent to ensure that Ether is transferred from the caller to the contract.

So how exactly does that take place? Does the keyword payable have anything to do with it?

Thank you!


To send ether to a contract, you invoke one of its payable functions by sending some ether together with the transaction.

For example: myContract.buy({}, { from: myAddress, value: someAmountInWei })

The amount received can then be seen in msg.value. No action is needed inside the contract to receive ether, the amount is automatically added to the account of the contract once the call finishes successfully (Note: if a function isn't payable, calling it with non-zero ether will fail).

address.transfer() is used to send ether from a contract to some other address (the caller of the function in the case of msg.sender.transfer()).

| improve this answer | |
  • So the payable keyword does not only "have something to do with it", but is also the actual trigger which ensures that Ether is transferred into the contract... Am I right? – goodvibration Jul 2 '18 at 14:15
  • payable is just a flag that allows ether to be sent together with the function call. Without it the function automatically rejects the call if it has any ether value. It's just a safety measure to prevent accidental payments to functions that don't do anything with the received amount. – rustyx Jul 2 '18 at 14:46
  • OK, but what exactly makes the amount to be "automatically added to the account of the contract once the call finishes successfully"? I mean, is that true for every function (declared payable) which is called with {msg.value > 0}? – goodvibration Jul 2 '18 at 14:55
  • A contract is "called" by sending a transaction to it. It's the same kind of transaction that you use to transfer ether from user A to user B, the network takes care of transferring the ether regardless of who user B is. Only in case user B is a contract, the EVM will additionally execute its code that further interprets the payload in the transaction (the function name and its arguments). – rustyx Jul 2 '18 at 15:08

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.