Skip to content

09. King

r1oga edited this page Oct 28, 2022 · 1 revision

Target

Prevent losing kingship when submitting your contract instance.

Weakness

The contract uses transfer instead of a withdraw pattern to send Ether.

Solidity Concepts

  • Neither contracts nor “external accounts” are currently able to prevent that someone sends them Ether. Contracts can react on and reject a regular transfer
  • If a contract receives Ether (without a function being called), either the receive Ether or the fallback function is executed. If it does not have a receive nor a fallback function, the Ether will be rejected (by throwing an exception).

Hack

Upon submission, the level contract sends some ETH amount to the contract instance contract fallback to reclaim kingship. The fallback uses transfer to send the prize value to the current king which about to be replaced. Only then the king address is updated. If the current king is a contract without a fallback or receive function execution will fail before the king address can be updated.

  1. Deploy a malicious contract without neither a payable fallback nor a payable receive function
  2. Let this malicious contract become king by having it send Ether to the King contract
  3. Submit instance

Takeaways

  • Assume any external account or contract you don't know/own is potentially malicious
  • Never assume transactions to external contracts will be successful
  • Handle failed transactions on the client side in the event you do depend on transaction success to execute other core logic.

Especially when transferring ETH:

  • Be careful when using send(), transfer() or call{ value }(''). If using send() check returned value
  • Prefer a 'withdraw' pattern instead of having a contract directly send ETH
Clone this wiki locally