cNGN issuer pause and proxy upgrade are absent from the documented trust assumptions
cNGN can be paused and upgraded by its issuer, but the specification does not list the issuer as a trusted party. Because every fund-moving path is a push transfer, a pause or blocklist can freeze disputed principal and seated jurors' stakes indefinitely.
Description
cNGN is issuer-controlled: it can be paused, and it sits behind an upgradeable proxy. docs/PROTOCOL_SPEC.md §4 lists the ERC-20 dependency as "Standard transfer/transferFrom; SafeERC20" with failure mode "Tx reverts", and §5 enumerates the trusted roles without including the token issuer — a party with more authority over user funds than any role the specification does list.
Every fund-moving path in the protocol is a push transfer. A pause or a targeted blocklist therefore converts the documented "tx reverts" into a permanent stall wherever the reverting call is the only exit from a state.
Vulnerable Scenario: The following steps illustrate the issue:
- A dispute reaches
Talliedwith rulingReleaseSeller. The three seated jurors each holdactiveAssignments == 1. - The issuer pauses cNGN, or upgrades the proxy to blocklist the seller's address for reasons unrelated to this deal.
- Any caller invokes
execute. The pool callsescrow.resolveDisputeByArbitrator(seller), which reachessafeTransfer(seller, ...)in_resolveDisputeFundsand reverts. - The entire
executetransaction reverts. The case staysTallied, the escrow staysDisputed, and the juror-release loop below the external call never runs. - Every subsequent
executefails identically. The jurors cannotunstake, becauseactiveAssignmentshas exactly one decrementer and it sits past the reverting call. - If the block was a targeted blocklist rather than a global pause, lifting the pause does not clear it. The only remaining exit is mutual agreement, which also requires a working transfer.
Impact
A party outside the protocol's stated trust boundary can freeze disputed principal indefinitely and, through the proxy, change token semantics under live escrows. Jurors seated on an affected case lose access to their entire stake with no administrative cure.
The product is presented as non-custodial; an undocumented issuer holding pause and upgrade authority is a material qualification of that claim, and users cannot weigh a risk that is not recorded.
Recommendation
Record the issuer's actual powers in docs/PROTOCOL_SPEC.md §5 and correct §4's failure mode from "tx reverts" to the stall behaviour above. This is the load-bearing part: a global pause halts every transfer, so no contract change can settle a deal while it is in force, and the only remedy available is that anyone relying on the protocol can see the dependency.
Release juror assignments independently of settlement success. execute performs the external settlement call before its juror-release loop, so a reverting transfer skips the release entirely and strands every seated stake with no administrative cure. Moving the release above the call, or recording a retryable settlement-failure state, removes that harm on its own and is much smaller than the change below.
Then make settlement pull-based: have execute record each party's entitlement and let each withdraw separately, so a single blocked recipient cannot hold the other party's funds and the case hostage. When making that change, compute sweepExcessTokens' escrowed balance from outstanding entitlements as well as from totalAmount - releasedAmount - abandonedAmount, otherwise a recorded award becomes sweepable surplus and the losing party can take the winner's entitlement.
Resolution
Fixed. Dispute settlement now records entitlements and parties withdraw, so an issuer pause no longer strands the case or its jurors. The remaining push-based exits and the assumption itself are documented in the specification.
Affected files
contracts/ArbitrationPool.sol#L957-L993contracts/Escrow.sol#L702-L766contracts/Escrow.sol#L411-L418docs/PROTOCOL_SPEC.md