# 컨트랙트 배포

> NeuroChain에 WASM 컨트랙트 배포하기 — wasm32용 빌드, 배포 트랜잭션, 모든 검증자가 실행하는 VMGuardian 감사 게이트, 생성자와 initialize, 수수료, 제한, 배포 후 지속적 모니터링.

Source: https://docs.nro.world/ko/build/deploy

배포는 `neuro:system.deploy`로 보내는 평범한 서명 트랜잭션입니다. 모든 검증자가 합의 과정에서 [VMGuardian](/ko/ai/vmguardian)으로 바이트코드를 감사하며, 감사를 통과하지 못한 컨트랙트는 어디에도 생성되지 않습니다.

![배포 흐름: wasm32 컨트랙트를 빌드하고, 선택적으로 분석한 뒤, 배포 트랜잭션을 보냅니다. 각 검증자가 VMGuardian 게이트를 실행합니다. 위험 점수가 임계값 이상이면 수수료 없이 트랜잭션이 실패하고, 그렇지 않으면 컨트랙트가 생성되어 init export가 실행된 다음 init_args로 initialize가 실행됩니다](/diagrams/ko/deploy-flow.svg)

## 1. 빌드

컨트랙트는 `wasm32-unknown-unknown`용 `cdylib`로 컴파일된 `no_std` Rust이며, `env` 모듈에서 host 함수를 import합니다. 최신 Rust에서 링크되도록 `#[link(wasm_import_module = "env")]`로 선언하세요. 인터페이스와 전체 예제는 [NeuroWASM](/ko/neurowasm/#a-minimal-contract)을 참고하세요.

```toml
[lib]
crate-type = ["cdylib"]

[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
```

```bash
cargo build --release --target wasm32-unknown-unknown
od -An -tx1 -v target/wasm32-unknown-unknown/release/my_contract.wasm | tr -d ' \n' > my_contract.hex
```

hex는 `0061736d`(WASM 매직 넘버)로 시작해야 합니다. 바이트코드 최대 크기: **512 KiB**(`MAX_BYTECODE_SIZE`).

저장소의 동작 예제: `neurochain/contracts/nrc20`(대체 가능 토큰), `ncert`(NRC-721 방식의 보안 인증서), `dao`, `gov_dao`.

## 2. 보내기 전에 확인 <Badge type="tip" text="선택 사항" />

| 엔드포인트 | 얻는 것 |
|------------|---------|
| `POST /api/v1/contracts/analyze` `{ "bytecode_hex": "…" }` | `risk_score`, `security_score`, `ml_score`, `model`, `violations` — 게이트가 실행하는 것과 같은 분석 |
| `POST /api/v1/contracts/attest` `{ "bytecode_hex": "…" }` | 노드가 ML-DSA-65로 서명한 같은 결과로, 브라우저에서 검증 가능 |

웹 앱의 배포 페이지는 먼저 브라우저에서 분석을 실행한 다음, 노드에 서명된 증명을 요청합니다.

## 3. 배포 보내기

**SDK 사용**(권장):

```js
await nc.deployContract({
  wallet,
  bytecodeHex,
  name: 'MyToken',            // 고유한 컨트랙트 이름, 선택 사항
  description: '…',
  template: 'nrc20',          // 등록된 템플릿 id, 선택 사항
  initArgs: { … },            // initialize에 전달됨, 선택 사항; decimals는 숫자로
  gasPrice,
})
```

**직접 보내기** — `to: "neuro:system.deploy"`, `value: 0`, 그리고 `data`를 다음 JSON 문자열로 설정해 `POST /api/v1/transactions`를 호출합니다.

```json
{ "bytecode_hex": "0061736d…", "name": "MyToken", "description": "", "template": "", "init_args": { } }
```

서명은 다른 트랜잭션과 같습니다(`nc-tx-v2|from|neuro:system.deploy|0|nonce`).

노드는 `POST /api/v1/contracts/deploy`도 제공합니다(`owner`, `bytecode_hex` 또는 `base64_wasm`, 그리고 `neuro:system.deploy`에 대한 서명된 작업). 이 엔드포인트가 같은 트랜잭션을 대신 만들어 줍니다.

## 4. 모든 검증자가 하는 일 {#_4-what-every-validator-does}

1. **게이트.** 바이트코드를 디코딩하고 SHA3-256 해시를 조회합니다.
   - 화이트리스트에 있음(NRC-20 같은 공식 템플릿) → 보안 점수 100, 분석 없음;
   - 거버넌스로 게이트가 꺼짐(`deploy_security_enabled = 0`) → 중립 점수 70;
   - 그 외에는 VMGuardian `analyze_v2`를 실행합니다. `risk_score ≥ deploy_risk_threshold`(기본값 0.80)이면 트랜잭션은 **수수료 없이 실패**하고, 거부 내역이 규칙 위반과 함께 로그에 기록되며, `nc_deploy_rejected_total` 메트릭에 집계됩니다.
2. **과금** 10 000 가스 단위 × `gas_price`.
3. **생성** `neuro:<10 hex>.app`에 컨트랙트를 생성합니다 — `SHA3-256(owner ‖ nonce)`의 처음 5바이트. 다른 컨트랙트가 이미 사용 중인 컨트랙트 이름이면 배포가 실패합니다.
4. **생성자.** 모듈이 `init`을 export하면 배포의 스토리지로 한 번 실행됩니다.
5. **초기화.** `init_args`가 있으면 컨트랙트가 `{"function": "initialize", …init_args}`로 호출됩니다 — 인자는 JSON의 최상위 수준에 평탄화됩니다 — 이때 호출자는 여러분입니다.
6. **템플릿 수수료.** `template`이 수수료가 있는 등록된 템플릿을 가리키면, 그 수수료가 여러분에게서 템플릿 작성자에게 지급됩니다.

결과로 나온 **보안 점수**는 `100 − risk_score × 100`이며, 컨트랙트와 함께 저장됩니다.

## 수수료

| 항목 | 비용 |
|------|------|
| 배포 | 10 000 가스 단위 × `gas_price`(1 uNRO일 때: 0.01 NRO) |
| 게이트에서 거부됨 | 없음 |
| 템플릿 | 템플릿 자체 수수료(있는 경우) |

## 배포 후: 지속적 모니터링

각 노드는 배포된 컨트랙트를 20초마다 다시 감사합니다(`MONITOR_INTERVAL_SECS`). 컨트랙트 점수가 10점 이상 변하면(`MONITOR_SCORE_THRESHOLD`) — 예를 들어 모델이 업데이트된 후 — 합의를 통해 인증서 업데이트 트랜잭션이 발행됩니다. 인증서는 `GET /api/v1/certificates/contract/:address`에서 읽을 수 있습니다. [VMGuardian](/ko/ai/vmguardian)을 참고하세요.

## 문제 해결

| 오류 | 원인 |
|------|------|
| `Deploy rejected by VMGuardian: risk_score … >= threshold …` | 감사에서 위험한 패턴이 발견되었습니다. `analyze`가 목록을 보여 줍니다. |
| `gas_price … below block base_fee …` | `gasPrice`를 현재 기본 수수료보다 높이세요. |
| `Contract name '…' is already taken` | 다른 `name`을 선택하거나 비워 두세요. |
| 크기 오류 | 바이트코드가 512 KiB를 넘습니다 — `opt-level = "z"`와 LTO로 빌드하세요. |
