who will pay the gas for the resultant transaction that will get created from that code?
The transfer()
function doesn't result in a transaction. It results in a message call inside the original transaction initiated by an external account. The blockchain will record a single transaction no matter how many transfer()
or call()
invocations there are in the code. The gas cost will be deducted from the external account that initiated the transaction.
I know it uses a gas limit of 2100, but what about gas price?
The gas price specified by the external account owner, who initiated the transaction, is used.
Also, does this gas come from the value passed in or from the contracts balance and the whole value will be transferred.
The gas cost will not be subtracted from the contract but instead the external account that initiated the transaction. The gas cost is added on top of the value passed in. The external account must have the balance greater or equal to value + gaslimit * gasprice
.
Just curious about the transfer() method in particular. As there is not a ton of documentation about its implementation as it differs from send(), that i could find.
When sending ether be aware of the relative tradeoffs between the use of someAddress.send()
, someAddress.transfer()
, and someAddress.call.value()()
:
someAddress.send()
and someAddress.transfer()
are considered safe against reentrancy. While these methods still trigger code execution, the called contract is only given a stipend of 2,300 gas which is currently only enough to log an event.
x.transfer(y)
is equivalent to require(x.send(y))
, it will automatically revert if the send fails.
someAddress.call.value(y)()
will send the provided ether and trigger code execution. The executed code is given all available gas for execution making this type of value transfer unsafe against reentrancy.
Using send()
or transfer()
will prevent reentrancy but it does so at the cost of being incompatible with any contract whose fallback function requires more than 2,300 gas. It is also possible to use someAddress.call.value(ethAmount).gas(gasAmount)()
to forward a custom amount of gas.
One pattern that attempts to balance this trade-off is to implement both a push and pull mechanism, using send()
or transfer()
for the push component and call.value()()
for the pull component.
It is worth pointing out that exclusive use of send()
or transfer()
for value transfers does not itself make a contract safe against reentrancy but only makes those specific value transfers safe against reentrancy.
Can read more here https://consensys.github.io/smart-contract-best-practices/recommendations/#be-aware-of-the-tradeoffs-between-send-transfer-and-callvalue
You can find more details in this answer https://ethereum.stackexchange.com/a/38642/18932