Bitallx · Missing evidence
Syntax error
The reference repair with a syntax error injected.
The patched contract does not compile, so no test could run. A build failure is never read as a blocked exploit.
What ran, and what it said.
Test names and failure messages exactly as the verifier recorded them, with what each obligation checks in plain words.
Exploit
1 replay · profit over 2,000 USDT- –The DeFiHackLabs reproduction of the attack: not runThe contract did not compile.test/poc.t.sol:Bitallx_PoC:testExploit()
Security obligations
not run- –A batch whose total exceeds what was funded pays nothingtest/hidden/security.t.sol:Bitallx_Security:test_multi_element_over_request_pays_nothing()
- –The incident’s own shape pays nothingtest/hidden/security.t.sol:Bitallx_Security:test_single_element_over_request_from_fresh_payer_pays_nothing()
- –The sum is bounded, not just each elementtest/hidden/security.t.sol:Bitallx_Security:test_sum_over_funded_total_rejected_even_when_each_element_fits()
Legitimate use · behaviour
not run- –A funded batch payout pays everyone correctlytest/hidden/regression.t.sol:Bitallx_Regression:test_funded_batch_payout_distributes_correctly()
- –The patched code still reads the contract’s live storagetest/hidden/regression.t.sol:Bitallx_Regression:test_live_storage_still_readable()
- –The owner’s treasury sweep works, and only for the ownertest/hidden/regression.t.sol:Bitallx_Regression:test_owner_treasury_path_still_works()
- –An unfunded payer is refusedtest/hidden/regression.t.sol:Bitallx_Regression:test_payout_rejects_an_unfunded_payer()
- –The publisher can still pay a reward, within its limitstest/hidden/regression.t.sol:Bitallx_Regression:test_publisher_can_still_pay_a_reward()
Legitimate use · interface
not run- –Original functions still answertest/hidden/invariants_auto.t.sol:AutoInvariants:test_abi_selectors_dispatch()
- –Every original function is still in the dispatch tabletest/hidden/invariants_auto.t.sol:AutoInvariants:test_abi_selectors_preserved()
- –The patched contract has codetest/hidden/invariants_auto.t.sol:AutoInvariants:test_contract_has_code()
- –Guard: the selector check can say notest/hidden/invariants_auto.t.sol:AutoInvariants:test_selector_check_is_not_vacuous()
- –Guard: unknown calls are still rejectedtest/hidden/invariants_auto.t.sol:AutoInvariants:test_unknown_selector_is_rejected()
The patch
against the original source@@ -91,7 +91,19 @@9191 uint256 totalSendAmount9292 ) external {9393 require(wallet.length == amount.length, "The length of 2 arrays should be the same");94− 94+95+ // PATCH: bound the payout by what was actually funded. Every check below -- the96+ // allowance, the sender's balance, and the transferFrom that pulls money IN -- is97+ // against `totalSendAmount`, while the loop below paid out the caller-supplied98+ // `amount[]` with nothing tying the two together. Calling this with99+ // totalSendAmount = 0 and amount[0] = the contract's own balance therefore passed100+ // every check and paid the caller the contract's treasury.101+ uint256 requested = 0;102+ for (uint256 i = 0; i < amount.length; i++) {103+ requested += amount[i];104+ }105+ require(requested == totalSendAmount, "Payout total does not match the funded amount");106+95107 uint256 allowance = IBEP20(tokencontract).allowance(msg.sender, address(this));96108 require(allowance >= totalSendAmount, "Insufficient token allowance");97109 @@ -107,6 +119,7 @@107119 }108120109121 //FUNCTION TO USER CLAIM REWARD122+ this line is not solidity;110123 function claimReward(address wallet, uint256 amount) public onlyPublisher {111124 require(amount >= minimumClaimAmount, "Claim amount below minimum limit!");112125 require(amount <= maximumClaimAmount, "Claim amount exceeds maximum limit!");
Re-run this grade
offline · same inputsNeeds Foundry 1.7.1 with solc 0.8.30, 0.8.26 and 0.8.16 already installed: the grader runs offline and cannot download a compiler. Python 3.12 or later. Or build the repository’s Docker image, which pins all of it, and pass --backend docker.
$ git clone https://github.com/FarseenSh/evmpatch-env.git && cd evmpatch-env
$ git checkout 165c0ed
$ python -m evmpatch_env.sandbox tasks/bitallx_2025_05 \
--patch worked_example/bitallx_2025_05/controls/compile_failed/Token.sol \
--backend local --sha256Expected output: core 738590218e3547f507d00750ab23dbd503bc104884540beef00a325b0c971a8e and strict d0592c5c6fedf42bd2195a6a4b1c6d768a4b336d71103b7b8dc3f6a6f81aadb2.
To check a downloaded grade file instead: shasum -a 256 grade.strict.json prints the strict hash.
Control note
from the repositoryReference repair with a syntax error injected. A compile failure is never credited as a block.