# SharedStake Insider Exploit Postmortem

SharedStake SmartTimelock's call() let the beneficiary approve itself to move all timelocked tokens, bypassing the release schedule and draining ~$40m.

- Payout: $5,000
- Severity: high
- Program: SharedStake
- Credited: Lucash-dev
- Disclosed: 2021-06-23
- Write-up quality: 7/10
- Original: https://immunefi.com/blog/bug-fix-reviews/sharedstake-insider-exploit-postmortem/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-sharedstake-insider-exploit-postmortem
- Tags: domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** SmartTimelock.sol timelock/vesting contract
**Root cause:** The call() method allowed the beneficiary to invoke arbitrary external contract methods with arbitrary data; the post-call balance check only verified the timelock's own balance didn't decrease, so an ERC20 approve() to the beneficiary passed the check while granting future transferFrom rights.
**Steps:**
1. Call `call(to=tokenAddress, value=0, data=abi.encodeWithSelector(ERC20.approve.selector, address(owner), balance))` as the beneficiary to approve yourself for the full token balance.
2. Call `transferFrom(timelock, beneficiary, balance)` on the token to move all timelocked funds out immediately, before the release schedule.
**How found:** Lucash-dev read SmartTimelock.sol and noticed the call() method permitted arbitrary external calls with arbitrary data, then reasoned that the post-call balance check could be bypassed by an approve() that doesn't change the timelock's balance in the same transaction.
**Exploitation:** The beneficiary (SharedStake core team) invoked call() to approve itself on the token contract, then used transferFrom to drain the timelocked funds; an insider allegedly executed this four times on mainnet for ~$500k, swapping some to USDC/vETH2 and staking the rest.
**Escalation:** Repeated across multiple timelocks (four mainnet transactions) and funds laundered into USDC, vETH2, and staking.
**Insight:** When a contract exposes an arbitrary-call primitive guarded only by a same-transaction balance check, look for state-changing token approvals (approve/permit) that grant future spending rights without moving funds now — the balance check passes but the allowance persists.
