# Multiples initializations of JBTiered721Delegate

JBTiered721Delegate.initialize only checks store==address(0), letting an attacker front-run initialization with empty params, seize ownership, and manipulate creditsOf via didPay.

- Payout: Contest reward
- Severity: medium
- Program: Juicebox
- Credited: 0x1f8b
- Disclosed: 2023-01-09
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-10-juicebox-findings/issues/24
- Library page: https://bugbountylibrary.com/r/c4%3A2022-10-juicebox%3AM-01
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:race-window technique:source-review vuln:access-control vuln:business-logic

**Target:** JBTiered721Delegate NFT rewards contract initialize()
**Root cause:** initialize() guards re-initialization only via store==address(0) and permits empty _baseUri/_contractUri/tiers/flags, so a first caller can initialize with a zero store and take ownership before the legitimate deployer.
**Steps:**
1. Call `initialize(projectId, directory, name, symbol, fundingCycleStore, "", address(0), "", pricing, IJBTiered721DelegateStore(address(0)), flags)` with empty tiers and all-false flags
2. Ownership transfers to attacker via `_transferOwnership(msg.sender)`
3. Call `didPay` with fabricated data to inflate `creditsOf` for arbitrary addresses without touching store
4. Call `initialize` again with a real non-zero `_store` so the project proceeds as if nothing happened
**How found:** Code review of initialize() noting the only re-init guard is store==address(0) and that empty optional params let the call succeed without reverting, enabling a first-caller ownership grab.
**Exploitation:** Attacker front-runs the legitimate initialization with a zero-store, empty-parameter call to become owner, then abuses didPay to manipulate creditsOf, then re-initializes with a valid store so the project continues normally while credits are already inflated.
**Escalation:** Re-initialization with a valid store hides the manipulation, making the tampered creditsOf persist unnoticed.
**Insight:** When an initializer's only replay guard is a single storage slot being zero, check whether all other params can be empty so an attacker can be the first caller, take ownership, and later re-initialize legitimately to mask state tampering.
