Skip to content
Back to skills

Soho

ASecurity

Initiate payments on the SOHO Pay credit layer using EIP-712 signatures.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 18, 2026
blockchainbashnodeapisecurity

Works with

  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 18, 2026

npx -y skills add johnalbertini14-glitch/openclaw-skills --skill soho --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Soho?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Soho
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/johnalbertini14-glitch-soho/badge)](https://www.skillsdirectory.com/skills/johnalbertini14-glitch-soho)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: sohopay
description: "Initiate payments on the SOHO Pay credit layer using EIP-712 signatures."
invocation: manual
require_confirmation: true
---

# SOHO Pay — Credit Layer Payments

This skill orchestrates payments through the SOHO Pay `Creditor` smart contract using the `spendWithAuthorization` EIP-712 flow.

**This skill is manual-invocation only.** It must not be triggered autonomously by a model. Every invocation requires explicit user confirmation.

---

## Architecture — Three-Party Separation

```
┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  Wallet Signer   │     │   SoHo (Credit)  │     │   Blockchain     │
│  (user/operator) │     │                  │     │   (Base)         │
│                  │     │  Credit checks   │     │                  │
│  Signs EIP-712   │────▶│  JIT funding     │────▶│  Settlement      │
│  Owns keys       │     │  Authorization   │     │  Creditor.sol    │
│                  │     │                  │     │                  │
│  MPC / HSM /     │     │  NEVER signs     │     │                  │
│  Turnkey / Privy │     │  NEVER holds keys│     │                  │
└──────────────────┘     └──────────────────┘     └──────────────────┘
```

**SoHo is a credit layer only.** It does not custody, hold, generate, or control any signing keys or key shards, and it does not produce EIP-712 signatures.

All EIP-712 signatures come from a separate **Wallet Signer** owned and controlled by the user or agent operator (e.g., MPC provider like Turnkey/Privy/Fireblocks, or a user wallet).

The skill orchestrates between:
- **Wallet Signer** — signing (user/operator-controlled)
- **SoHo** — credit checks + just-in-time funding (credit layer only)
- **Blockchain** — settlement

---

## Usage

```bash
node scripts/pay.js <amount> <merchantAddress> [payerAddress]
```

| Argument          | Description                                                        |
| ----------------- | ------------------------------------------------------------------ |
| `amount`          | Decimal USDC value (e.g. `10`, `0.5`)                             |
| `merchantAddress` | Explicit 0x-prefixed EVM address (checksummed). **Never a name.** |
| `payerAddress`    | Required when `SIGNER_PROVIDER=WALLET_SIGNER_REMOTE`              |

### Example — Base Sepolia with local key (dev only)

```bash
export RPC_URL=https://sepolia.base.org
export CHAIN_ID=84532
export SIGNER_PROVIDER=LOCAL_PRIVATE_KEY
export SOHO_DEV_PRIVATE_KEY=0xabc...

node scripts/pay.js 10 0x1234567890abcdef1234567890abcdef12345678
```

### Example — Base Sepolia with remote wallet signer (production pattern)

```bash
export RPC_URL=https://sepolia.base.org
export CHAIN_ID=84532
export SIGNER_PROVIDER=WALLET_SIGNER_REMOTE
export WALLET_SIGNER_SERVICE_URL=https://your-mpc-signer.example.com
export SIGNER_SERVICE_AUTH_TOKEN=sk_live_...

node scripts/pay.js 10 0xMERCHANT... 0xPAYER...
```

---

## Workflow

1. **Validate config** — all env vars checked with Zod at startup; unknown chains rejected.
2. **Parse inputs** — amount and explicit merchant address (no name-to-address generation).
3. **Pre-flight credit checks** — SoHo credit layer verifies borrower registration, active status, credit limit.
4. **Sign EIP-712** — Wallet Signer (user-controlled) produces signature. SoHo never signs.
5. **Submit tx** — call `spendWithAuthorization` on the Creditor contract.
6. **Return result** — transaction hash + block number.

---

## Supported Networks

| Network       | Chain ID | Status                                     |
| ------------- | -------- | ------------------------------------------ |
| Base Sepolia  | 84532    | Supported                                  |
| Base Mainnet  | 8453     | Requires `SOHO_MAINNET_CONFIRM=YES`        |

Unknown chain IDs are rejected at config validation time.

## Contract Addresses (Base Sepolia)

| Contract         | Address                                      |
| ---------------- | -------------------------------------------- |
| Creditor         | `0x1867a19816f38ec31ec3af1be15fd7104f161978` |
| Borrower Manager | `0x76e51158015e869ab2875fa17b87383d8886e93c` |
| USDC (test)      | `0x55b8ff660d4f0f176de84f325d39a773a7a3bda7` |

---

## Security Model

### Key Custody Boundary

| Entity         | Role                                 | Holds keys? |
| -------------- | ------------------------------------ | ----------- |
| **Wallet Signer** | Produces EIP-712 signatures       | **Yes** — user/operator-controlled |
| **SoHo**       | Credit authorization + JIT funding   | **No** — credit layer only |
| **This skill** | Orchestration between the above      | **No** — passes typed data to signer |

SoHo must NEVER custody, hold, generate, or control any signing keys or key shards.

### Wallet Signer Providers

| Provider                 | When to use                | Risk level |
| ------------------------ | -------------------------- | ---------- |
| `WALLET_SIGNER_REMOTE`  | **Production / Mainnet**   | Low — keys stay in user's MPC/HSM (Turnkey, Privy, Fireblocks, etc.) |
| `LOCAL_PRIVATE_KEY`      | **Dev / Testnet only**     | High — raw key in env |

- **Default and recommended**: `WALLET_SIGNER_REMOTE`. The skill sends EIP-712 typed data to the user's wallet signing service and never touches private keys.
- **Dev-only fallback**: `LOCAL_PRIVATE_KEY` is gated to testnet chain IDs. Using it on mainnet requires `DEV_ALLOW_LOCAL_KEY=YES` and is **strongly discouraged**.

### Mainnet Safety Gate

Transactions on Base Mainnet (`CHAIN_ID=8453`) are refused unless `SOHO_MAINNET_CONFIRM=YES` is set. This prevents accidental mainnet spends during development.

### Recipient Address Policy

The skill **never** derives or generates an address from a merchant name. The `merchantAddress` argument must be an explicit, valid, checksummed EVM address. Any non-address input is rejected with an error.

### Invocation Policy

- `invocation: manual` — the skill cannot be triggered autonomously.
- `require_confirmation: true` — the orchestrator must obtain user confirmation before execution.
- A runtime guard rejects execution if `SOHO_AUTONOMOUS=true` is detected in the environment.

---

## Threat Model & Mitigations

| Threat | Mitigation |
| ------ | ---------- |
| **Signer compromise** | Default to `WALLET_SIGNER_REMOTE` (MPC/HSM); keys never leave the user's signing service. Local key gated to testnet only. |
| **Replay attacks** | Random 32-byte nonce per transaction; `validAfter` / `expiry` window (10 min). On-chain nonce check in Creditor contract. |
| **Wrong merchant address** | Address generation from names removed. Only explicit checksummed EVM addresses accepted; checksum validated before signing. |
| **Accidental mainnet transaction** | `SOHO_MAINNET_CONFIRM=YES` safety gate required for chain ID 8453. |
| **Autonomous invocation with signing authority** | `invocation: manual` in metadata; `require_confirmation: true`; runtime guard blocks `SOHO_AUTONOMOUS=true`. |
| **SoHo used as signer** | Architecture enforces SoHo = credit-only. No signing key env vars reference SoHo as a signer. Skill never passes keys to SoHo API. |
| **Undeclared env var dependencies** | All env vars declared in `skill.json` with types and sensitivity flags. |
| **MITM on wallet signer service** | Use HTTPS for `WALLET_SIGNER_SERVICE_URL`; bearer token auth via `SIGNER_SERVICE_AUTH_TOKEN`. |

---

## Environment Variables

### Required (all modes)

| Variable          | Example                          | Description                              |
| ----------------- | -------------------------------- | ---------------------------------------- |
| `RPC_URL`         | `https://sepolia.base.org`       | JSON-RPC endpoint                        |
| `CHAIN_ID`        | `84532`                          | 84532 (Sepolia) or 8453 (Mainnet)       |
| `SIGNER_PROVIDER` | `WALLET_SIGNER_REMOTE`           | `WALLET_SIGNER_REMOTE` or `LOCAL_PRIVATE_KEY` |

### Required for `WALLET_SIGNER_REMOTE`

| Variable                     | Description                                          | Sensitive |
| ---------------------------- | ---------------------------------------------------- | --------- |
| `WALLET_SIGNER_SERVICE_URL`  | Base URL of user/operator's wallet signing service   | No        |
| `SIGNER_SERVICE_AUTH_TOKEN`  | Bearer auth token for the wallet signing service     | **Yes**   |

### SoHo Credit Layer

| Variable       | Description                                           | Sensitive |
| -------------- | ----------------------------------------------------- | --------- |
| `SOHO_API_URL` | SoHo credit-layer API (credit checks, JIT funding)   | No        |

### Required for `LOCAL_PRIVATE_KEY` (dev / testnet only)

| Variable               | Description                                  | Sensitive |
| ---------------------- | -------------------------------------------- | --------- |
| `SOHO_DEV_PRIVATE_KEY` | User/operator's raw hex private key (NOT a SoHo key) | **Yes** |

### Conditional

| Variable               | When required                                         |
| ---------------------- | ----------------------------------------------------- |
| `SOHO_MAINNET_CONFIRM` | Must be `YES` when `CHAIN_ID=8453`                   |
| `DEV_ALLOW_LOCAL_KEY`  | Set `YES` to allow local key on non-testnet (dangerous) |

---

## Dependencies

Install with:

```bash
npm install
```

| Package  | Purpose                            |
| -------- | ---------------------------------- |
| `ethers` | EVM interactions, EIP-712 signing  |
| `dotenv` | Load `.env` files                  |
| `zod`    | Env var validation at startup      |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.