Currently have this smart contract written in Remix.
I deploy the contract using the JavaScript VM on the topmost account
Then I switch accounts and then call the function like so:
To send 4 ether from the account to the smart contract. However, my transaction fails.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
- @title PayableContract
- @dev send ether to a smart contract
*/
contract PayableContract {
constructor() {}
event PaymentReceived(address indexed _sender, uint _before, uint _after);
function getContractBalance() public view returns (uint256) {
return address(this).balance;
}
function sendPaymentToContract(uint _amount) payable external
{
uint beforeBalance = getContractBalance();
payable(address(this)).transfer(_amount);
uint afterBalance = getContractBalance();
emit PaymentReceived(msg.sender, beforeBalance, afterBalance);
}
receive() payable external {}
}
After I call the function, I expect to see my balance go from 100 ether on the left part of the Remix IDE to 95.999... (100 ether - 4 - gas costs). However, the 4 ether does not get withdrawn, but only the gas costs.
I get that the transfer() function is bad for safety reasons. I just did it for clarity. I also understand that this is suboptimal and bad code since I can just use msg.value instead. However, I am wondering why exactly this doesn't work. It seems like it should.

transfer(), send(), call{value: _amount}(“”)with parameters to a function? Does this somehow relate tocalldata? – hacker Apr 07 '22 at 04:15Seeing that you asked the same question a year ago and you answering it now is so funny :) says a lot about if you stick with something long enough, you'll get it and more. Thanks for your detailed answers and comments!
– hacker Apr 07 '22 at 21:09