market_actions.gno
4.51 Kb · 134 lines
1package memba_weighted_host
2
3import (
4 "strconv"
5
6 "chain"
7 "gno.land/p/samcrew/memba_weighted_policy"
8)
9
10// MarketConfigPath is the sole target of this source-only typed action model.
11// These values do not dispatch an action or grant the host application authority.
12const MarketConfigPath = "gno.land/r/samcrew/memba_market_config"
13
14type MarketLane string
15
16const (
17 MarketNFT MarketLane = "nft"
18 MarketService MarketLane = "service"
19 MarketToken MarketLane = "token"
20)
21
22type MarketActionKind string
23
24const (
25 MarketAcceptAdmin MarketActionKind = "accept-admin"
26 MarketSetFee MarketActionKind = "set-fee"
27 MarketSetTreasury MarketActionKind = "set-treasury"
28 MarketReturnAdmin MarketActionKind = "return-admin"
29 MarketAbortReturn MarketActionKind = "abort-return"
30)
31
32// MarketPolicy contains only addresses separately approved for a generated DAO
33// candidate. The generator requires explicit inputs and binds fixed-target
34// dispatch. No address here is inferred from an old testnet literal.
35type MarketPolicy struct {
36 dao address
37 treasury address
38 successor address
39}
40
41func NewMarketPolicy(dao, treasury, successor address) MarketPolicy {
42 target := chain.PackageAddress(MarketConfigPath)
43 if !dao.IsValid() || dao != chain.PackageAddress("gno.land/r/samcrew/memba_dao") {
44 panic("market policy requires the founding DAO address")
45 }
46 if !treasury.IsValid() || treasury == target || treasury == dao {
47 panic("market policy requires a valid external treasury")
48 }
49 if !successor.IsValid() || successor == dao || successor == target {
50 panic("market policy requires a valid distinct successor")
51 }
52 return MarketPolicy{dao: dao, treasury: treasury, successor: successor}
53}
54
55func (p MarketPolicy) DAO() address { return p.dao }
56func (p MarketPolicy) Treasury() address { return p.treasury }
57func (p MarketPolicy) Successor() address { return p.successor }
58
59// MarketAction is a closed value, not a callback, method name or free-form
60// payload. Its private fields are frozen into the commitment returned by Bytes.
61type MarketAction struct {
62 kind MarketActionKind
63 lane MarketLane
64 bps int64
65 recipient address
66}
67
68func MarketAccept() MarketAction { return MarketAction{kind: MarketAcceptAdmin} }
69
70func MarketFee(lane MarketLane, bps int64) MarketAction {
71 if lane != MarketNFT && lane != MarketService && lane != MarketToken {
72 panic("unsupported market fee lane")
73 }
74 if bps < 0 || bps > 500 {
75 panic("market fee out of range")
76 }
77 return MarketAction{kind: MarketSetFee, lane: lane, bps: bps}
78}
79
80func (p MarketPolicy) SetTreasury() MarketAction {
81 return MarketAction{kind: MarketSetTreasury, recipient: p.treasury}
82}
83
84func (p MarketPolicy) ReturnAdmin() MarketAction {
85 return MarketAction{kind: MarketReturnAdmin, recipient: p.successor}
86}
87
88func (p MarketPolicy) AbortReturn() MarketAction {
89 return MarketAction{kind: MarketAbortReturn, recipient: p.successor}
90}
91
92func (a MarketAction) Kind() MarketActionKind { return a.kind }
93func (a MarketAction) Lane() MarketLane { return a.lane }
94func (a MarketAction) BPS() int64 { return a.bps }
95func (a MarketAction) Recipient() address { return a.recipient }
96
97func (a MarketAction) Category() memba_weighted_policy.Category {
98 // Refuse zero-value or malformed actions before returning an authorization
99 // category, including values created from a zero-value MarketPolicy.
100 a.Bytes()
101 switch a.kind {
102 case MarketSetFee, MarketSetTreasury:
103 return memba_weighted_policy.Financial
104 case MarketAcceptAdmin, MarketReturnAdmin, MarketAbortReturn:
105 return memba_weighted_policy.Critical
106 default:
107 panic("unsupported market action")
108 }
109}
110
111// Bytes commits the target path, operation, category-relevant arguments and
112// recipient. There are no user-supplied delimiters in these closed domains.
113func (a MarketAction) Bytes() string {
114 base := "market-config/v1|" + MarketConfigPath + "|" + string(a.kind)
115 switch a.kind {
116 case MarketAcceptAdmin:
117 if a.lane != "" || a.bps != 0 || a.recipient != "" {
118 panic("malformed market accept action")
119 }
120 return base
121 case MarketSetFee:
122 if (a.lane != MarketNFT && a.lane != MarketService && a.lane != MarketToken) || a.bps < 0 || a.bps > 500 || a.recipient != "" {
123 panic("malformed market fee action")
124 }
125 return base + "|" + string(a.lane) + "|" + strconv.FormatInt(a.bps, 10)
126 case MarketSetTreasury, MarketReturnAdmin, MarketAbortReturn:
127 if a.lane != "" || a.bps != 0 || !a.recipient.IsValid() {
128 panic("malformed market recipient action")
129 }
130 return base + "|" + string(a.recipient)
131 default:
132 panic("unsupported market action")
133 }
134}