> 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/novacont-docs/korean/undefined-5/novacont.md).

# NovaCont 보안 검토

**범위**

* NovaCont.sol
* NovaJury.sol

**방법론**

* 정적 분석: Slither v0.11.5, 101개 탐지기, 두 번의 별도 컴파일 패스에서 실행.
* 모든 Medium 이상 발견 사항은 소스 코드에 대해 수동으로 검증되었습니다. 정적 분석이 관련 컨텍스트를 놓친 경우는 아래 별도 섹션에서 문서화되고 정당화됩니다.

| 심각도             | 수량  | 참고                                                                                                                 |
| --------------- | --- | ------------------------------------------------------------------------------------------------------------------ |
| Critical / High | 0   | -                                                                                                                  |
| Medium (검증됨)    | 0   | 4개 후보 모두 아래에서 "검토 완료 및 악용 불가"로 종료, 정당화 포함                                                                          |
| Low             | 8   | Immutable 최적화 (2), 이벤트 발행 누락 (2), missing-zero-check (OZ 라이브러리 코드), solc 버전 고정, costly-loop, cyclomatic-complexity |
| Informational   | 110 | 명명 규칙 (\~90), assembly/low-level-calls (OZ 라이브러리 코드), timestamp 사용, unused-state                                   |

**발견 사항: 검토 및 악용 불가 판정**

Slither가 표시하고 수동 검토 후 종료된 네 가지 발견 사항:

**오라클 라운드 검증 (unused-return)**

Slither는 "feed.latestRoundData()"의 반환 값 일부가 사용되지 않음을 표시했습니다. 코드 검토에서 "getLatestTokenUSDPrice"가 이미 "updatedAt" 신선도 검사와 "answeredInRound >= roundId" 오래된 라운드 검사를 모두 구현하고 있음을 확인했습니다. 이 발견은 Slither가 부분 튜플 폐기 패턴("startedAt" 필드, "None"으로 남겨둠)에서 오탐을 생성한 것에서 비롯됩니다.

**교차 함수 재진입 (reentrancy-eth, reentrancy-no-eth)**

"createContract", "disputeWork", "joinJury" 및 "payCounterFee"는 모두 "nonReentrant" 수정자를 포함합니다. OpenZeppelin의 "ReentrancyGuard"가 단일 계약 수준 잠금을 사용하므로 하나가 실행되는 동안 다른 "nonReentrant" 함수에 대한 진입이 차단됩니다. "disputeWork"에서 외부 "createCase" 호출 후 "dd.linkedCaseId"에 대한 쓰기는 Slither가 checks-effects-interactions 위반으로 표시하는 패턴이지만, 활성 잠금은 이 시나리오에서의 재진입을 사실상 불가능하게 만듭니다.

**초기화되지 않은 로컬 변수 (\_assignJurors.selected, \_processJurorOutcomes.voters)**

"\_assignJurors"는 루프 끝에서 "require(pickedCount == JURORS\_PER\_CASE, "Not enough eligible jurors")"로 보호됩니다. 풀에 충분한 적격 배심원이 없으면 함수가 완전히 되돌아갑니다. 부분적으로 채워진 배열은 절대 반환될 수 없습니다. "\_processJurorOutcomes"는 "voters" 배열의 채워지지 않은 부분에 접근하지 않습니다. 루프 경계가 "voterCount"에 의해 엄격하게 정의되기 때문입니다. "address(0)" 슬롯은 절대 처리되지 않습니다.

**나눗셈 후 곱셈 (cancelContract, computeDisputeFeePerParty)**

두 위치 모두에서 나눗셈이 곱셈 전에 발생합니다. 영향받는 금액의 크기는 이더리움 측에서 약 1 wei(\~$0.000000000003), 오라클 계산에서 사용하는 8자리 소수점 가격 형식에서 약 1 단위($0.000000005)입니다. 실제로 이것이 수백만 번 발생해야 어떤 사용자나 프로토콜이 측정 가능한 손실을 경험할 수 있습니다. 자금 안전이나 자금 잠금에는 영향이 없습니다.

**낮은 심각도**

| 발견                                                | 권장 사항                                         |
| ------------------------------------------------- | --------------------------------------------- |
| usdtToken/usdt는 immutable일 수 있음                   | 생성자에서 한 번만 설정되면 immutable로 표시하여 가스를 절약, 단점 없음 |
| setJuryContract, setNovaContAddress가 이벤트를 발행하지 않음 | 투명성을 위해 이벤트를 추가해야 함                           |
| USDT\_DECIMALS가 사용되지 않음                           | 죽은 코드, 제거해야 함                                 |
| replaceInactiveJuror의 순환 복잡도가 높음                  | 기능적 버그는 아니지만 유지보수성과 감사 가능성을 위해 하위 함수로 분할 권장   |
| solc ^0.8.20에 알려진 컴파일러 버그 포함                      | 프로젝트 자체에서 assembly/verbatim 사용 없음             |

**결론**

정적 분석은 코드베이스에서 **Critical 또는 High 심각도 발견 사항을 발견하지 못했습니다**. 4개의 Medium 후보 모두 수동 검토 후 "악용 불가"로 종료되었으며, 위에 정당화가 문서화되어 있습니다. 나머지 발견 사항은 가스 최적화, 코드 스타일 또는 이미 알려지고 수용된 설계 결정입니다. 이 결과는 독립적인 제3자 감사를 대체하지 않지만 코드베이스의 현재 성숙도에 대한 긍정적인 신호입니다.
