# Node.js Contract 구조 리팩토링 — 수정 보고서

**작업일**: 2026-03-16
**기준 문서**: `NODEJS_CONTRACT_REFACTOR_GUIDE.md`
**빌드 결과**: `pnpm run build` — 5개 패키지 모두 SUCCESS

---

## 수정 결과 요약

| 항목 | 상태 | 변경 파일 |
|------|------|----------|
| ContractDeployService → ContractManagementService 리네임 | ✅ | 삭제 1 + 신규 1 |
| deployContract() → registerContract() 전환 | ✅ | 1 |
| addRelayer() TVM 분기 | ✅ | 2 (서비스 + 라우트) |
| removeRelayer() TVM 분기 | ✅ | 2 (서비스 + 라우트) |
| pauseContract() TVM 분기 | ✅ | 1 |
| unpauseContract() TVM 분기 | ✅ | 1 |
| getContractStatus() TVM 분기 | ✅ | 1 |
| system-admin.ts: deploy → register | ✅ | 1 |
| CollectionPoller: executeTransfer TVM 분기 | ✅ | 1 |
| WithdrawalPoller: executeTransfer TVM 분기 | ✅ | 1 |
| BYTECODE export 삭제 | ✅ | 2 |
| TronZap estimateEnergy from_address 수정 | ✅ | 2 |
| tronweb 의존성 추가 | ✅ | 2 (package.json) |

---

## 핵심 변경

### 1. deploy → register 전환

**이전**: Node.js가 ethers.js `ContractFactory`로 직접 배포 (EVM only)
**이후**: 운영자가 Hardhat/Tronbox로 수동 배포 후, Admin Console에서 컨트랙트 등록

```
POST /api/admin/contract/register
{
  networkId, contractAddress, deployTxHash, ownerAddressId, abiVersion?
}
```

등록 시 온체인 owner 검증 (EVM: `contract.owner()`, TVM: `contract.owner().call()`)

### 2. 모든 온체인 인터랙션에 EVM/TVM 분기 추가

| 함수 | EVM | TVM |
|------|-----|-----|
| `addRelayer()` | ethers.js `contract.addRelayer()` + `tx.wait()` | tronweb `contract.addRelayer().send()` |
| `removeRelayer()` | 동일 패턴 | 동일 패턴 |
| `pauseContract()` | ethers.js `contract.pause()` | tronweb `contract.pause().send()` |
| `unpauseContract()` | ethers.js `contract.unpause()` | tronweb `contract.unpause().send()` |
| `getContractStatus()` | ethers.js `contract.owner()` 등 | tronweb `contract.owner().call()` 등 |
| `executeTransfer()` (Poller) | ethers.js + nonce | tronweb + feeLimit |

### 3. TronZap estimateEnergy from_address 수정

CollectionPoller/WithdrawalPoller 모두 `from_address`를 HOT/MASTER 지갑 → **Relayer EOA**로 변경. TVM에서 에너지는 `tx.origin` (= Relayer)이 소비하므로.

---

## 변경 파일 목록

| 패키지 | 파일 | 유형 |
|--------|------|------|
| common | `src/contracts/CryptoRelayerAbi.ts` | BYTECODE 유지 (export만 제거) |
| common | `src/contracts/index.ts` | BYTECODE re-export 삭제 |
| common | `src/index.ts` | BYTECODE export 삭제 |
| blockchain-api | `src/services/ContractDeployService.ts` | **삭제** |
| blockchain-api | `src/services/ContractManagementService.ts` | **신규** |
| blockchain-api | `src/routes/system-admin.ts` | deploy → register 라우트 |
| blockchain-api | `package.json` | tronweb 의존성 추가 |
| relayer-api | `src/routes/relayer.ts` | register/unregister TVM 분기 |
| relayer-api | `src/services/CollectionPoller.ts` | executeTransfer TVM + estimateEnergy fix |
| relayer-api | `src/services/WithdrawalPoller.ts` | executeTransfer TVM + estimateEnergy fix |
| relayer-api | `package.json` | tronweb 의존성 추가 |

---

## API 변경

| 변경 | 이전 | 이후 |
|------|------|------|
| 엔드포인트 | `POST /api/admin/contract/deploy` | `POST /api/admin/contract/register` |
| Request | `{ networkId }` | `{ networkId, contractAddress, deployTxHash, ownerAddressId, abiVersion? }` |
| Response | `{ contractAddress, deployTxHash, ... }` | `{ contractId, contractAddress, verified, ... }` |

나머지 엔드포인트(add-relayer, remove-relayer, pause, unpause, status, list)는 URL 변경 없음.
