# _writeCheckpoint does not write to storage on same block

VoteEscrowDelegation._writeCheckpoint writes to a memory copy, so same-block redelegation is lost, letting attackers multiply delegation power.

- Payout: Contest reward
- Severity: high
- Program: Golom
- Credited: async
- Disclosed: 2023-04-05
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-07-golom-findings/issues/455
- Library page: https://bugbountylibrary.com/r/c4%3A2022-07-golom%3AH-07
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** VoteEscrowDelegation.sol checkpoint logic (Solidity)
**Root cause:** oldCheckpoint is declared as a memory struct, so assigning delegatedTokenIds mutates a copy and never persists to storage when overwriting a checkpoint in the same block.
**Steps:**
1. Call `delegate` for a tokenId, creating a checkpoint at block N.
2. In the same block, call `delegate` again for the same tokenId to a different target.
3. `_writeCheckpoint` hits `oldCheckpoint.fromBlock == block.number` branch and writes to `memory oldCheckpoint`, so the new delegation is not stored.
4. Only the first delegation persists; subsequent same-block changes are silently dropped.
**How found:** Code reading of `_writeCheckpoint`: noticed `Checkpoint memory oldCheckpoint` used in the same-block overwrite branch, meaning the assignment targets memory not storage.
**Exploitation:** Attacker uses a contract to call delegate-add and delegate-remove in the same transaction/block; the add persists but the removal is dropped, so the same token can be re-delegated repeatedly, endlessly multiplying delegation power.
**Escalation:** Chaining add+remove in one tx via a contract to repeatedly re-delegate the same token, amplifying voting/delegation weight.
**Insight:** In Solidity, structs read from storage into a `memory` local are copies; any branch that mutates a checkpoint for the current block must use a `storage` pointer or the write is silently lost. Audit same-block overwrite paths in checkpoint/voting code.
