# Builder can call Community.escrow again to reduce debt further using same signatures

Community.escrow lacked a nonce, letting a builder replay the same signed escrow message repeatedly to reduce their debt to zero.

- Payout: Contest reward
- Severity: high
- Program: Rigor Protocol
- Credited: sseefried
- Disclosed: 2022-09-12
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-08-rigor-findings/issues/161
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-rigor%3AH-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:business-logic vuln:signature-replay

**Target:** Community.sol escrow() debt-reduction function
**Root cause:** escrow() decodes _data and verifies signatures but includes no nonce, so a valid signed escrow message can be replayed indefinitely.
**Steps:**
1. Builder has $50,000 debt; lender, builder, escrow agent sign _data reducing debt by $5,000.
2. Call `Community.escrow(_communityID, _project, _data, _signature)`; debt drops to $45,000.
3. Replay the same `_data` and `_signature` 9 more times; debt reaches zero.
**How found:** Code reading of escrow() showed decoded fields lacked a nonce, unlike publishProject which uses one; recognized replay of signed messages.
**Exploitation:** Builder reuses the same signed escrow payload in repeated escrow() calls, each reducing debt by the signed amount until debt is fully cleared without paying cash.
**Insight:** When a signed off-chain message authorizes a state change, check whether the decoded struct carries a per-project nonce; compare against sibling functions that already use nonces to spot the omission.
