You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Dec 11, 2024. It is now read-only.
the King contract represents a simple ponzi where whoever sends the largest amount of ether (larger than the current prize value) becomes the new king. in this event, the previous king gets paid the new prize.
this contract is vulnerable because it trusts the external input of msg.value when running transfer(msg.value).
it assumes that the king is an EOA, which could also be a contract.
our goal is to explore this vulnerability to not let anyone else become the king.
king is initially the person who deployed the contract and sets prize (the current value to be bet by someone to become king). the only requirement is that the ether sent to the contract must be larger than prize.
following we have the receive() function and a getter for king. to become a king one needs to either be owner or send a value for prize larger than its current. since we didn't deploy the contract, the first option is not available:
looking at receive(), we see that after we send enough prize, a payable function is triggered to pay prize to the previous king.
it uses transfer(address), which sends the amount of wei to address, throwing an error on failure.
sending ether to EOAs is usually performed via transfer() method, but remember that there are a few ways of performing external calls in solidity.
the send() function also consumes 2300 gas, but returns a bool.
finally, the call() function and the CALL opcode can be directly employed, forwarding all gas and returning a bool.
in addition, note that this contract has no error handling, so an obvious security issue is unchecked call return values.
in other words, each time a contract sends ether to another, it depends on the other contract’s code to handle the transaction and determine its success.
for instance, the contract might not have a payablefallback(), or have a malicious fallback() or payable function.
if the new king is a contract address instead of a EOA, it could redirect transfer() and revert its transaction, skipping the execution of the next lines:
king = msg.sender;
prize = msg.value;
solution
we write our exploit at src/09/KingExploit.sol. note that the fallback() is optional for winning the challenge, but we add it here to make very clear the point that no eth should be sent (i.e., there won't be a new king):