External Contracts & Calls Discussion

Hey @javier_ortiz_mir

The transfer function reverts on failure, while the send function just returns false and does not revert.

The consequences are:

  • If transferfails you will notice it because it reverts. You will pay only for the amount of code already executed.
  • If sendfails it returns false. It means that you need to handle the error yourself.

Happy learning,
Dani

Thanks for the fast reply @dan-i but in the case of send, even when it returns false, does it spend the gas according to the executed code?

1 Like

Hey @javier_ortiz_mir,

Great question!
My understanding is that send() when it fails and returns false, will use slightly more gas than transfer() when it reverts (all other things in the function being equal).
My reasoning is that transfer() on failure reverts and only consumes gas for the operations performed up to that point… whereas send() will return false and any remaining code in the function will continue to be executed as no revert is triggered. With send() you will still pay gas to find out that it returns false, and also for handling this error, but with transfer() you won’t have that extra cost.

3 Likes

As of 0.7.0 using .value(amount) is deprecated.
It is recommended(docs.soliditylang.org) to use .{value: amount} instead.

3 Likes

Hello
For the push method, I don’t really understand what it means by “run out of gas”.
Who’s paying the gas? Isn’t it the user? Or is it the contract?
I am a bit confused.

Hi @REGO350

I suggest you to take some time and deeply understand how Ethereum works so that you will be able to use its max potential.
This video is a good starting point: https://academy.ivanontech.com/products/ethereum-101/categories/1684760/posts/5657771

Cheers,
Dani

Ok, I read some articles after.
But I want to make it clear:
The gas here is referring to gas limit. This limit prevents programs from spamming or running very complex function.

Hi @filip . Can you explain, I do not really understand this bug. Why other function can be call before balance[msg.sender] = 0 being executed

Hi, I have a question as to the syntax of the call function.

In the video Filip writes it as address.call.value(x), but according to this article from version 0.8.3 it’s address.call{value: x}("") (or optionally adding gas costs address.call{gas: x, value: y}("").

Which is it? And does it make a difference?

I can’t find the call function on any of the official channels, so if someone knows where to look, please let me know.

So are there use cases for Contract.callcode() nowadays?

Hey,

So I found kind of a contradiction between this course and ethereum programming 201 since here it is said that ‘address.call.value()()’ should not be used since it is vulnerable to re-entrancy attacks but on the other course it is said to be used instead of ‘address.transfer()’ since this later function can run out of gas when called by complex functions or if in the future our contract will be outdated in terms of gas spent being more than the gas stipend.

I am therefore confused, should I use ‘address.call.value()()’ or not?

Thanks

This may be a very simple question to answer. In the second step, the effect step, where you set the balance to zero, how does that work in the account? It seems like it might actually set the account balance to zero leaving no value to withdraw in the interaction step. I’m assuming this is wrong and the balances account does not affect the actual monetary value of the account-- in this case, what am I missing? How are we changing the value of the account value to zero and still allowing someone to receive value from that balance?

1 Like

The reason it is possible to receive value (more than 0) through “interaction” line in the code is because the balance of the user was already checked in the “checks” part, and the user initially had something on the balance, before the balance was set to 0. It was required to be equal to the amount in the balances mapping for that msg.sender in the initial line.

uint amountToWithdraw = balances[msg.sender];

next after that, the value for msg.sender in the mapping is set to 0,

balances[msg.sender] = 0;

and then the amount (that must be equal to balance in the mapping when code was ran initially) is sent from the smart contract.

require(msg.sender.call.value(amountToWithdraw)());

The contract caller cant withdraw again because now his amount in mapping is set to 0 and the smart contract will think he doesnt have any right to money on the smart contract. But he was able to withdraw after his balance was set to zero because the smart contract ran the code to give the withdraw amount (required to be equal to balance before it was set to 0) to the msg.sender.

2 Likes

How come do we not know the code of the external contract that we call to? Would it also not in theory be visible publicly on the blockchain for us to read as to what is possible to do with it and what not?