> For the complete documentation index, see [llms.txt](https://novacont.gitbook.io/nova-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://novacont.gitbook.io/nova-docs/security-and-developers/security-model.md).

# Security Model

### Pull Payment Architecture

NovaCont does not push funds to recipients. Instead, all fund distributions are recorded as credits in a `pendingWithdrawals` mapping, and recipients initiate their own withdrawals explicitly.

This is a deliberate security choice. Push-based payment systems (where the contract sends ETH directly to recipient addresses) are vulnerable to reentrancy attacks if the recipient is a malicious contract that re-enters the sending function before state is updated. By separating the crediting step from the withdrawal step, NovaCont eliminates this attack surface entirely.

Every withdrawal function is additionally protected by the `nonReentrant` modifier as a secondary layer of defense.

<figure><img src="/files/Eb0KqnBaXRDzd8QWaNwA" alt=""><figcaption></figcaption></figure>

### Reentrancy Protection

All functions that interact with ETH or ERC-20 balances are marked with the `nonReentrant` modifier from OpenZeppelin's ReentrancyGuard. This modifier uses a lock variable to ensure that no function in the contract can be called recursively. If a reentrant call is attempted, the transaction reverts immediately.

ERC-20 transfers use OpenZeppelin's `SafeERC20` wrapper, which handles non-standard token implementations gracefully and reverts on failed transfers rather than silently succeeding with a false return value.

### Access Control

**Owner**: The deploying address. Can pause the contract, update fees, register tokens, set price feeds, and manage the resolver and jury system configuration. Ownership transfers require two steps to prevent accidental transfers.

**Resolver**: A designated address authorized to settle disputes in administered mode. Defaults to the owner at deployment. Can be changed by the owner at any time. When the jury system is activated, the resolver is automatically set to the NovaJury contract address.

**onlyJuryContract**: A modifier restricting certain settlement functions exclusively to the registered NovaJury address. Cannot be called by the owner, resolver, or any external actor.

**Party-based access**: Most workflow functions are restricted to the specific addresses registered as client or provider at contract creation. No other address can accept, deliver, approve, dispute, or cancel on behalf of a party.

### Emergency Pause

The contract owner can invoke `pause()` at any time to halt all state-modifying operations. This is intended as an emergency measure in the event of a discovered vulnerability or an ongoing attack.

When paused:

* No new contracts can be created
* No state transitions can be triggered
* Withdrawals from `pendingWithdrawals` remain fully functional. Users can always reclaim credited funds

The contract can be unpaused by the owner at any time via `unpause()`.

### Known Limitations and Assumptions

**Pseudo-random juror selection:** Juror assignment uses an on-chain pseudo-random mechanism based on `blockhash`, `prevrandao`, `gasleft`, and an incrementing nonce. This is not cryptographically secure randomness. A validator with sufficient control over block production could theoretically influence juror selection outcomes. For the current scale of the protocol this risk is considered acceptable, but it is acknowledged as a limitation. Integration with a verifiable randomness solution such as Chainlink VRF is a potential future upgrade.

**Oracle dependency:** NovaCont relies on Chainlink price feeds for deposit calculations. Extended oracle downtime or a compromised feed could affect the accuracy of USD-to-token conversions. The 24-hour staleness check mitigates this risk but does not eliminate it entirely.

**No appeal mechanism:** Dispute verdicts (whether issued by the administrator or the jury) are final and irreversible once executed on-chain. There is no appeals process. Users should approach disputes with complete and well-organized evidence from the outset.

**Off-chain evidence:** Evidence URIs point to off-chain resources. NovaCont cannot guarantee the permanence or integrity of these resources. A provider or client who submits a link that later becomes inaccessible bears the consequences of that inaccessibility in any dispute evaluation.

### Attack Surface Analysis

Understanding where a smart contract is most vulnerable is as important as understanding what it does. The following is an honest assessment of NovaCont's primary attack surfaces and the mitigations in place for each.

#### cancelContract - Owner Access Path

The `cancelContract` function contains an access control path that deserves explicit documentation. The require statement reads:

```
require(canCancel || msg.sender == owner(), "Cannot cancel");
```

This means the contract owner can cancel any agreement at any time, regardless of state or party consent. This is an intentional administrative capability — it exists to handle edge cases such as sanctioned addresses, legal obligations, or critical bugs that require manual intervention. However, it represents a centralization assumption that users should be aware of. Owner-initiated cancellations always result in a full refund to the client with no penalty applied.

#### settleDispute — Split Validation

The administrator settlement function enforces a strict invariant:

```
require(_clientRefund + _grossProviderPayment == c.totalLocked)
```

This ensures that the total distributed amount always equals the total locked amount — no funds can be created or destroyed during settlement. Any resolution that does not account for every wei of the locked balance will revert. This is a critical correctness check that prevents both accidental and malicious fund misallocation during dispute resolution.

#### claimTimeout — Time Dependency

The timeout mechanism relies on `block.timestamp` for its 7-day window check. Miners and validators have a small degree of influence over block timestamps — typically within a range of a few seconds to a few minutes. This is not a meaningful attack vector for a 7-day window, but it is worth noting as a general property of timestamp-dependent logic. NovaCont does not use timestamps for anything where second-level precision is security-critical.

### Integer Overflow and Underflow

NovaCont is compiled with Solidity 0.8.20, which introduced native overflow and underflow protection at the language level. Every arithmetic operation in the contract will revert automatically if the result exceeds the bounds of the data type. No explicit SafeMath library is required.

This means operations such as fee calculations, deposit multiplications, and basis point conversions are all protected against overflow by default. The one area where this matters most is the 1.25x deposit calculation:

solidity

```solidity
uint256 requiredDeposit = (agreedPrice * 125) / 100;
```

If `agreedPrice` is extremely large, the intermediate result of `agreedPrice * 125` could theoretically overflow a `uint256`. In practice, this would require an agreed price on the order of 10^75 wei — a value so astronomically large that it could never represent a real transaction. The overflow protection is nonetheless present and would cause the transaction to revert safely.

### Front-Running Considerations

Front-running occurs when a malicious actor observes a pending transaction in the mempool and submits their own transaction with a higher gas fee to be processed first.

**Oracle price front-running:** When a client calls `createContract`, the ETH/USD price is fetched from Chainlink at that exact block. A sophisticated actor could theoretically observe a pending `createContract` transaction, predict the oracle price at the time of inclusion, and craft an attack around it. However, there is no meaningful exploit available here. The client is the one locking their own funds, and the oracle price only affects how much ETH they must send, not whether funds can be stolen.

**Dispute front-running:** A provider who sees a client's `disputeWork` transaction in the mempool cannot front-run it in a way that benefits them. The contract state only allows one dispute to be opened, and the dispute can only be opened while in the Delivered state. There is no race condition that could allow a provider to preempt a legitimate dispute.

### ERC-20 Edge Cases

**Fee-on-transfer tokens:** As noted above, tokens that deduct a percentage on transfer are not compatible with NovaCont. The contract assumes that the amount declared in `erc20DepositAmount` equals the amount actually received. Any discrepancy would leave the contract with less collateral than the recorded `totalLocked` value, creating an accounting error that could affect fund distribution.

**Approval race condition:** The standard ERC-20 `approve` function is technically vulnerable to a race condition where a spender can observe an approval being changed and front-run it to spend both the old and new allowance. NovaCont mitigates this by using `safeTransferFrom` via `SafeERC20`, and users are advised to set allowances to zero before increasing them if they are interacting with the contracts directly rather than through the application interface.

**Non-standard return values:** Some ERC-20 tokens do not return a boolean value from `transfer` and `transferFrom`, contrary to the EIP-20 specification. OpenZeppelin's `SafeERC20` wrapper handles this gracefully by checking return data length and treating missing return values as success only when the call itself did not revert. This ensures compatibility with a broader range of token implementations.

### Centralization Risks

NovaCont is not fully trustless in its current form. The following owner capabilities represent centralization assumptions that users should evaluate before using the protocol:

| Capability                     | Function                                          | Impact                                                                                          |
| ------------------------------ | ------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| Pause all operations           | `pause()`                                         | Halts contract creation and state transitions. Withdrawals unaffected.                          |
| Cancel any contract            | `cancelContract()`                                | Owner can force-cancel any agreement. Client always refunded in full.                           |
| Change platform fee            | `setPlatformFee()`                                | Fee can be changed up to a maximum of 10%. Affects future settlements only.                     |
| Change resolver                | `setResolver()`                                   | Can redirect dispute resolution authority to any address.                                       |
| Activate or deactivate jury    | `activateJurySystem()` / `deactivateJurySystem()` | Can switch between administered and decentralized dispute modes at any time.                    |
| Add or remove supported tokens | `addSupportedToken()` / `removeSupportedToken()`  | Can expand or restrict payment options. Cannot remove ETH or USDT.                              |
| Update price feeds             | `setPriceFeed()`                                  | Can change the oracle source for any token. A malicious feed could affect deposit calculations. |

These capabilities are necessary for the protocol to operate safely during its current stage of development. As the protocol matures, the intention is to progressively reduce owner authority through timelocks, multisig requirements, and eventually on-chain governance. Any changes to the owner privilege model will be documented and announced in advance.

### Audit Status

NovaCont has not yet undergone a formal third-party security audit. The contracts have been developed following established security best practices and make extensive use of audited OpenZeppelin libraries, but the absence of a formal audit means that unknown vulnerabilities may exist.

Users should treat the protocol as experimental until a formal audit has been completed and its findings published. Do not deposit funds you cannot afford to lose.

An audit engagement is planned as part of the protocol's path to mainnet deployment. Audit reports will be published in full and linked from this documentation when available.
