king의 자리를 탈환하고, 다른 유저가 king의 자리를 뺏지 못하도록 해라
pragma solidity ^0.8.0;
contract King {
address king;
uint256 public prize;
address public owner;
constructor() payable {
owner = msg.sender;
king = msg.sender;
prize = msg.value;
}
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
payable(king).transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
function _king() public view returns (address) {
return king;
}
}
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
payable(king).transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
receive() 가 동작하게 되면 이더를 기존 왕에게 전송하고 새로운 왕이 등록되는 방식이다
처음 문제를 생각했을 떄 “msg.value에 max값을 넣어 보내면 되지않을까?” 라는 생각을 하고 문제를 풀었는데, king을 탈환하는데는 성공했지만 msg.value >= prize 조건에 의해 다른 사람이 max 값을 보내면 똑같이 탈환당할 수 있었음..
흠…. 어캐 풀지????
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
payable(king).transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
0.01이더 보다 큰 금액을 전송하여 king 권한을 탈취한 후, receive() 함수가 동작할 떄 transfer 하는 과정에서 revert가 발생하면 king 권한 탈취를 막을 수 있다.
transfer 함수를 이용하여 이더를 전송할 떄 전송 받는 곳에서 receive or fallback 이 있어야 한다고 우리는 알고 있다. 이 점을 이용해 Attack 코드에 receive or fallback 코드를 넣지 않으면 transfer 하는 과정에서 자연스럽게 revert가 발생하여 다음 로직을 수행하지 않게 된다.
이를 이용 ㄱㄱㄱㄱ