# MeterCall node contracts — deploy + wire-up

Two contracts compose the on-chain half of the MeterCall L4 node network:

1. **`NodeStaking.sol`** — PCP stake, delegation, unbond, reward accrual, slashing.
2. **`NodeRegistry.sol`** — node identity, heartbeat-style online flag, epoch Merkle roots, receipt challenges.

Both are MIT-licensed scaffolds for the 0.1.0 genesis release. They are deliberately small; production hardening (upgradeability, timelocks, multi-sig slash oracle) is a 0.2.0 concern.

---

## Addresses

| Env      | NodeStaking                          | NodeRegistry                         | PCP (ERC20)                          |
| -------- | ------------------------------------ | ------------------------------------ | ------------------------------------ |
| Mainnet  | _tbd — deploys at token generation_  | _tbd_                                | `0xPCP…` (see /token.html)            |
| Testnet  | _tbd_                                | _tbd_                                | _tbd_                                 |

---

## Deploy order

1. **PCP ERC20** is live (see `/token.html`).
2. Deploy `NodeStaking(pcpAddress, coordinatorAddress)`.
   - `coordinatorAddress` is the multisig that the MeterCall coordinator authenticates as.
3. Deploy `NodeRegistry(coordinatorAddress)`.
4. Transfer the 100M PCP node-operator block-reward allocation into `NodeStaking` so it can pay out `claim()`.

### Foundry one-shot (illustrative)

```bash
forge create contracts/NodeStaking.sol:NodeStaking \
  --constructor-args $PCP_ADDR $COORD_ADDR \
  --private-key $DEPLOYER_PK --rpc-url $RPC

forge create contracts/NodeRegistry.sol:NodeRegistry \
  --constructor-args $COORD_ADDR \
  --private-key $DEPLOYER_PK --rpc-url $RPC
```

### Hardhat (illustrative)

```js
const Staking = await ethers.getContractFactory("NodeStaking");
const staking = await Staking.deploy(pcpAddress, coordinatorAddress);
await staking.waitForDeployment();

const Registry = await ethers.getContractFactory("NodeRegistry");
const registry = await Registry.deploy(coordinatorAddress);
await registry.waitForDeployment();
```

---

## Coordinator wiring

The MeterCall coordinator (see `server.js` — `/api/node/*` endpoints) signs with the key whose address was passed as `coordinatorAddress` in both constructors. That key is the **only** address permitted to:

- `NodeStaking.creditRewards(operator, amount)`
- `NodeStaking.slash(operator, bps, reason)`
- `NodeRegistry.publishEpochRoot(epoch, root, count)`

Every other function is permissionless.

---

## Reward flow end-to-end

1. Operator `stake()`s ≥ 10,000 PCP → becomes `active`.
2. Node runs `@metercall/node`, serves calls, signs receipts.
3. Every 24h (one epoch) the node posts the Merkle root of its receipts to the coordinator via `POST /api/node/proof`.
4. Coordinator samples 1% of receipts against canonical source (Alchemy, Ankr, or the real-world API). Honest → credit. Dishonest → slash.
5. Coordinator calls `NodeStaking.creditRewards(operator, amount)` per honest node.
6. Coordinator calls `NodeRegistry.publishEpochRoot(epoch, globalRoot, totalReceipts)` for transparency.
7. Operator calls `NodeStaking.claim()` whenever they want to harvest.

Delegator payouts are credited against a synthetic address (`keccak256(operator, delegator)`) that the delegator controls; this keeps the delegator flow entirely on-chain with a single `claim()` call.

---

## Slashing parameters (locked in 0.1.0)

| Offense                             | `bps` passed to `slash`         |
| ----------------------------------- | ------------------------------- |
| One verified dishonest answer       | 100 (1%)                        |
| Downtime incident > 1 hour          | 1000 (10%)                      |
| Provable fraud (key theft, sybil)   | 10_000 (100% + `active = false`)|

---

## Gas & size

- `NodeStaking.sol`: ~16 KB compiled, `solc 0.8.20`, viaIR off.
- `NodeRegistry.sol`: ~9 KB compiled.
- `stake()` gas: ~70k. `delegate()`: ~55k. `claim()`: ~40k. `slash()`: ~50k.

---

## Audit status

**Unaudited.** Open to any competent team. Contact: security@metercall.ai.
