@sherwoodagent/cli 0.65.2 → 0.72.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{abis-4HWN2E3H.js → abis-KP7M4IPM.js} +4 -2
- package/dist/addresses-YDPUPGWQ.js +45 -0
- package/dist/{agent-AETROOEW.js → agent-6IRZUPFT.js} +10 -10
- package/dist/{agent-AETROOEW.js.map → agent-6IRZUPFT.js.map} +1 -1
- package/dist/{chat-JSSTSE4K.js → chat-G5M3OK6M.js} +37 -36
- package/dist/chat-G5M3OK6M.js.map +1 -0
- package/dist/{chunk-IL43IMOC.js → chunk-3NMJ4LUL.js} +23 -18
- package/dist/chunk-3NMJ4LUL.js.map +1 -0
- package/dist/{chunk-UBAX22KA.js → chunk-52U76TRE.js} +4 -4
- package/dist/chunk-52U76TRE.js.map +1 -0
- package/dist/{chunk-W2ZUPR3W.js → chunk-5DWB5Y7G.js} +9 -9
- package/dist/chunk-5DWB5Y7G.js.map +1 -0
- package/dist/{chunk-YZHZSBES.js → chunk-BQMOE4FJ.js} +144 -37
- package/dist/chunk-BQMOE4FJ.js.map +1 -0
- package/dist/{chunk-VYF2TXPX.js → chunk-D4SPHYXA.js} +6 -6
- package/dist/{chunk-UCQEEF3Z.js → chunk-FOAX5PGR.js} +6 -6
- package/dist/chunk-FOAX5PGR.js.map +1 -0
- package/dist/chunk-FOS47623.js +127 -0
- package/dist/chunk-FOS47623.js.map +1 -0
- package/dist/{chunk-2W4KGGPU.js → chunk-GSC7PVEO.js} +27 -27
- package/dist/chunk-GSC7PVEO.js.map +1 -0
- package/dist/chunk-HYUUR6SC.js +111 -0
- package/dist/chunk-HYUUR6SC.js.map +1 -0
- package/dist/{chunk-RO26TXXE.js → chunk-NWY2U753.js} +2 -2
- package/dist/chunk-RAITRCM7.js +308 -0
- package/dist/chunk-RAITRCM7.js.map +1 -0
- package/dist/{chunk-A6TOJEUD.js → chunk-S6XA7PK4.js} +124 -128
- package/dist/chunk-S6XA7PK4.js.map +1 -0
- package/dist/{chunk-O4G3SBCI.js → chunk-UUHWD7Y3.js} +109 -129
- package/dist/chunk-UUHWD7Y3.js.map +1 -0
- package/dist/{chunk-YJSCIQUZ.js → chunk-WECQ6NVS.js} +6 -6
- package/dist/chunk-WECQ6NVS.js.map +1 -0
- package/dist/{chunk-RHRLYVKM.js → chunk-ZYXFKVYF.js} +25 -12
- package/dist/chunk-ZYXFKVYF.js.map +1 -0
- package/dist/{client-KBBFAMEI.js → client-QN6SA76M.js} +4 -4
- package/dist/{config-REASKDIK.js → config-FAQO37S7.js} +10 -10
- package/dist/{cron-EOULYO3R.js → cron-QMLRWDJG.js} +19 -17
- package/dist/cron-QMLRWDJG.js.map +1 -0
- package/dist/{eas-K4ZBACYN.js → eas-HM2AUOEY.js} +7 -7
- package/dist/{governor-2CDSMSG7.js → governor-RRBTDGDX.js} +17 -13
- package/dist/index.js +2026 -1222
- package/dist/index.js.map +1 -1
- package/dist/{ipfs-FAYWUCS2.js → ipfs-VGWTUORE.js} +2 -2
- package/dist/{network-3ZU7UBDU.js → network-L6JKNYOJ.js} +7 -7
- package/dist/{price-LCTECRQP.js → price-AJ4JMHCT.js} +6 -6
- package/dist/{research-FUQOQWKK.js → research-6VEEPEPP.js} +22 -22
- package/dist/research-6VEEPEPP.js.map +1 -0
- package/dist/research-7Z6SFPPX.js +14 -0
- package/dist/{session-FJB2RV2X.js → session-PURMITWE.js} +28 -28
- package/dist/session-PURMITWE.js.map +1 -0
- package/dist/{session-XAW5UIXP.js → session-XBQY7SBJ.js} +2 -2
- package/dist/{trade-U7H5IFH6.js → trade-YTGLGCRQ.js} +34 -34
- package/dist/trade-YTGLGCRQ.js.map +1 -0
- package/dist/vault-NIPA5JV4.js +54 -0
- package/dist/vault-NIPA5JV4.js.map +1 -0
- package/dist/{xmtp-6NJ4PW6L.js → xmtp-M32JSE4I.js} +13 -12
- package/dist/xmtp-M32JSE4I.js.map +1 -0
- package/package.json +4 -3
- package/dist/addresses-J2LMGUCT.js +0 -35
- package/dist/chat-JSSTSE4K.js.map +0 -1
- package/dist/chunk-2LRC7I33.js +0 -186
- package/dist/chunk-2LRC7I33.js.map +0 -1
- package/dist/chunk-2W4KGGPU.js.map +0 -1
- package/dist/chunk-A6TOJEUD.js.map +0 -1
- package/dist/chunk-GWMTAW6A.js +0 -494
- package/dist/chunk-GWMTAW6A.js.map +0 -1
- package/dist/chunk-IL43IMOC.js.map +0 -1
- package/dist/chunk-O4G3SBCI.js.map +0 -1
- package/dist/chunk-RHRLYVKM.js.map +0 -1
- package/dist/chunk-UBAX22KA.js.map +0 -1
- package/dist/chunk-UCQEEF3Z.js.map +0 -1
- package/dist/chunk-W2ZUPR3W.js.map +0 -1
- package/dist/chunk-YJSCIQUZ.js.map +0 -1
- package/dist/chunk-YZHZSBES.js.map +0 -1
- package/dist/cron-EOULYO3R.js.map +0 -1
- package/dist/research-FUQOQWKK.js.map +0 -1
- package/dist/research-XEXTHDT3.js +0 -14
- package/dist/session-FJB2RV2X.js.map +0 -1
- package/dist/trade-U7H5IFH6.js.map +0 -1
- package/dist/xmtp-6NJ4PW6L.js.map +0 -1
- /package/dist/{abis-4HWN2E3H.js.map → abis-KP7M4IPM.js.map} +0 -0
- /package/dist/{addresses-J2LMGUCT.js.map → addresses-YDPUPGWQ.js.map} +0 -0
- /package/dist/{chunk-VYF2TXPX.js.map → chunk-D4SPHYXA.js.map} +0 -0
- /package/dist/{chunk-RO26TXXE.js.map → chunk-NWY2U753.js.map} +0 -0
- /package/dist/{client-KBBFAMEI.js.map → client-QN6SA76M.js.map} +0 -0
- /package/dist/{config-REASKDIK.js.map → config-FAQO37S7.js.map} +0 -0
- /package/dist/{eas-K4ZBACYN.js.map → eas-HM2AUOEY.js.map} +0 -0
- /package/dist/{governor-2CDSMSG7.js.map → governor-RRBTDGDX.js.map} +0 -0
- /package/dist/{ipfs-FAYWUCS2.js.map → ipfs-VGWTUORE.js.map} +0 -0
- /package/dist/{network-3ZU7UBDU.js.map → network-L6JKNYOJ.js.map} +0 -0
- /package/dist/{price-LCTECRQP.js.map → price-AJ4JMHCT.js.map} +0 -0
- /package/dist/{research-XEXTHDT3.js.map → research-7Z6SFPPX.js.map} +0 -0
- /package/dist/{session-XAW5UIXP.js.map → session-XBQY7SBJ.js.map} +0 -0
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SHERWOOD
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RAITRCM7.js";
|
|
4
4
|
import {
|
|
5
5
|
getAccount,
|
|
6
6
|
getPublicClient,
|
|
7
7
|
waitForReceipt,
|
|
8
8
|
writeContractWithRetry
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-WECQ6NVS.js";
|
|
10
10
|
import {
|
|
11
11
|
getChain
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HYUUR6SC.js";
|
|
13
13
|
import {
|
|
14
|
+
PROTOCOL_CONFIG_ABI,
|
|
15
|
+
SYNDICATE_FACTORY_ABI,
|
|
14
16
|
SYNDICATE_GOVERNOR_ABI
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BQMOE4FJ.js";
|
|
16
18
|
|
|
17
19
|
// src/lib/governor.ts
|
|
18
20
|
import { parseEventLogs } from "viem";
|
|
@@ -43,6 +45,22 @@ var VOTE_TYPE = {
|
|
|
43
45
|
Against: 1,
|
|
44
46
|
Abstain: 2
|
|
45
47
|
};
|
|
48
|
+
function evaluateExecuteGate(args) {
|
|
49
|
+
const { state, reviewEnd, executeBy, now } = args;
|
|
50
|
+
if (state === PROPOSAL_STATE.Approved) return { kind: "send" };
|
|
51
|
+
if (state === PROPOSAL_STATE.GuardianReview) {
|
|
52
|
+
if (now <= reviewEnd) return { kind: "refuse-review-open" };
|
|
53
|
+
if (now > executeBy) return { kind: "refuse-expired" };
|
|
54
|
+
return { kind: "send-self-resolve" };
|
|
55
|
+
}
|
|
56
|
+
return { kind: "refuse-state" };
|
|
57
|
+
}
|
|
58
|
+
function classifyReview(args) {
|
|
59
|
+
const { opened, resolved, reviewEnd, now } = args;
|
|
60
|
+
const pastWindow = reviewEnd > 0n && now >= reviewEnd;
|
|
61
|
+
if (!pastWindow || resolved) return "none";
|
|
62
|
+
return opened ? "resolvable" : "cold-start";
|
|
63
|
+
}
|
|
46
64
|
function parseDuration(input) {
|
|
47
65
|
const match = input.match(/^(\d+)(d|h|m|s)?$/);
|
|
48
66
|
if (!match) throw new Error(`Invalid duration: ${input}`);
|
|
@@ -61,125 +79,143 @@ function parseDuration(input) {
|
|
|
61
79
|
throw new Error(`Unknown duration unit: ${match[2]}`);
|
|
62
80
|
}
|
|
63
81
|
}
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
var governorCache = /* @__PURE__ */ new Map();
|
|
83
|
+
async function getGovernorOf(vault) {
|
|
84
|
+
const key = `${getChain().id}:${vault.toLowerCase()}`;
|
|
85
|
+
const cached = governorCache.get(key);
|
|
86
|
+
if (cached) return cached;
|
|
87
|
+
const client = getPublicClient();
|
|
88
|
+
const governor = await client.readContract({
|
|
89
|
+
address: SHERWOOD().FACTORY,
|
|
90
|
+
abi: SYNDICATE_FACTORY_ABI,
|
|
91
|
+
functionName: "governorOf",
|
|
92
|
+
args: [vault]
|
|
93
|
+
});
|
|
94
|
+
if (governor === "0x0000000000000000000000000000000000000000") {
|
|
95
|
+
throw new Error(`No governor registered for vault ${vault} \u2014 is it a factory-created vault?`);
|
|
96
|
+
}
|
|
97
|
+
governorCache.set(key, governor);
|
|
98
|
+
return governor;
|
|
99
|
+
}
|
|
100
|
+
var protocolConfigCache = /* @__PURE__ */ new Map();
|
|
101
|
+
async function getProtocolConfigAddress() {
|
|
102
|
+
const chainId = getChain().id;
|
|
103
|
+
const cached = protocolConfigCache.get(chainId);
|
|
104
|
+
if (cached) return cached;
|
|
105
|
+
const client = getPublicClient();
|
|
106
|
+
const config = await client.readContract({
|
|
107
|
+
address: SHERWOOD().FACTORY,
|
|
108
|
+
abi: SYNDICATE_FACTORY_ABI,
|
|
109
|
+
functionName: "protocolConfig"
|
|
110
|
+
});
|
|
111
|
+
protocolConfigCache.set(chainId, config);
|
|
112
|
+
return config;
|
|
66
113
|
}
|
|
67
|
-
async function getGovernorParams() {
|
|
114
|
+
async function getGovernorParams(vault) {
|
|
68
115
|
const client = getPublicClient();
|
|
69
116
|
const result = await client.readContract({
|
|
70
|
-
address:
|
|
117
|
+
address: await getGovernorOf(vault),
|
|
71
118
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
72
119
|
functionName: "getGovernorParams"
|
|
73
120
|
});
|
|
74
121
|
return result;
|
|
75
122
|
}
|
|
76
|
-
async function getProposal(id) {
|
|
123
|
+
async function getProposal(vault, id) {
|
|
77
124
|
const client = getPublicClient();
|
|
78
125
|
const result = await client.readContract({
|
|
79
|
-
address:
|
|
126
|
+
address: await getGovernorOf(vault),
|
|
80
127
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
81
128
|
functionName: "getProposal",
|
|
82
129
|
args: [id]
|
|
83
130
|
});
|
|
84
131
|
return result;
|
|
85
132
|
}
|
|
86
|
-
async function getProposalState(id) {
|
|
133
|
+
async function getProposalState(vault, id) {
|
|
87
134
|
const client = getPublicClient();
|
|
88
135
|
return client.readContract({
|
|
89
|
-
address:
|
|
136
|
+
address: await getGovernorOf(vault),
|
|
90
137
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
91
138
|
functionName: "getProposalState",
|
|
92
139
|
args: [id]
|
|
93
140
|
});
|
|
94
141
|
}
|
|
95
|
-
async function proposalCount() {
|
|
142
|
+
async function proposalCount(vault) {
|
|
96
143
|
const client = getPublicClient();
|
|
97
144
|
return client.readContract({
|
|
98
|
-
address:
|
|
145
|
+
address: await getGovernorOf(vault),
|
|
99
146
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
100
147
|
functionName: "proposalCount"
|
|
101
148
|
});
|
|
102
149
|
}
|
|
103
|
-
async function getVoteWeight(proposalId, voter) {
|
|
150
|
+
async function getVoteWeight(vault, proposalId, voter) {
|
|
104
151
|
const client = getPublicClient();
|
|
105
152
|
return client.readContract({
|
|
106
|
-
address:
|
|
153
|
+
address: await getGovernorOf(vault),
|
|
107
154
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
108
155
|
functionName: "getVoteWeight",
|
|
109
156
|
args: [proposalId, voter]
|
|
110
157
|
});
|
|
111
158
|
}
|
|
112
|
-
async function hasVoted(proposalId, voter) {
|
|
159
|
+
async function hasVoted(vault, proposalId, voter) {
|
|
113
160
|
const client = getPublicClient();
|
|
114
161
|
return client.readContract({
|
|
115
|
-
address:
|
|
162
|
+
address: await getGovernorOf(vault),
|
|
116
163
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
117
164
|
functionName: "hasVoted",
|
|
118
165
|
args: [proposalId, voter]
|
|
119
166
|
});
|
|
120
167
|
}
|
|
121
|
-
async function getExecuteCalls(proposalId) {
|
|
168
|
+
async function getExecuteCalls(vault, proposalId) {
|
|
122
169
|
const client = getPublicClient();
|
|
123
170
|
const result = await client.readContract({
|
|
124
|
-
address:
|
|
171
|
+
address: await getGovernorOf(vault),
|
|
125
172
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
126
173
|
functionName: "getExecuteCalls",
|
|
127
174
|
args: [proposalId]
|
|
128
175
|
});
|
|
129
176
|
return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));
|
|
130
177
|
}
|
|
131
|
-
async function getSettlementCalls(proposalId) {
|
|
178
|
+
async function getSettlementCalls(vault, proposalId) {
|
|
132
179
|
const client = getPublicClient();
|
|
133
180
|
const result = await client.readContract({
|
|
134
|
-
address:
|
|
181
|
+
address: await getGovernorOf(vault),
|
|
135
182
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
136
183
|
functionName: "getSettlementCalls",
|
|
137
184
|
args: [proposalId]
|
|
138
185
|
});
|
|
139
186
|
return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));
|
|
140
187
|
}
|
|
141
|
-
async function getRegisteredVaults() {
|
|
142
|
-
const client = getPublicClient();
|
|
143
|
-
return client.readContract({
|
|
144
|
-
address: getGovernorAddress(),
|
|
145
|
-
abi: SYNDICATE_GOVERNOR_ABI,
|
|
146
|
-
functionName: "getRegisteredVaults"
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
188
|
async function getActiveProposal(vault) {
|
|
150
189
|
const client = getPublicClient();
|
|
151
190
|
return client.readContract({
|
|
152
|
-
address:
|
|
191
|
+
address: await getGovernorOf(vault),
|
|
153
192
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
154
|
-
functionName: "getActiveProposal"
|
|
155
|
-
args: [vault]
|
|
193
|
+
functionName: "getActiveProposal"
|
|
156
194
|
});
|
|
157
195
|
}
|
|
158
196
|
async function getCooldownEnd(vault) {
|
|
159
197
|
const client = getPublicClient();
|
|
160
198
|
return client.readContract({
|
|
161
|
-
address:
|
|
199
|
+
address: await getGovernorOf(vault),
|
|
162
200
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
163
|
-
functionName: "getCooldownEnd"
|
|
164
|
-
args: [vault]
|
|
201
|
+
functionName: "getCooldownEnd"
|
|
165
202
|
});
|
|
166
203
|
}
|
|
167
|
-
async function
|
|
204
|
+
async function openProposalCount(vault) {
|
|
168
205
|
const client = getPublicClient();
|
|
169
206
|
return client.readContract({
|
|
170
|
-
address:
|
|
207
|
+
address: await getGovernorOf(vault),
|
|
171
208
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
172
|
-
functionName: "
|
|
173
|
-
args: [proposalId]
|
|
209
|
+
functionName: "openProposalCount"
|
|
174
210
|
});
|
|
175
211
|
}
|
|
176
|
-
async function
|
|
212
|
+
async function getCapitalSnapshot(vault, proposalId) {
|
|
177
213
|
const client = getPublicClient();
|
|
178
214
|
return client.readContract({
|
|
179
|
-
address:
|
|
215
|
+
address: await getGovernorOf(vault),
|
|
180
216
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
181
|
-
functionName: "
|
|
182
|
-
args: [
|
|
217
|
+
functionName: "getCapitalSnapshot",
|
|
218
|
+
args: [proposalId]
|
|
183
219
|
});
|
|
184
220
|
}
|
|
185
221
|
function parseProposalIdFromLogs(logs) {
|
|
@@ -194,31 +230,31 @@ function parseProposalIdFromLogs(logs) {
|
|
|
194
230
|
return void 0;
|
|
195
231
|
}
|
|
196
232
|
}
|
|
197
|
-
async function propose(vault, strategy, metadataURI,
|
|
233
|
+
async function propose(vault, strategy, metadataURI, strategyDuration, executeCalls, settlementCalls, coProposers = []) {
|
|
198
234
|
const hash = await writeContractWithRetry({
|
|
199
235
|
account: getAccount(),
|
|
200
236
|
chain: getChain(),
|
|
201
|
-
address:
|
|
237
|
+
address: await getGovernorOf(vault),
|
|
202
238
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
203
239
|
functionName: "propose",
|
|
204
|
-
args: [vault, strategy, metadataURI,
|
|
240
|
+
args: [vault, strategy, metadataURI, strategyDuration, executeCalls, settlementCalls, coProposers]
|
|
205
241
|
});
|
|
206
242
|
const receipt = await waitForReceipt(hash);
|
|
207
243
|
let proposalId = parseProposalIdFromLogs(receipt.logs);
|
|
208
244
|
if (proposalId === void 0) {
|
|
209
245
|
try {
|
|
210
|
-
proposalId = await proposalCount();
|
|
246
|
+
proposalId = await proposalCount(vault);
|
|
211
247
|
} catch {
|
|
212
248
|
proposalId = 0n;
|
|
213
249
|
}
|
|
214
250
|
}
|
|
215
251
|
return { hash: receipt.transactionHash, proposalId };
|
|
216
252
|
}
|
|
217
|
-
async function vote(proposalId, support) {
|
|
253
|
+
async function vote(vault, proposalId, support) {
|
|
218
254
|
const hash = await writeContractWithRetry({
|
|
219
255
|
account: getAccount(),
|
|
220
256
|
chain: getChain(),
|
|
221
|
-
address:
|
|
257
|
+
address: await getGovernorOf(vault),
|
|
222
258
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
223
259
|
functionName: "vote",
|
|
224
260
|
args: [proposalId, support]
|
|
@@ -226,11 +262,11 @@ async function vote(proposalId, support) {
|
|
|
226
262
|
const receipt = await waitForReceipt(hash);
|
|
227
263
|
return receipt.transactionHash;
|
|
228
264
|
}
|
|
229
|
-
async function executeProposal(proposalId) {
|
|
265
|
+
async function executeProposal(vault, proposalId) {
|
|
230
266
|
const hash = await writeContractWithRetry({
|
|
231
267
|
account: getAccount(),
|
|
232
268
|
chain: getChain(),
|
|
233
|
-
address:
|
|
269
|
+
address: await getGovernorOf(vault),
|
|
234
270
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
235
271
|
functionName: "executeProposal",
|
|
236
272
|
args: [proposalId]
|
|
@@ -247,11 +283,11 @@ function detectStrategyAdapter(calls) {
|
|
|
247
283
|
}
|
|
248
284
|
return null;
|
|
249
285
|
}
|
|
250
|
-
async function settleProposal(proposalId) {
|
|
286
|
+
async function settleProposal(vault, proposalId) {
|
|
251
287
|
const hash = await writeContractWithRetry({
|
|
252
288
|
account: getAccount(),
|
|
253
289
|
chain: getChain(),
|
|
254
|
-
address:
|
|
290
|
+
address: await getGovernorOf(vault),
|
|
255
291
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
256
292
|
functionName: "settleProposal",
|
|
257
293
|
args: [proposalId]
|
|
@@ -259,23 +295,23 @@ async function settleProposal(proposalId) {
|
|
|
259
295
|
const receipt = await waitForReceipt(hash);
|
|
260
296
|
return receipt.transactionHash;
|
|
261
297
|
}
|
|
262
|
-
async function emergencySettle(proposalId, calls) {
|
|
298
|
+
async function emergencySettle(vault, proposalId, calls) {
|
|
263
299
|
const hash = await writeContractWithRetry({
|
|
264
300
|
account: getAccount(),
|
|
265
301
|
chain: getChain(),
|
|
266
|
-
address:
|
|
302
|
+
address: await getGovernorOf(vault),
|
|
267
303
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
268
|
-
functionName: "
|
|
304
|
+
functionName: "emergencySettleWithCalls",
|
|
269
305
|
args: [proposalId, calls]
|
|
270
306
|
});
|
|
271
307
|
const receipt = await waitForReceipt(hash);
|
|
272
308
|
return receipt.transactionHash;
|
|
273
309
|
}
|
|
274
|
-
async function cancelProposal(proposalId) {
|
|
310
|
+
async function cancelProposal(vault, proposalId) {
|
|
275
311
|
const hash = await writeContractWithRetry({
|
|
276
312
|
account: getAccount(),
|
|
277
313
|
chain: getChain(),
|
|
278
|
-
address:
|
|
314
|
+
address: await getGovernorOf(vault),
|
|
279
315
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
280
316
|
functionName: "cancelProposal",
|
|
281
317
|
args: [proposalId]
|
|
@@ -283,11 +319,11 @@ async function cancelProposal(proposalId) {
|
|
|
283
319
|
const receipt = await waitForReceipt(hash);
|
|
284
320
|
return receipt.transactionHash;
|
|
285
321
|
}
|
|
286
|
-
async function emergencyCancel(proposalId) {
|
|
322
|
+
async function emergencyCancel(vault, proposalId) {
|
|
287
323
|
const hash = await writeContractWithRetry({
|
|
288
324
|
account: getAccount(),
|
|
289
325
|
chain: getChain(),
|
|
290
|
-
address:
|
|
326
|
+
address: await getGovernorOf(vault),
|
|
291
327
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
292
328
|
functionName: "emergencyCancel",
|
|
293
329
|
args: [proposalId]
|
|
@@ -295,83 +331,41 @@ async function emergencyCancel(proposalId) {
|
|
|
295
331
|
const receipt = await waitForReceipt(hash);
|
|
296
332
|
return receipt.transactionHash;
|
|
297
333
|
}
|
|
298
|
-
async function
|
|
334
|
+
async function setGovernorParam(vault, functionName, value) {
|
|
299
335
|
const hash = await writeContractWithRetry({
|
|
300
336
|
account: getAccount(),
|
|
301
337
|
chain: getChain(),
|
|
302
|
-
address:
|
|
338
|
+
address: await getGovernorOf(vault),
|
|
303
339
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
304
|
-
functionName
|
|
305
|
-
args: [
|
|
340
|
+
functionName,
|
|
341
|
+
args: [value]
|
|
306
342
|
});
|
|
307
343
|
const receipt = await waitForReceipt(hash);
|
|
308
344
|
return receipt.transactionHash;
|
|
309
345
|
}
|
|
310
|
-
async function
|
|
311
|
-
|
|
312
|
-
account: getAccount(),
|
|
313
|
-
chain: getChain(),
|
|
314
|
-
address: getGovernorAddress(),
|
|
315
|
-
abi: SYNDICATE_GOVERNOR_ABI,
|
|
316
|
-
functionName: "setExecutionWindow",
|
|
317
|
-
args: [seconds]
|
|
318
|
-
});
|
|
319
|
-
const receipt = await waitForReceipt(hash);
|
|
320
|
-
return receipt.transactionHash;
|
|
346
|
+
async function setVotingPeriod(vault, seconds) {
|
|
347
|
+
return setGovernorParam(vault, "setVotingPeriod", seconds);
|
|
321
348
|
}
|
|
322
|
-
async function
|
|
323
|
-
|
|
324
|
-
account: getAccount(),
|
|
325
|
-
chain: getChain(),
|
|
326
|
-
address: getGovernorAddress(),
|
|
327
|
-
abi: SYNDICATE_GOVERNOR_ABI,
|
|
328
|
-
functionName: "setVetoThresholdBps",
|
|
329
|
-
args: [bps]
|
|
330
|
-
});
|
|
331
|
-
const receipt = await waitForReceipt(hash);
|
|
332
|
-
return receipt.transactionHash;
|
|
349
|
+
async function setExecutionWindow(vault, seconds) {
|
|
350
|
+
return setGovernorParam(vault, "setExecutionWindow", seconds);
|
|
333
351
|
}
|
|
334
|
-
async function
|
|
335
|
-
|
|
336
|
-
account: getAccount(),
|
|
337
|
-
chain: getChain(),
|
|
338
|
-
address: getGovernorAddress(),
|
|
339
|
-
abi: SYNDICATE_GOVERNOR_ABI,
|
|
340
|
-
functionName: "setMaxPerformanceFeeBps",
|
|
341
|
-
args: [bps]
|
|
342
|
-
});
|
|
343
|
-
const receipt = await waitForReceipt(hash);
|
|
344
|
-
return receipt.transactionHash;
|
|
352
|
+
async function setVetoThresholdBps(vault, bps) {
|
|
353
|
+
return setGovernorParam(vault, "setVetoThresholdBps", bps);
|
|
345
354
|
}
|
|
346
|
-
async function
|
|
347
|
-
|
|
348
|
-
account: getAccount(),
|
|
349
|
-
chain: getChain(),
|
|
350
|
-
address: getGovernorAddress(),
|
|
351
|
-
abi: SYNDICATE_GOVERNOR_ABI,
|
|
352
|
-
functionName: "setMaxStrategyDuration",
|
|
353
|
-
args: [seconds]
|
|
354
|
-
});
|
|
355
|
-
const receipt = await waitForReceipt(hash);
|
|
356
|
-
return receipt.transactionHash;
|
|
355
|
+
async function setMaxPerformanceFeeBps(vault, bps) {
|
|
356
|
+
return setGovernorParam(vault, "setMaxPerformanceFeeBps", bps);
|
|
357
357
|
}
|
|
358
|
-
async function
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
abi: SYNDICATE_GOVERNOR_ABI,
|
|
364
|
-
functionName: "setCooldownPeriod",
|
|
365
|
-
args: [seconds]
|
|
366
|
-
});
|
|
367
|
-
const receipt = await waitForReceipt(hash);
|
|
368
|
-
return receipt.transactionHash;
|
|
358
|
+
async function setMaxStrategyDuration(vault, seconds) {
|
|
359
|
+
return setGovernorParam(vault, "setMaxStrategyDuration", seconds);
|
|
360
|
+
}
|
|
361
|
+
async function setCooldownPeriod(vault, seconds) {
|
|
362
|
+
return setGovernorParam(vault, "setCooldownPeriod", seconds);
|
|
369
363
|
}
|
|
370
|
-
async function vetoProposal(proposalId) {
|
|
364
|
+
async function vetoProposal(vault, proposalId) {
|
|
371
365
|
const hash = await writeContractWithRetry({
|
|
372
366
|
account: getAccount(),
|
|
373
367
|
chain: getChain(),
|
|
374
|
-
address:
|
|
368
|
+
address: await getGovernorOf(vault),
|
|
375
369
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
376
370
|
functionName: "vetoProposal",
|
|
377
371
|
args: [proposalId]
|
|
@@ -383,8 +377,8 @@ async function setProtocolFeeBps(bps) {
|
|
|
383
377
|
const hash = await writeContractWithRetry({
|
|
384
378
|
account: getAccount(),
|
|
385
379
|
chain: getChain(),
|
|
386
|
-
address:
|
|
387
|
-
abi:
|
|
380
|
+
address: await getProtocolConfigAddress(),
|
|
381
|
+
abi: PROTOCOL_CONFIG_ABI,
|
|
388
382
|
functionName: "setProtocolFeeBps",
|
|
389
383
|
args: [bps]
|
|
390
384
|
});
|
|
@@ -396,8 +390,11 @@ export {
|
|
|
396
390
|
PROPOSAL_STATES,
|
|
397
391
|
PROPOSAL_STATE,
|
|
398
392
|
VOTE_TYPE,
|
|
393
|
+
evaluateExecuteGate,
|
|
394
|
+
classifyReview,
|
|
399
395
|
parseDuration,
|
|
400
|
-
|
|
396
|
+
getGovernorOf,
|
|
397
|
+
getProtocolConfigAddress,
|
|
401
398
|
getGovernorParams,
|
|
402
399
|
getProposal,
|
|
403
400
|
getProposalState,
|
|
@@ -406,11 +403,10 @@ export {
|
|
|
406
403
|
hasVoted,
|
|
407
404
|
getExecuteCalls,
|
|
408
405
|
getSettlementCalls,
|
|
409
|
-
getRegisteredVaults,
|
|
410
406
|
getActiveProposal,
|
|
411
407
|
getCooldownEnd,
|
|
408
|
+
openProposalCount,
|
|
412
409
|
getCapitalSnapshot,
|
|
413
|
-
isRegisteredVault,
|
|
414
410
|
parseProposalIdFromLogs,
|
|
415
411
|
propose,
|
|
416
412
|
vote,
|
|
@@ -429,4 +425,4 @@ export {
|
|
|
429
425
|
vetoProposal,
|
|
430
426
|
setProtocolFeeBps
|
|
431
427
|
};
|
|
432
|
-
//# sourceMappingURL=chunk-
|
|
428
|
+
//# sourceMappingURL=chunk-S6XA7PK4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/governor.ts"],"sourcesContent":["/**\n * Governor contract wrapper — reads/writes to SyndicateGovernor.\n *\n * Per-vault governor design: the factory deploys ONE governor per vault\n * (BeaconProxy). Every helper takes the vault address and resolves its\n * governor via `factory.governorOf(vault)` (memoized per chain+vault —\n * the binding is set once at createSyndicate and never changes).\n *\n * Protocol-wide fee parameters (protocol/guardian fee bps + recipients)\n * live on the separate ProtocolConfig contract, resolved via\n * `factory.protocolConfig()`.\n */\n\nimport type { Address, Hex, Log } from \"viem\";\nimport { parseEventLogs } from \"viem\";\nimport { getPublicClient, getAccount, writeContractWithRetry, waitForReceipt } from \"./client.js\";\nimport { getChain } from \"./network.js\";\nimport { SHERWOOD } from \"./addresses.js\";\nimport { SYNDICATE_GOVERNOR_ABI, SYNDICATE_FACTORY_ABI, PROTOCOL_CONFIG_ABI } from \"./abis.js\";\n\n// ── Types ──\n\nexport interface GovernorParams {\n votingPeriod: bigint;\n executionWindow: bigint;\n vetoThresholdBps: bigint;\n maxPerformanceFeeBps: bigint;\n cooldownPeriod: bigint;\n collaborationWindow: bigint;\n maxCoProposers: bigint;\n minStrategyDuration: bigint;\n maxStrategyDuration: bigint;\n}\n\nexport interface StrategyProposal {\n id: bigint;\n proposer: Address;\n vault: Address;\n /** Strategy contract address whose `positionValue()` the vault polls\n * for live NAV. Set at propose time, immutable thereafter. address(0)\n * for queue-only proposals (no live NAV). */\n strategy: Address;\n metadataURI: string;\n /** Agent fee (bps) snapshotted from the vault's `agentFeeBps` at propose. */\n performanceFeeBps: bigint;\n strategyDuration: bigint;\n votesFor: bigint;\n votesAgainst: bigint;\n votesAbstain: bigint;\n snapshotTimestamp: bigint;\n voteEnd: bigint;\n reviewEnd: bigint;\n executeBy: bigint;\n executedAt: bigint;\n state: number;\n vetoThresholdBps: bigint;\n /** Fee snapshot taken from ProtocolConfig at propose time (PR #421). These\n * four fields sit between `vetoThresholdBps` and `selfManagesFees` in the\n * on-chain `StrategyProposal` struct — omitting them corrupts tuple decode. */\n snapshotProtocolFeeBps: bigint;\n snapshotProtocolFeeRecipient: Address;\n snapshotGuardianFeeBps: bigint;\n snapshotGuardiansFeeRecipient: Address;\n /** `IStrategy.selfManagesFees()` snapshotted at propose (PR #388 #2); read\n * from storage at settle so it can't flip mid-flight or brick settlement. */\n selfManagesFees: boolean;\n}\n\nexport interface CoProposer {\n agent: Address;\n splitBps: bigint;\n}\n\nexport interface BatchCall {\n target: Address;\n data: Hex;\n value: bigint;\n}\n\n// Must match Solidity ISyndicateGovernor.ProposalState ordering. PR #229\n// inserted GuardianReview at index 2, shifting every subsequent state by\n// one. Without this fix, the CLI mislabels Approved (3) as Rejected,\n// Executed (6) as Settled, etc. — and `proposal execute` rejects valid\n// approved proposals.\nexport const PROPOSAL_STATES = [\n \"Draft\",\n \"Pending\",\n \"GuardianReview\",\n \"Approved\",\n \"Rejected\",\n \"Expired\",\n \"Executed\",\n \"Settled\",\n \"Cancelled\",\n] as const;\n\nexport const PROPOSAL_STATE = {\n Draft: 0,\n Pending: 1,\n GuardianReview: 2,\n Approved: 3,\n Rejected: 4,\n Expired: 5,\n Executed: 6,\n Settled: 7,\n Cancelled: 8,\n} as const;\n\nexport const VOTE_TYPE = {\n For: 0,\n Against: 1,\n Abstain: 2,\n} as const;\n\n// ── Client-side action gates (mirror SyndicateGovernor) ──\n//\n// The governor's mutating entrypoints resolve state INLINE and can act on a\n// state the read-only `getProposalState` view is still reporting as\n// GuardianReview. The client gates below reproduce that divergence so the CLI\n// stops refusing txs the contract would accept (issue #452).\n\n/** Result of the `proposal execute` client gate. */\nexport type ExecuteGate =\n | { kind: \"send\" } // state == Approved — straightforward execute.\n | { kind: \"send-self-resolve\" } // GuardianReview, window elapsed, still within\n // the execution window — executeProposal\n // self-resolves the (cold-start) review inline.\n | { kind: \"refuse-review-open\" } // GuardianReview, review window still open — the\n // tx WOULD revert (ProposalNotApproved).\n | { kind: \"refuse-expired\" } // GuardianReview past executeBy — the inline\n // self-resolve maps to Expired, tx WOULD revert.\n | { kind: \"refuse-state\" }; // any other non-executable state.\n\n/**\n * Decide whether `executeProposal(id)` should be broadcast.\n *\n * Mirrors `SyndicateGovernor.executeProposal` (contracts/src/SyndicateGovernor.sol:342)\n * vs. the `getProposalState` view:\n * - The view (`_resolveStateView` @824 / `_resolveAfterVote` @865) keeps\n * reporting `GuardianReview` once the review window elapses but the registry\n * has not cached a resolution — a zero-guardian / never-opened cold-start\n * review NEVER auto-opens, so the view is stuck there indefinitely.\n * - `executeProposal` runs the MUTATING `_resolveState` (@789) which, when the\n * window elapsed (`now > reviewEnd`), calls `registry.resolveReview` inline\n * (cold-start ⇒ blocked=false) and maps to Approved when `now <= executeBy`\n * (else Expired) — then executes in the same tx.\n * Invariant `voteEnd < reviewEnd < executeBy` (@528-530) holds for any past-vote\n * proposal, so `reviewEnd`/`executeBy` are always populated in the GuardianReview\n * branch.\n *\n * `now` MUST be chain time (latest block timestamp), not wall-clock — on a\n * time-warped vnet the two diverge and the contract compares against chain time.\n */\nexport function evaluateExecuteGate(args: {\n state: number;\n reviewEnd: bigint;\n executeBy: bigint;\n now: bigint;\n}): ExecuteGate {\n const { state, reviewEnd, executeBy, now } = args;\n if (state === PROPOSAL_STATE.Approved) return { kind: \"send\" };\n if (state === PROPOSAL_STATE.GuardianReview) {\n if (now <= reviewEnd) return { kind: \"refuse-review-open\" };\n if (now > executeBy) return { kind: \"refuse-expired\" };\n return { kind: \"send-self-resolve\" };\n }\n return { kind: \"refuse-state\" };\n}\n\n/**\n * Classification for the `resolve-reviews` keeper.\n * - `resolvable`: an OPENED, unresolved review past its window — needs a real\n * `resolveReview` tx (computes block quorum, may slash approvers).\n * - `cold-start`: an UNOPENED, unresolved review past its window — the\n * zero-guardian case. `resolveReview` would only mark it resolved/not-blocked\n * (GuardianRegistry.resolveReview @639-643), which `executeProposal`\n * already does inline, so the keeper should report it (pointing at\n * `proposal execute`) rather than spend a redundant tx.\n * - `none`: not past window yet, or already resolved.\n */\nexport type ReviewResolveClass = \"resolvable\" | \"cold-start\" | \"none\";\n\nexport function classifyReview(args: {\n opened: boolean;\n resolved: boolean;\n reviewEnd: bigint;\n now: bigint;\n}): ReviewResolveClass {\n const { opened, resolved, reviewEnd, now } = args;\n const pastWindow = reviewEnd > 0n && now >= reviewEnd;\n if (!pastWindow || resolved) return \"none\";\n return opened ? \"resolvable\" : \"cold-start\";\n}\n\n// ── Duration parser ──\n\nexport function parseDuration(input: string): bigint {\n const match = input.match(/^(\\d+)(d|h|m|s)?$/);\n if (!match) throw new Error(`Invalid duration: ${input}`);\n const value = BigInt(match[1]);\n switch (match[2]) {\n case \"d\":\n return value * 86400n;\n case \"h\":\n return value * 3600n;\n case \"m\":\n return value * 60n;\n case \"s\":\n case undefined:\n return value;\n default:\n throw new Error(`Unknown duration unit: ${match[2]}`);\n }\n}\n\n// ── Address helpers ──\n\n// governorOf(vault) is set once at createSyndicate and never rebinds, so\n// it is safe to memoize per chain+vault for the lifetime of the process.\nconst governorCache = new Map<string, Address>();\n\n/** Resolve the per-vault governor via `factory.governorOf(vault)`. */\nexport async function getGovernorOf(vault: Address): Promise<Address> {\n const key = `${getChain().id}:${vault.toLowerCase()}`;\n const cached = governorCache.get(key);\n if (cached) return cached;\n\n const client = getPublicClient();\n const governor = await client.readContract({\n address: SHERWOOD().FACTORY,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"governorOf\",\n args: [vault],\n }) as Address;\n\n if (governor === \"0x0000000000000000000000000000000000000000\") {\n throw new Error(`No governor registered for vault ${vault} — is it a factory-created vault?`);\n }\n\n governorCache.set(key, governor);\n return governor;\n}\n\n// ProtocolConfig is a protocol-wide singleton behind the factory — same\n// set-once semantics as governorOf, memoized per chain.\nconst protocolConfigCache = new Map<number, Address>();\n\n/** Resolve the ProtocolConfig address via `factory.protocolConfig()`. */\nexport async function getProtocolConfigAddress(): Promise<Address> {\n const chainId = getChain().id;\n const cached = protocolConfigCache.get(chainId);\n if (cached) return cached;\n\n const client = getPublicClient();\n const config = await client.readContract({\n address: SHERWOOD().FACTORY,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"protocolConfig\",\n }) as Address;\n\n protocolConfigCache.set(chainId, config);\n return config;\n}\n\n// ── Read helpers ──\n\nexport async function getGovernorParams(vault: Address): Promise<GovernorParams> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getGovernorParams\",\n }) as {\n votingPeriod: bigint;\n executionWindow: bigint;\n vetoThresholdBps: bigint;\n maxPerformanceFeeBps: bigint;\n cooldownPeriod: bigint;\n collaborationWindow: bigint;\n maxCoProposers: bigint;\n minStrategyDuration: bigint;\n maxStrategyDuration: bigint;\n };\n return result;\n}\n\nexport async function getProposal(vault: Address, id: bigint): Promise<StrategyProposal> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getProposal\",\n args: [id],\n }) as StrategyProposal;\n return result;\n}\n\nexport async function getProposalState(vault: Address, id: bigint): Promise<number> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getProposalState\",\n args: [id],\n }) as Promise<number>;\n}\n\nexport async function proposalCount(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"proposalCount\",\n }) as Promise<bigint>;\n}\n\nexport async function getVoteWeight(vault: Address, proposalId: bigint, voter: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getVoteWeight\",\n args: [proposalId, voter],\n }) as Promise<bigint>;\n}\n\nexport async function hasVoted(vault: Address, proposalId: bigint, voter: Address): Promise<boolean> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"hasVoted\",\n args: [proposalId, voter],\n }) as Promise<boolean>;\n}\n\n// `getProposalCalls` (concat of execute + settle) was dropped in V1.5\n// to reclaim governor bytecode under EIP-170. Use `getExecuteCalls`\n// + `getSettlementCalls` instead — same data, no on-chain copy loop.\n\nexport async function getExecuteCalls(vault: Address, proposalId: bigint): Promise<BatchCall[]> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getExecuteCalls\",\n args: [proposalId],\n }) as { target: Address; data: Hex; value: bigint }[];\n return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));\n}\n\nexport async function getSettlementCalls(vault: Address, proposalId: bigint): Promise<BatchCall[]> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getSettlementCalls\",\n args: [proposalId],\n }) as { target: Address; data: Hex; value: bigint }[];\n return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));\n}\n\n// Per-vault governor: `getRegisteredVaults` / `isRegisteredVault` were\n// removed on-chain — a governor serves exactly one vault (`governor.vault()`).\n// Enumerate vaults via the factory (`getAllActiveSyndicates`) instead.\n\nexport async function getActiveProposal(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getActiveProposal\",\n }) as Promise<bigint>;\n}\n\nexport async function getCooldownEnd(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getCooldownEnd\",\n }) as Promise<bigint>;\n}\n\nexport async function openProposalCount(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"openProposalCount\",\n }) as Promise<bigint>;\n}\n\nexport async function getCapitalSnapshot(vault: Address, proposalId: bigint): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getCapitalSnapshot\",\n args: [proposalId],\n }) as Promise<bigint>;\n}\n\n/**\n * Extract proposalId from ProposalCreated event logs.\n * Returns undefined if the event is not found or parsing fails.\n */\nexport function parseProposalIdFromLogs(logs: Log[]): bigint | undefined {\n try {\n const parsed = parseEventLogs({\n abi: SYNDICATE_GOVERNOR_ABI,\n logs,\n eventName: \"ProposalCreated\",\n });\n return parsed[0]?.args.proposalId;\n } catch {\n return undefined;\n }\n}\n\n// ── Write helpers ──\n\nexport async function propose(\n vault: Address,\n strategy: Address,\n metadataURI: string,\n strategyDuration: bigint,\n executeCalls: BatchCall[],\n settlementCalls: BatchCall[],\n coProposers: CoProposer[] = [],\n): Promise<{ hash: Hex; proposalId: bigint }> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"propose\",\n args: [vault, strategy, metadataURI, strategyDuration, executeCalls, settlementCalls, coProposers],\n });\n\n const receipt = await waitForReceipt(hash);\n\n // Parse proposalId from the ProposalCreated event in the receipt logs.\n // Falls back to proposalCount() if event parsing fails.\n let proposalId = parseProposalIdFromLogs(receipt.logs);\n if (proposalId === undefined) {\n try {\n proposalId = await proposalCount(vault);\n } catch {\n proposalId = 0n;\n }\n }\n\n return { hash: receipt.transactionHash, proposalId };\n}\n\nexport async function vote(vault: Address, proposalId: bigint, support: number): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"vote\",\n args: [proposalId, support],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function executeProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"executeProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n/**\n * Walk a proposal's executeCalls and pick the strategy clone — the\n * target of the call whose selector matches `BaseStrategy.execute()`\n * (0x61461954). This is the canonical entry point that every Sherwood\n * strategy template inherits from BaseStrategy, so it's a reliable\n * marker even across template families (Moonwell / Aerodrome /\n * Hyperliquid / Mamo / Venice / Portfolio).\n *\n * Returns null when no execute() call is present (e.g. proposals that\n * only do approves and direct ERC-20 transfers without a strategy).\n */\nexport function detectStrategyAdapter(\n calls: { target: Address; data: Hex; value: bigint }[],\n): Address | null {\n const STRATEGY_EXECUTE_SELECTOR = \"0x61461954\";\n for (const call of calls) {\n if (call.data.slice(0, 10).toLowerCase() === STRATEGY_EXECUTE_SELECTOR) {\n return call.target;\n }\n }\n return null;\n}\n\nexport async function settleProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"settleProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function emergencySettle(vault: Address, proposalId: bigint, calls: BatchCall[]): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"emergencySettleWithCalls\",\n args: [proposalId, calls],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function cancelProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"cancelProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function emergencyCancel(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"emergencyCancel\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n// ── Parameter setters ──\n//\n// Per-vault governor: governance parameters are per-vault now, set by the\n// VAULT OWNER on that vault's governor. Setters revert with\n// `ParamsFrozenDuringProposal` while any proposal is open on the vault.\n\ntype GovernorParamSetter =\n | \"setVotingPeriod\"\n | \"setExecutionWindow\"\n | \"setVetoThresholdBps\"\n | \"setMaxPerformanceFeeBps\"\n | \"setMaxStrategyDuration\"\n | \"setCooldownPeriod\";\n\nasync function setGovernorParam(\n vault: Address,\n functionName: GovernorParamSetter,\n value: bigint,\n): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName,\n args: [value],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function setVotingPeriod(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setVotingPeriod\", seconds);\n}\n\nexport async function setExecutionWindow(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setExecutionWindow\", seconds);\n}\n\nexport async function setVetoThresholdBps(vault: Address, bps: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setVetoThresholdBps\", bps);\n}\n\nexport async function setMaxPerformanceFeeBps(vault: Address, bps: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setMaxPerformanceFeeBps\", bps);\n}\n\nexport async function setMaxStrategyDuration(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setMaxStrategyDuration\", seconds);\n}\n\nexport async function setCooldownPeriod(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setCooldownPeriod\", seconds);\n}\n\nexport async function vetoProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"vetoProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n// ── ProtocolConfig fee setters (protocol-owner only) ──\n//\n// Fee parameters moved off the governor onto the protocol-wide\n// ProtocolConfig contract (resolved via `factory.protocolConfig()`).\n\nexport async function setProtocolFeeBps(bps: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getProtocolConfigAddress(),\n abi: PROTOCOL_CONFIG_ABI,\n functionName: \"setProtocolFeeBps\",\n args: [bps],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n"],"mappings":"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","names":[]}
|