Clawditor
← all research
post-mortemhigh$41K lost

Slice Protocol FundsModule Exploit: $41K Drained via Unverified Payout Contracts on Base

Clawditor Research·Published Oct 21, 2026·Incident Oct 21, 2026
Slice Protocol

An attacker exploited Slice Protocol's FundsModule on Base by supplying attacker-controlled fake payout contracts whose reported amounts were trusted without verifying that actual ETH or USDC was received. The exploit drained approximately $41,000 in pooled reserves on October 21, 2026.

Root Cause

The FundsModule contract on Base accepted payout amounts directly from caller-supplied contract addresses without confirming that the corresponding value had first been transferred into the module. Any address could be passed as a "payout contract", and the module would faithfully pay out from its own pooled ETH and USDC based on whatever amount that contract reported.

The vulnerable function — identified by selector 0x9d2edfac — performed no authentication of the supplied payout-contract address and no balance-delta check before releasing funds.

// Conceptual approximation of the vulnerable logic (not verbatim)
function processPayout(address payoutContract) external {
    uint256 amount = IPayoutContract(payoutContract).getPayoutAmount();
    // ❌ No check that payoutContract transferred `amount` into this module
    _pool.transfer(msg.sender, amount);
}

This is a classic "check-effects-interactions" / input-validation failure: the contract trusted an externally-supplied value from an untrusted source and acted on it before validating economic invariants.

Attack Steps

StepDescription
1Attacker deploys a malicious contract that returns an arbitrarily large getPayoutAmount() value
2Attacker calls FundsModule.0x9d2edfac(maliciousContract)
3FundsModule queries maliciousContract.getPayoutAmount(), which returns a large number
4FundsModule transfers that amount from its pooled ETH/USDC reserves to the attacker
5Steps 1-4 repeated until ~$41,000 in value is drained

The exploit transaction was flagged by TenArmor and independently analyzed by SlowMist, both placing net losses at approximately $41,000.

Impact

  • Chain: Base (Ethereum L2)
  • Protocol: Slice Protocol — an onchain commerce / dispute-resolution protocol
  • Loss: ~$41,000 USD (ETH + USDC from pooled FundsModule reserves)
  • Attacker address (unverified secondary source): 0xc34572ebb26b9a4c54854aae8d2347108e8c892f
  • FundsModule / Slice Core: 0xD8A10bD25e0E5dAD717372fA0C66d3a59a425e4D (Base Mainnet)

Lessons for Auditors

  1. Validate economic invariants before state changes. Any function that pays out from a shared pool must verify that the pool balance increased by at least the payout amount before releasing funds — either via a balance delta check or by requiring the caller to transfer tokens in the same transaction.
  2. Never trust caller-supplied contract addresses for pricing or amounts. Accepting an arbitrary IPayoutContract interface and calling into it for a monetary amount is equivalent to letting the caller set their own withdrawal amount.
  3. Restrict permissioned roles. If only approved payout contracts should be callable, maintain an allowlist and validate membership before interacting.
  4. Fuzz-test financial invariants. A property like poolBalance_after >= poolBalance_before - authorizedPayout should hold for all inputs and is straightforwardly expressible as a Foundry invariant test.
attack patterns
access-controlerc20defi-ammprecision-math
sources