Reproduced Exploit

Basis MultiDistributor — unprotected minimum-distribution list growth

setMinimumDistribution is documented for trusted participants, but anyone can append token addresses. Repeated zero-minimum entries inflate every distribution loop and can eventually cause a gas-limit denial of service.

Jan 2022Otheraccess-control2 min read

Chain

Other

Category

access-control

Date

Jan 2022

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

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.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 16760-setminimumdistribution-is-not-protected-trailofbits-basis-pd. Standalone Foundry PoC and full write-up: 16760-setminimumdistribution-not-protected_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/access-control/missing-auth · vuln/dos/unbounded-loop

Reproduction: local synthetic Foundry reduction; the complete passing trace is in output.txt.

Key info#

FieldValue
LossAn arbitrary caller appends 32 entries, increasing distribution work from 1 to 33 iterations.
Vulnerable contractMultiDistributor.setMinimumDistribution in test/16760-setminimumdistribution-not-protected.sol
Attacker EOA0x1111111111111111111111111111111111111111
Attack contractExploit
Attack txLocal Foundry Exploit.run()
Chain · block · dateEthereum model · block 0 · synthetic
CompilerSolidity ^0.8.24
Bug classMissing authorization on unbounded list mutation

TL;DR#

setMinimumDistribution is documented for trusted participants, but anyone can append token addresses. Repeated zero-minimum entries inflate every distribution loop and can eventually cause a gas-limit denial of service.

Background#

The minimum-distribution threshold exists to prevent negligible entries. It is ineffective when untrusted callers can add entries without governance or owner authorization.

The vulnerable code#

SOLIDITY
function setMinimumDistribution(address token, uint256 tokenMinDistribution) external {
    if (tokenIdx[token] == 0) tokens.push(token);
    // @> VULN: intended trusted-participant operation has no access check.
    minDistribution[token] = tokenMinDistribution;
}

Root cause#

The mutator is public and unbounded while distribute iterates the entire tokens array. No role, allowlist, or cap protects the expensive state transition.

Preconditions#

  • setMinimumDistribution is externally callable.
  • Distribution operations iterate all registered tokens.
  • An attacker can submit repeated transactions (or a loop in one transaction).

Attack walkthrough#

  1. Add 32 unique token addresses with minimum distribution zero.
  2. Invoke distribute; it loops 33 entries instead of the baseline one.
  3. The passing trace records the enlarged loop at output.txt:4.

Diagrams#

flowchart LR A[Untrusted caller] -->|32 setter calls| L[Token list grows] L --> D[distribute loops every entry] D --> G[Gas cost / DoS pressure]

Remediation#

Restrict the setter to an owner, controller, or allowlist and cap the list length. Consider a mapping-based distribution registry or bounded iteration rather than an attacker-controlled array.

How to reproduce#

BASH
cd evm-hack-registry/16760-setminimumdistribution-not-protected_exp
forge test -vvvvv

Sources#

Reference: https://github.com/trailofbits/publications/blob/master/reviews/basis.pdf


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

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.