# Possible token reentrancy in release() of BathBuddy.sol

BathBuddy.release() lacks a reentrancy guard; an ERC777-style callback token lets a malicious beneficiary re-enter and drain vested tokens before the vesting period ends.

- Payout: Contest reward
- Severity: medium
- Program: Rubicon
- Credited: kebabsec
- Disclosed: 2022-08-01
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-05-rubicon-findings/issues/283
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-rubicon%3AM-23
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:reentrancy

**Target:** BathBuddy.sol vesting release() function
**Root cause:** release() transfers tokens before updating the released-token counter array and has no nonReentrant/synchronized modifier, so a token callback can re-enter while the counter is still stale.
**Steps:**
1. Deploy malicious beneficiary contract B implementing tokensReceived() hook.
2. Call `release()` on BathBuddy with B as recipient; token transfer triggers B's tokensReceived().
3. Inside tokensReceived(), call `release()` again before the released counter is updated.
4. Repeat recursively until the full vested amount is withdrawn early.
**How found:** Code review of release() noting absence of the synchronized modifier used elsewhere and that the released counter is updated only after the token transfer, combined with knowledge of ERC777 transfer hooks.
**Exploitation:** Malicious beneficiary uses an ERC777-compatible (or attacker-controlled) bonus token whose transfer callback re-enters release() repeatedly, each time seeing released==0, extracting the vested amount without waiting for the vesting schedule.
**Insight:** When auditing vesting/streaming contracts, check whether the released/claimed accounting is updated after the external token transfer and whether the token set is attacker-influenceable (bonus/incentive tokens), enabling ERC777-style reentrancy even without a native ETH callback.
