# Self-delgated users can have their delegation unknowingly hijacked during crowdfunding

In PartyDAO crowdfund, anyone can contribute 1 wei on behalf of a self-delegated user with themselves as delegate, hijacking that user's voting power.

- Payout: Contest reward
- Severity: high
- Program: PartyDAO
- Credited: 0x52
- Disclosed: 2023-06-23
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-04-party-findings/issues/38
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-01
- Tags: domain:web3 kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** PartyGovernance / ETHCrowdfundBase contribution and delegation logic
**Root cause:** _processContribution lets any caller set a contributor's delegate when oldDelegate is zero, but self-delegation is stored as address(0), so a third party's contribution overwrites the self-delegation.
**Steps:**
1. User A contributes to ReraiseETHCrowdfund with `delegate == address(0)` to self-delegate; delegationsByContributor[A] stays address(0).
2. Attacker calls contribute on behalf of A with `delegate == attacker` and amount 1 (>= minContribution).
3. In _processContribution, msg.sender != contributor but oldDelegate == address(0), so delegationsByContributor[A] = attacker.
4. When crowdfund succeeds and NFTs are claimed, A's voting power is delegated to attacker.
**How found:** Code reading of _adjustVotingPower showing self-delegation is represented as address(0), combined with _processContribution's guard `oldDelegate == address(0)` allowing third-party delegate overwrite.
**Exploitation:** Attacker spends minContribution (e.g. 1 wei) contributing on behalf of a self-delegated victim, setting themselves as delegate; after the crowdfund succeeds, victim's newly minted party NFT votes are controlled by attacker.
**Escalation:** ReraiseETHCrowdfund defers NFT minting until crowdfund success, so attacker captures all of the victim's newly minted votes rather than just current power.
**Insight:** When a sentinel value (address(0)) doubles as 'unset' and 'self', any guard checking `== address(0)` to mean 'not yet delegated' can be bypassed by users who intentionally chose that sentinel; trace how sentinel semantics interact across functions.
