Skip to content

Commit 48f5ce2

Browse files
committed
looprpc: require loop:out for instant out
InstantOut can now accept a caller-provided destination address and use it as the on-chain sweep target for reservation funds. That makes it an externally directed loop-out spend path, so a swap:execute-only macaroon should not be sufficient. Require the same loop:out authority used by LoopOut and add a regression test so the method cannot drift back to swap:execute-only authorization.
1 parent cc0392a commit 48f5ce2

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

looprpc/perms.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ var RequiredPermissions = map[string][]bakery.Op{
181181
"/looprpc.SwapClient/InstantOut": {{
182182
Entity: "swap",
183183
Action: "execute",
184+
}, {
185+
Entity: "loop",
186+
Action: "out",
184187
}},
185188
"/looprpc.SwapClient/InstantOutQuote": {{
186189
Entity: "swap",

looprpc/perms_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package looprpc
2+
3+
import (
4+
"testing"
5+
6+
"gopkg.in/macaroon-bakery.v2/bakery"
7+
)
8+
9+
func TestInstantOutRequiresLoopOutPermission(t *testing.T) {
10+
requiredPerms, ok := RequiredPermissions["/looprpc.SwapClient/InstantOut"]
11+
if !ok {
12+
t.Fatalf("InstantOut permission entry missing")
13+
}
14+
15+
assertPermission := func(want bakery.Op) {
16+
t.Helper()
17+
18+
for _, perm := range requiredPerms {
19+
if perm == want {
20+
return
21+
}
22+
}
23+
24+
t.Fatalf("InstantOut permission entry missing %v", want)
25+
}
26+
27+
assertPermission(bakery.Op{
28+
Entity: "swap",
29+
Action: "execute",
30+
})
31+
assertPermission(bakery.Op{
32+
Entity: "loop",
33+
Action: "out",
34+
})
35+
}

0 commit comments

Comments
 (0)