12

In other words, is using transfer() safe?

function transfer(address contractB) public
{
    contractB.transfer(1000);
    //balances[msg.sender] -= 1000;
}

How about using call.gas?

function transfer2(address receiver) public
{
    receiver.call.gas(20000).value(1000)();
}
14

transfer() and send() should be avoided (because they take a hard dependency on gas costs by forwarding a fixed amount of gas: 2300).

Gas specific code (call{gas: ..., value: ...}("")) should also be avoided.

call{value: ...}("") should be used, for example: contractB.call{value: 1000}("")

It is also critical that you make sure to guard against reentrancy by making all state changes, before call{value: ...}("").

https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now explains more about the best practice change.

Any gas specific code should be avoided because gas costs can and will change.

For example, the gas cost for SLOAD was raised from 50 to 200 in 2016, and again in EIP 1884, with some impacts described in: https://chainsecurity.com/istanbul-hardfork-eips-increasing-gas-costs-and-more/


UNGAS is an idea to remove the GAS opcode and smart contracts would not have any notion of gas. (Gas would still be in the protocol, but not in the EVM.)

4
  • 1
    Rather than "prevent", it's better to say "guard against". You can't prevent reentrancy by making state changes before ether transfer. In your example, for example, you can re-enter multiple times, draining the balance of msg.sender. The example from the consensus blog sends the entire balance and has a line that sets the balance to 0 before the send, which guards appropriately in that context against reentrancy. Jan 15 '20 at 19:36
  • 1
    @Chan-HoSuh Thanks for your comments and edits have been made. (The example in this answer was basically copy-pasted from the question without much thought, so it has now been removed because it was a little nonsensical.)
    – eth
    Jan 18 '20 at 7:56
  • Care to explain why transfer() and send() should be avoided?
    – axwell
    Sep 7 at 16:30
  • 1
    @axwell I added a bit more explanation to answer but the linked blog post has more space for it.
    – eth
    Sep 12 at 5:27
6

the above answer is perfect, just notice the change in syntax in the latest version of Solidity.

someAddress.call{value: 1 ether}('');

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.