https://remix.ethereum.org/
Type the name Auction.sol and press Enter.
A "Auction.sol" tab appears on the right side. Paste in this code, as shown below.
The Auction contract takes bids, and when a higher bid comes in, it refunds the lower bid and accepts the higher bid.
The Attacker contract has a malicious fallback function that refuses to accept the refund, preventing any higher bid from being accepted.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract Auction {
address payable public currentLeader;
uint public highestBid;
event logBid(address _address, uint _bid);
function bid() public payable {
emit logBid(msg.sender, msg.value);
require(msg.value > highestBid);
require(currentLeader.send(highestBid)); // Refund the old leader, if it fails then revert
currentLeader = payable(msg.sender);
highestBid = msg.value;
}
}
contract Attacker {
Auction auction_address;
event LogFallback(uint count, uint balance);
constructor(address auction) payable { auction_address = Auction(auction); }
function win() public payable { auction_address.bid{value: msg.value}(); }
fallback () payable external {
revert();
}
function getBalance() public returns(uint) {
address _this = address(this);
return _this.balance;
}
}
On the left side, the third icon now has an orange "2" on it indicating two warnings, as shown below.
Use an Environment of "JavaScript VM (London)". If the account balances are not all 100 Ether, switch to "JavaScript VM (Berlin)" and back to "JavaScript VM (London)" to refresh the blockchain to its initial state.
Select a CONTRACT of "Auction - contracts/Auction.sol", outlined in blue in the image below.
Click the orange Deploy button.
In that line, click the copy icon, outlined in green in the image below, to copy that contract's address.
Select a CONTRACT of "Attacker - contracts/Auction.sol", outlined in red in the image below.
Paste the address into the field next to the Deploy button.
Click the red Deploy button.
At the lower left, click the > next to "AUCTION" to expand that section, as shown below.
At the top left, enter a VALUE of "1 ether", outlined in green in the image below.
Notice the first few characters in the current ACCOUNT number, outlined in red in the image below. In that image, the account number begins with 5B3. At the lower left, click the red bid button.
At the lower left, click the blue-gray currentLeader button. The current leader is the ACCOUNT number you noted previously.
At the lower left, click the blue-gray highestBid button. The highest bid is 1000000000000000000 wei, or 1 Ether, as shown below.
At the top left, notice that this account balance has fallen to approximately 99 ether, outlined in red in the image below.
At the top left, enter a VALUE of "2 ether", outlined in green in the image below.
At the lower left, click the red bid button.
At the top left, click the drop-down arrow on the right side of the ACCOUNT field.
The first account now has approximately 100 ether, and the second account has approximately 98 ether, outlined in red in the image below.
The Ether previously bid has been returned, and only the Ether from the highest bid has been transferred to the Auction contract.
At the lower left, click the blue-gray currentLeader button. The current leader is the second ACCOUNT number.
At the lower left, click the blue-gray highestBid button. The highest bid is 2 Ether, as shown below.
At the top left, select the third ACCOUNT, which has a balance of 100 ether, outlined in red in the image below.
At the top left, enter a VALUE of "3 ether", outlined in green in the image below.
At the lower left, click the red win button.
The third ACCOUNT balance falls to approximately 97 ether, outlined in red in the image below.
At the lower left, click the blue-gray currentLeader button. The current leader is not the third ACCOUNT shown at the top left, it's the account number of the ATTACKER contract, outlined in blue in the image below.
At the lower left, click the blue-gray highestBid button. The highest bid is 3 Ether, as shown below.
C 354.1 Bidding Higher (10 pts)
To see the effect of the attack, at the top left, select the first ACCOUNT.At the top left, enter a VALUE of "4 ether", outlined in green in the image below.
At the lower left, click the red bid button.
The transaction fails, and the first account does not lose 4 ether.
The flag is covered by a green rectangle in the image below.
Fix
Removing the "require" from line 13, as shown below, stops the attack.
Solidity Security: Comprehensive list of known attack vectors and common anti-patterns
Solidity Top 10 Common Issues
Common attacks in Solidity and how to defend against them
Posted 5-19-2021
Explanation augmented 10-22-21
Environment updated to Javascript Vm (London) on 10-26-21
Fix added 10-27-21