# Conviction scoring fails to initialize and bootstrap

New users' conviction scores never initialize in ERC20ConvictionScore because numCheckpoints is zero, breaking FairSide's core conviction-scoring feature entirely.

- Payout: Audit contest
- Severity: high
- Program: FairSide
- Disclosed: 2021-07-07
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-05-fairside-findings/issues/26
- Library page: https://bugbountylibrary.com/r/c4%3A2021-05-fairside%3AH-01
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:solidity vuln:accounting-error vuln:business-logic

**Target:** ERC20ConvictionScore contract (_updateConvictionScore / _beforeTokenTransfer)
**Root cause:** _updateConvictionScore computes ts from numCheckpoints[user]; for a first-time recipient numCheckpoints is 0 so ts=0 and balance is 0, making convictionDelta=0 and skipping checkpoint creation, so no checkpoint is ever written.
**Steps:**
1. Alice transfers FSD to Bob for the first time, triggering `_beforeTokenTransfer(Alice, Bob, 100)` which calls `_updateConvictionScore(Bob, 100)`.
2. In `_updateConvictionScore`, `numCheckpoints[Bob]` is 0 (Line116), so `ts = 0` (Line120).
3. Bob's prior FSD balance is 0, so `convictionDelta = 0` (Line122).
4. Control does not pass Line129, so no new checkpoint is written and conviction score never initializes.
**How found:** Code review of the Compound-derived conviction scoring: noticed FairSide's time-based adaptation requires initialization that Compound's version doesn't, and traced the first-transfer path to see numCheckpoints stays zero.
**Insight:** When forking Compound-style checkpoint logic, check the first-write path: time-weighted adaptations need explicit initialization of numCheckpoints/ts that the original didn't require.

