I came across many blogs saying the defacto standard to send ether from one contract to another and why one is better than the other. However, what is the best practice for sending ether from contract to EAO (out of three withdrawal functions)?

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.5;

contract WalletApp {
    mapping(address => uint256) public balances;

    function depositBalance() external payable {
        balances[msg.sender] = msg.value;

    // Different ways to withdraw the deposit to externally owned account!
    // Gas usage: 30462 gas
    function withdrawDeposit() external payable {
        (bool success, ) = payable(msg.sender).call{
            value: balances[msg.sender]

    // Gas usage: 30320 gas
    function withdrawDeposit2() external payable {

    // Gas usage: 30256 gas
    function withdrawDeposit3() external payable {
        (bool success) = payable(msg.sender).send(balances[msg.sender]);

1 Answer 1


If you are sure that msg.sender is an Externally Owned Account (EOA) then all of them are fine, with a slight gas advantage for .transfer probably due to the way it handles errors.

That being said, you shouldn't make such an assumption as there are ways to bypass it, potentially exposing you to exploits.

The best (i.e., safest and most versatile) way overall is :

There is a great answer here going more in details over the differences between .transfer .send and .call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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