# Creator of one vesting plan can affect vesting plans created by other users.

VestingDeployer maps owner=>token instead of token=>owner, letting any token owner create/transfer vestings on another owner's plan, pulling funds from the wrong issuer.

- Payout: Contest reward
- Severity: medium
- Program: SecondSwap
- Credited: sl1
- Disclosed: 2025-02-18
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-12-secondswap#m-04
- Library page: https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-04
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** SecondSwap_VestingDeployer / SecondSwap_StepVesting Solidity contracts
**Root cause:** setTokenOwner stores _tokenOwner[owner]=token (owner=>token) rather than token=>owner, so multiple owners can map to the same token; createVesting/transferVesting only check _tokenOwner[msg.sender]==token, not that msg.sender is the plan's actual creator.
**Steps:**
1. Admin calls `setTokenOwner(token, ownerA)` and `setTokenOwner(token, ownerB)` — both succeed since mapping is owner=>token.
2. ownerA creates vesting plan A for token; ownerB creates plan B for same token.
3. ownerB calls `createVesting(...)` targeting plan A's StepVesting address; require `_tokenOwner[msg.sender]==token` passes.
4. StepVesting._createVesting executes `token.safeTransferFrom(tokenIssuer, address(this), _totalAmount)` pulling funds from plan A's creator, not ownerB.
5. Same bypass applies to `transferVesting()` on another owner's plan.
**How found:** Code review of setTokenOwner noticed the mapping is keyed by owner instead of token, then traced createVesting/transferVesting checks and the downstream safeTransferFrom(tokenIssuer,...) to confirm the wrong party's funds are pulled.
**Exploitation:** A token owner (ownerB) calls createVesting/transferVesting against another owner's StepVesting contract for the same token; the check passes because both owners map to the token, and the StepVesting pulls tokens from the legitimate issuer (tokenIssuer) rather than the caller, mutating another plan and moving funds from the wrong party.
**Insight:** When auditing access-control mappings, check the key direction: an owner=>resource map permits many owners per resource, so any per-resource authorization check keyed on msg.sender silently authorizes all of them.
