Files
pezkuwi-sdk/tools/usdt-bridge/deploy/usdt-bridge.service
T
Satoshi Qazi Muhammed 96840fd17e Add bounded automation-key auto-pay: per-tx cap, daily velocity cap, circuit breaker
Small/mid-size swaps no longer have to wait on 3-of-5 for every single
transaction. usdt-bridge can now execute Assets.transfer_approved directly via
the automation key's existing delegated allowance when a deposit/withdrawal
passes all three independent guards:

- max_single_tx (50,000 USDT): any single transaction above this always queues
  for manual multisig review, no exceptions.
- auto_pay_daily_cap (200,000 USDT): a rolling 24h budget tracked separately
  per leg (wUSDT payouts vs USDT payouts draw on separate on-chain allowances),
  not a per-tx ceiling - lets many legitimate sub-cap swaps clear same-day.
- circuit breaker: if >=50% of the daily cap is consumed within 30 minutes,
  auto-pay halts entirely until a human runs reset-circuit-breaker - a burst
  that fast reads as a compromised key or a bug, not organic demand.

The automation key can only ever move funds via its pre-approved allowance
(never mint/burn/set_team/transfer_ownership - those stay multisig-only), so
its worst case is bounded by whatever allowance + daily cap remain, not
unbounded custody. Withdrawal auto-pay releases real USDT immediately but
defers the corresponding wUSDT burn (Owner/Admin-only, no delegation exists
for it) to a periodic manual multisig batch - tracked via a distinct
auto_paid_burn_pending status so it can't be silently forgotten.

Auto-pay is opt-in at the infra level: AUTOMATION_KEY_MNEMONIC unset means
100% manual behavior, unchanged from before. Bumped pezbridge-bot's
renewal_threshold/topup_amount so the next 3-of-5-approved allowance renewal
scales to the new daily cap.
2026-07-14 15:28:20 -07:00

61 lines
2.6 KiB
Desktop File

[Unit]
Description=usdt-bridge listen-all - USDT/wUSDT listener; auto-pays sub-cap swaps via the bounded automation-key allowance, everything else queues for 3-of-5
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=usdtbridge
Group=usdtbridge
WorkingDirectory=/opt/usdtbridge/data
ExecStart=/opt/usdtbridge/bin/usdt-bridge --config /opt/usdtbridge/bin/bridge_config.json listen-all
Environment=RUST_LOG=info
EnvironmentFile=/etc/pezbridgebot/telegram_token.env
EnvironmentFile=-/etc/usdtbridge/automation_key.env
Restart=on-failure
RestartSec=10
# --- Hardening ---
# Deployed 2026-07-14 on NEW-10 (89.116.25.180), same UTIL bucket as pezbridge-bot (no
# consensus/fund-critical services here - see dks-ci-runners/vps2-dev-decommission-status
# memory for the placement convention). UPDATED 2026-07-14: this process now also loads the
# automation key's mnemonic (from a separate, tighter-scoped EnvironmentFile than the Telegram
# token) and can sign+submit Assets.transfer_approved on both chains - but ONLY within the
# multisig's pre-approved delegated allowance, capped per-tx (max_single_tx) and per rolling 24h
# window (auto_pay_daily_cap) with a circuit breaker on burst consumption. It can never mint,
# burn, set_team, or transfer_ownership - those stay exclusively multisig (3-of-5), same as
# before. Worst case of this key being compromised is bounded by whatever allowance + daily cap
# remain at the time, not unbounded custody - a materially different (and much smaller) risk
# tier than the legacy single-key bot this whole migration replaced. Hardening kept as-is; the
# automation_key.env file itself is root:usdtbridge 0640, separate from the Telegram token file
# so a Telegram-token leak alone can never expose the signing key. The leading "-" on that
# EnvironmentFile line is required (not decorative): the file does not exist until an operator
# deliberately provisions it, and the unit must still start cleanly without it, matching the
# code's own AUTOMATION_KEY_MNEMONIC-unset fallback (100% manual, auto-pay simply inactive).
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
RestrictSUIDSGID=yes
RemoveIPC=yes
LockPersonality=yes
RestrictRealtime=yes
RestrictNamespaces=yes
MemoryDenyWriteExecute=yes
SystemCallFilter=@system-service
SystemCallArchitectures=native
CapabilityBoundingSet=
AmbientCapabilities=
ReadWritePaths=/opt/usdtbridge/data
UMask=0077
[Install]
WantedBy=multi-user.target