Reproduced Exploit
Primev — Overpayment to bidder in `slash` due to incorrect amount transfer
1. slash computes residualAmt = amt * residualBidPercentAfterDecay / 100%. 2. Provider stake is reduced by residualAmt + fee (correct). 3. Bidder is paid amt instead of residualAmt. 4. With 50% decay, bidder gets 1 ETH instead of 0.5 ETH — 0.5 ETH excess from the registry.
Chain
Other
Category
logic
Date
Nov 2024
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 46246-overpayment-to-bidder-in-slash-function-due-to-incorrect-amo. Standalone Foundry PoC and full write-up: 46246-overpayment-to-bidder-in-slash-function-due-to-incorrect-amo_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/wrong-transfer-amount · vuln/accounting/fee · vuln/logic/direct-drain
Reproduction: a self-contained Foundry PoC that compiles & runs in an isolated project with only
forge-std— no fork, no RPC, noanvil_state. Full trace: output.txt. PoC: test/46246-overpayment-to-bidder-in-slash-function-due-to-incorrect-amo_exp.sol.
AuditVault taxonomy: lang/solidity · platform/cantina · has/poc · severity/high · sector/staking · genome: wrong-condition · direct-drain · account-signer · fee-accounting · reward-accounting
Key info#
| Impact | HIGH — slash pays full amt to the bidder while only debiting residualAmt + fee from provider stake; excess drains registry ETH |
| Protocol | Primev — ProviderRegistry.slash |
| Vulnerable code | bidder.call{value: amt} should be residualAmt |
| Bug class | Wrong transfer amount after correct residual computation |
| Finding | Cantina — Primev · #46246 · reporter Nexarion |
| Report | Cantina Primev PDF |
| Source | AuditVault |
| Status | Audit finding. Reproduced here as a standalone local PoC. |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
slashcomputesresidualAmt = amt * residualBidPercentAfterDecay / 100%.- Provider stake is reduced by
residualAmt + fee(correct). - Bidder is paid
amtinstead ofresidualAmt. - With 50% decay, bidder gets 1 ETH instead of 0.5 ETH — 0.5 ETH excess from the registry.
The vulnerable code#
uint256 residualAmt = (amt * residualBidPercentAfterDecay) / ONE_HUNDRED_PERCENT;
// ... debit residualAmt + fee from providerStake ...
(bool ok, ) = bidder.call{value: amt}(""); // @> VULN: should be residualAmt
Fix: transfer residualAmt to the bidder.
Root cause#
Residual/decay accounting is applied to the provider debit but not to the bidder credit — asymmetric transfer.
Preconditions#
- Provider has stake ≥ slash amount.
- Caller is authorized preconf manager.
residualBidPercentAfterDecay < 100%.
Attack walkthrough#
- Provider stakes 2 ETH.
- Slash 1 ETH with 50% residual → residualAmt = 0.5 ETH.
- Bidder receives 1 ETH; provider loses only residual+fee.
- Registry ETH short by the excess payment.
Diagrams#
Impact#
Repeated slashes with decay drain the registry's ETH balance (other providers' stakes / protocol float).
Sources#
- AuditVault finding #46246
- Cantina Primev report
- Reduced source: Primev
ProviderRegistry.slash(Cantina competition codebase)
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 46246-overpayment-to-bidder-in-slash-function-due-to-incorrect-amo_exp (evm-hack-registry mirror).
- AuditVault finding: 46246-overpayment-to-bidder-in-slash-function-due-to-incorrect-amo.
Alerts & third-party analyses
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.