The same voter attempts to commit more than once for the same proposal.
AlreadyCommitted
- voter record has
has_committed - commit requires
!vr.has_committed
tests/private-dao.ts
No duplicate commit effect observed.
A voter or keeper attempts to reveal the same vote twice.
AlreadyRevealed
- voter record has
has_revealed - reveal requires
!vr.has_revealed
tests/private-dao.tstests/full-flow-test.ts
No reveal replay path with duplicate tallying is observed.
A proposal is finalized twice.
AlreadyFinalized
- finalize requires
proposal.status == Voting
tests/full-flow-test.ts
No repeated finalize path advances state twice.
The same passed proposal is executed more than once.
AlreadyExecuted
- execute requires
!proposal.is_executed
tests/full-flow-test.ts
No replay path results in duplicated execution effects in current coverage.
The attacker resubmits the same instruction intent with the same signer but different DAO, treasury, proposal, voter record, or delegation account order/binding.
Seed or relationship constraint failure.
- proposal PDA bound to DAO
- voter record PDA bound to proposal + voter
- delegation PDA bound to proposal + delegator
- treasury PDA bound to DAO
tests/private-dao.tstests/full-flow-test.ts
No successful reordered-account replay is observed in the tested surfaces.
A replay substitutes a different signer while preserving a valid-looking account set.
Authorization or signer-role failure.
- reveal checks voter/keeper role
- delegated commit checks delegatee equality
- authority-only actions use
has_one = authority
tests/private-dao.ts
Finalize and execute are intentionally permissionless, so replay safety there depends on lifecycle and account binding rather than signer exclusivity.
A transaction is re-sent after the protocol state has already advanced.
The state transition should no longer be valid even if the transaction intent is repeated.
- lifecycle gating
AlreadyCommittedAlreadyRevealedAlreadyFinalizedAlreadyExecuted
tests/private-dao.tstests/full-flow-test.ts
No duplicate-signature-driven double effect is observed in protocol behavior.
An attacker reuses vote or delegation state created for Proposal A against Proposal B.
Seed mismatch or explicit proposal relation mismatch.
- vote PDA includes proposal key
- delegation PDA includes proposal key
- delegated commit checks
delegation.proposal == proposal.key()
tests/private-dao.ts
No cross-proposal replay effect is observed in current tests.
Current test-backed reasoning supports the following conclusion:
- no replayed commit path duplicates voting weight
- no replayed reveal path duplicates tally effects
- no replayed finalize path reopens or refinalizes proposals
- no replayed execute path duplicates treasury effects
The residual replay boundary is operational rather than protocol-internal:
- permissionless surfaces remain exposed to repeated submission attempts, but protocol state and account validation prevent those attempts from duplicating effects
- RPC behavior and transaction rebroadcasting remain environmental concerns, not currently observed protocol replay vulnerabilities