How to calculate the gas cost of Solidity's 'transfer' function?

Hi,

I have read that the gas cost of transfer function is 2300Ether. I have got the following contract having a function, testFunc(…), only containing transfer method as shown below:

pragma solidity ^0.5.1;
contract TransferCost{
uint public testVal = 97 ether;
function testFunc(address payable addr) public {
addr.transfer(testVal);
}
function deposit() payable public{}
}

When I am estimating the cost of the testFunc() function
using truffle console, I am not getting 2300 instead I am getting
32201.

Truffle(development)>TGC= await TransferCost.new()
undefined
*:
:

**truffle(development)> balance = await web3.eth.getBalance(TGC.address)**
**undefined**
**truffle(development)> web3.utils.fromWei(balance, "ether")**
**'194'**
**truffle(development)> await web3.eth.getGasPrice()**
**'20000000000'**
**truffle(development)> await TGC.testFunc.estimateGas('0x515f013CfC0B1beA8C4B95Baa438258EA1D81eeA')**
**32201**

Somebody please guide me how can we calculate the cost of transfer function to
be 2300 Ether?

1 Like

Hello @zak100

The addr.transfer() function (which you should not use by the way) indeed has a low cost, but this is not everything you have to account for.

  • First, any transaction cost at least 21000 gas … this a flat fee
  • Then you are sending data to a smart contract, so you have calldata that include the function selector and the parameters, this is memory that has a cost.
  • Then there is the part where you run the smart contract:
    • The evm will have to find your function in the contract, using the first 4 bytes of the calldata from earlier → this has a cost
    • The evm will have to read the testVal that is in the contract storage (this is something you can optimise once you have a better understanding of the evm) → this has a cost
    • The contract can prepare the memory (this has a cost) and trigger the transfer → this will forward a fixed amount of gas (2300) plus the actual cost of the call. You’ll pay for the call anyway, but part of the 2300 forwarded gas might not be used by the receiver.

So in the end, 2300 is was the receiver will have to react to the value being sent (using a receive() of fallback()), its not what you way to send the entire transaction that triggers the transfer.

Hopes this helps you understand things better

3 Likes

This was very helpful. If I want to dive deeper into this and better understand how all of this gas is being used, do you have some resources that you could recommend?

I wonder if this still applies. The linked article about transfer() and send() is from 3 years ago. In web3 time that's an eon. I'm looking for a way to know the gas cost inside the function itself and ran into this page.

1 Like

It does.

Account abstraction is a growing trend, and (as the article points out) using transfer() will potentially cause interraction with such accounts impossible.