@sherwoodagent/cli 0.86.0 → 0.86.1
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/{chat-PRYOT3ZV.js → chat-ETZSKQDI.js} +5 -5
- package/dist/{chunk-ARSQ5UQA.js → chunk-3IAZQMAW.js} +2 -2
- package/dist/{chunk-LRUSZUEU.js → chunk-6QBGTX2Q.js} +87 -13
- package/dist/chunk-6QBGTX2Q.js.map +1 -0
- package/dist/{chunk-HODME7UJ.js → chunk-EA65CDQH.js} +2 -2
- package/dist/{chunk-53W6CYYV.js → chunk-EVUKJ7CJ.js} +2 -2
- package/dist/{chunk-AM6MI2JF.js → chunk-IAM4VIU2.js} +146 -23
- package/dist/chunk-IAM4VIU2.js.map +1 -0
- package/dist/{chunk-M4GX5PL2.js → chunk-OUYMZ5ZC.js} +2 -2
- package/dist/{chunk-5NFAEOFG.js → chunk-XPVXNG2K.js} +3 -3
- package/dist/{chunk-6N7EVSAZ.js → chunk-YAS52NEF.js} +19 -6
- package/dist/{chunk-6N7EVSAZ.js.map → chunk-YAS52NEF.js.map} +1 -1
- package/dist/{chunk-I2BBOJNC.js → chunk-ZN2MHIB7.js} +2 -2
- package/dist/{eas-D3BVHBJH.js → eas-KMDAMLXW.js} +3 -3
- package/dist/{governor-35IXAEDJ.js → governor-JNSWPJVQ.js} +7 -5
- package/dist/{identity-XOAYQFUW.js → identity-ATWV2O7Y.js} +4 -4
- package/dist/index.js +101 -35
- package/dist/index.js.map +1 -1
- package/dist/{price-I5T77X7Y.js → price-YNPYE2EO.js} +3 -3
- package/dist/{research-NKGP3M4J.js → research-W74PNYPO.js} +3 -3
- package/dist/{session-LJT3SAED.js → session-HVRZ6AJM.js} +6 -6
- package/dist/{trade-OTZ7UHDK.js → trade-EOQY72L7.js} +6 -6
- package/dist/{vault-7O4N6WZG.js → vault-HWJQJW5U.js} +5 -5
- package/dist/{xmtp-R25Q5GWY.js → xmtp-KW73BGVO.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-AM6MI2JF.js.map +0 -1
- package/dist/chunk-LRUSZUEU.js.map +0 -1
- /package/dist/{chat-PRYOT3ZV.js.map → chat-ETZSKQDI.js.map} +0 -0
- /package/dist/{chunk-ARSQ5UQA.js.map → chunk-3IAZQMAW.js.map} +0 -0
- /package/dist/{chunk-HODME7UJ.js.map → chunk-EA65CDQH.js.map} +0 -0
- /package/dist/{chunk-53W6CYYV.js.map → chunk-EVUKJ7CJ.js.map} +0 -0
- /package/dist/{chunk-M4GX5PL2.js.map → chunk-OUYMZ5ZC.js.map} +0 -0
- /package/dist/{chunk-5NFAEOFG.js.map → chunk-XPVXNG2K.js.map} +0 -0
- /package/dist/{chunk-I2BBOJNC.js.map → chunk-ZN2MHIB7.js.map} +0 -0
- /package/dist/{eas-D3BVHBJH.js.map → eas-KMDAMLXW.js.map} +0 -0
- /package/dist/{governor-35IXAEDJ.js.map → governor-JNSWPJVQ.js.map} +0 -0
- /package/dist/{identity-XOAYQFUW.js.map → identity-ATWV2O7Y.js.map} +0 -0
- /package/dist/{price-I5T77X7Y.js.map → price-YNPYE2EO.js.map} +0 -0
- /package/dist/{research-NKGP3M4J.js.map → research-W74PNYPO.js.map} +0 -0
- /package/dist/{session-LJT3SAED.js.map → session-HVRZ6AJM.js.map} +0 -0
- /package/dist/{trade-OTZ7UHDK.js.map → trade-EOQY72L7.js.map} +0 -0
- /package/dist/{vault-7O4N6WZG.js.map → vault-HWJQJW5U.js.map} +0 -0
- /package/dist/{xmtp-R25Q5GWY.js.map → xmtp-KW73BGVO.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/governor.ts","../src/lib/generated/proposal-state.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\";\nimport { PROPOSAL_STATE, PROPOSAL_STATES } from \"./generated/proposal-state.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-recipient snapshot taken from ProtocolConfig at propose time.\n *\n * THE FLAT `snapshot*FeeBps` SCALARS AND `selfManagesFees` ARE GONE: the\n * splits became structs (`snapshotMgmtSplit`/`snapshotPerfSplit` below) and\n * self-managed fees were removed outright. Every field below is positional\n * in the on-chain tuple — omitting or reordering one corrupts the decode of\n * everything after it. */\n snapshotProtocolFeeRecipient: Address;\n snapshotGuardiansFeeRecipient: Address;\n /** Risk envelope declared at propose: the net-outflow ceiling the execute\n * batch is metered against. */\n maxCapital: bigint;\n /** Declared drawdown bound, bps of `effectiveMaxCapital`. */\n maxDrawdownBps: number;\n /** Tier the envelope resolved to; drives how much coverage is required. */\n envelopeTier: number;\n requiredCoverage: bigint;\n /** WOOD bond pulled from the proposer at propose, held by the escrow. */\n proposerBondWood: bigint;\n proposerBondEscrow: Address;\n /** Management-fee split snapshotted from ProtocolConfig at propose. */\n snapshotMgmtSplit: { agentBps: number; protocolBps: number; guardianBps: number };\n /** Performance-fee split snapshotted from ProtocolConfig at propose. */\n snapshotPerfSplit: { agentBps: number; protocolBps: number; guardianBps: number; ownerBps: number };\n /** The ledger the bond's reclaim gates read — bound alongside the escrow so\n * re-pointing either slot later cannot strand the bond. */\n proposerBondLedger: Address;\n /** `maxCapital` after any scaling applied at execute. */\n effectiveMaxCapital: bigint;\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// ProposalState ordering is code-generated from the Solidity enum\n// (contracts/src/interfaces/ISyndicateGovernor.sol) — `npm run codegen`.\n// History: PR #229 inserted GuardianReview at index 2 and this hand-kept\n// mirror drifted for ~2 months, mislabeling Approved (3) as Rejected and\n// making `proposal execute` reject valid approved proposals. The generated\n// module (checked by codegen-drift.test.ts + CI) makes that impossible.\nexport { PROPOSAL_STATE, PROPOSAL_STATES };\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/**\n * Classification for the `open-reviews` keeper (SHE-162), the other leg of\n * `classifyReview`: `GuardianRegistry.openReview(governor, proposalId)` is\n * permissionless, and an unopened review clears by default (`outcomeOf`:\n * `if (!r.opened) return ReviewOutcome.Cleared;`) — nobody opening it means\n * proposals execute unreviewed.\n * - `openable`: a registered, unopened, unresolved review inside the open\n * window `[voteEnd, reviewEnd)` — needs an `openReview` keeper tx.\n * - `none`: never registered (collapsed window, `reviewEnd <= voteEnd`),\n * already opened or resolved, or outside the window. Past `reviewEnd`\n * opening is pointless — that is `classifyReview`'s territory.\n */\nexport type ReviewOpenClass = \"openable\" | \"none\";\n\nexport function classifyReviewOpen(args: {\n opened: boolean;\n resolved: boolean;\n voteEnd: bigint;\n reviewEnd: bigint;\n now: bigint;\n}): ReviewOpenClass {\n const { opened, resolved, voteEnd, reviewEnd, now } = args;\n // Collapsed window ⇒ the review was never registered with the registry;\n // openReview would revert ReviewNotOpen (r.voteEnd == 0).\n const registered = voteEnd > 0n && reviewEnd > voteEnd;\n // Contract gate is `now >= voteEnd` (inclusive); past reviewEnd the open\n // is moot — the review resolves/clears without it.\n const inWindow = now >= voteEnd && now < reviewEnd;\n if (!registered || !inWindow || opened || resolved) return \"none\";\n return \"openable\";\n}\n\n/**\n * Per-proposal scan step shared by the `open-reviews` / `resolve-reviews`\n * keepers. Runs `load` for every id concurrently; an id whose load throws is\n * RECORDED in `failures` (id + error), never silently swallowed — a systemic\n * failure (e.g. an ABI mismatch, the SHE-88/SHE-49 class) must surface as\n * \"N of M failed to load\", not as a clean \"nothing to do\". The loadable ids\n * are still returned so the keeper can process every candidate it CAN see.\n */\nexport interface ReviewScanFailure {\n id: bigint;\n error: unknown;\n}\n\nexport async function scanReviewCandidates<T>(\n ids: readonly bigint[],\n load: (id: bigint) => Promise<T>,\n): Promise<{ candidates: T[]; failures: ReviewScanFailure[] }> {\n const failures: ReviewScanFailure[] = [];\n const settled = await Promise.all(\n ids.map(async (id): Promise<{ ok: true; value: T } | { ok: false }> => {\n try {\n return { ok: true, value: await load(id) };\n } catch (error) {\n failures.push({ id, error });\n return { ok: false };\n }\n }),\n );\n const candidates: T[] = [];\n for (const s of settled) if (s.ok) candidates.push(s.value);\n return { candidates, failures };\n}\n\n/**\n * A mined-but-REVERTED tx still yields a receipt — `waitForReceipt` resolves\n * with `status: \"reverted\"` and does not throw. A keeper counting that as a\n * success would report \"opened/resolved\" for a tx that changed nothing. Call\n * this on every keeper receipt: it throws (like a send failure) unless the\n * tx actually succeeded, so the caller's catch path drives the exit code.\n */\nexport function assertReceiptSuccess(receipt: { status: string }): void {\n if (receipt.status !== \"success\") {\n throw new Error(`transaction mined but reverted on-chain (status=${receipt.status})`);\n }\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\n/**\n * The risk envelope a proposal commits to.\n *\n * `maxCapital` is in ASSET UNITS (the vault's own asset, at its decimals), not\n * a share. `maxDrawdownBps` is the declared loss allowance in basis points,\n * 0..10_000, and is what the settle-price guard sizes its tolerance from — so\n * it is a real declaration to voters and guardians, not a formality.\n */\nexport interface RiskEnvelope {\n maxCapital: bigint;\n maxDrawdownBps: number;\n}\n\n/**\n * @param executeCallCaps one entry per execute call, in ASSET UNITS: the\n * maximum GROSS OUTFLOW of the vault asset measured around that call. A call\n * that moves nothing out (an `approve`, or a settlement that only returns\n * assets) takes 0. Summed per batch and required to be <= `maxCapital`;\n * the execute and settlement batches are bounded independently because they\n * run in separate transactions.\n */\nexport async function propose(\n vault: Address,\n strategy: Address,\n metadataURI: string,\n strategyDuration: bigint,\n envelope: RiskEnvelope,\n executeCalls: BatchCall[],\n executeCallCaps: bigint[],\n settlementCalls: BatchCall[],\n settlementCallCaps: bigint[],\n coProposers: CoProposer[] = [],\n): Promise<{ hash: Hex; proposalId: bigint }> {\n // Fail here rather than as an on-chain `CallCapsLengthMismatch` — the\n // governor's revert names the mismatch but not which batch, and a caller that\n // built the arrays in different places will not know.\n if (executeCallCaps.length !== executeCalls.length) {\n throw new Error(\n `executeCallCaps has ${executeCallCaps.length} entries for ${executeCalls.length} execute calls — every call must declare exactly one cap`,\n );\n }\n if (settlementCallCaps.length !== settlementCalls.length) {\n throw new Error(\n `settlementCallCaps has ${settlementCallCaps.length} entries for ${settlementCalls.length} settlement calls — every call must declare exactly one cap`,\n );\n }\n\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: [\n vault,\n strategy,\n metadataURI,\n strategyDuration,\n { maxCapital: envelope.maxCapital, maxDrawdownBps: envelope.maxDrawdownBps },\n executeCalls,\n executeCallCaps,\n settlementCalls,\n settlementCallCaps,\n coProposers,\n ],\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","/**\n * AUTO-GENERATED by cli/scripts/codegen-contracts.ts — do not edit.\n * Regenerate: npm run codegen (in cli/)\n *\n * Source of truth: sherwood-protocol src/interfaces/ISyndicateGovernor.sol (enum ProposalState)\n */\n\n/** On-chain `ProposalState` member names, index === Solidity enum value. */\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 type ProposalStateName = (typeof PROPOSAL_STATES)[number];\n\n/** Name → Solidity enum value. */\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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/governor.ts","../src/lib/generated/proposal-state.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\";\nimport { PROPOSAL_STATE, PROPOSAL_STATES } from \"./generated/proposal-state.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-recipient snapshot taken from ProtocolConfig at propose time.\n *\n * THE FLAT `snapshot*FeeBps` SCALARS AND `selfManagesFees` ARE GONE: the\n * splits became structs (`snapshotMgmtSplit`/`snapshotPerfSplit` below) and\n * self-managed fees were removed outright. Every field below is positional\n * in the on-chain tuple — omitting or reordering one corrupts the decode of\n * everything after it. */\n snapshotProtocolFeeRecipient: Address;\n snapshotGuardiansFeeRecipient: Address;\n /** Risk envelope declared at propose: the net-outflow ceiling the execute\n * batch is metered against. */\n maxCapital: bigint;\n /** Declared drawdown bound, bps of `effectiveMaxCapital`. */\n maxDrawdownBps: number;\n /** Tier the envelope resolved to; drives how much coverage is required. */\n envelopeTier: number;\n requiredCoverage: bigint;\n /** WOOD bond pulled from the proposer at propose, held by the escrow. */\n proposerBondWood: bigint;\n proposerBondEscrow: Address;\n /** Management-fee split snapshotted from ProtocolConfig at propose. */\n snapshotMgmtSplit: { agentBps: number; protocolBps: number; guardianBps: number };\n /** Performance-fee split snapshotted from ProtocolConfig at propose. */\n snapshotPerfSplit: { agentBps: number; protocolBps: number; guardianBps: number; ownerBps: number };\n /** The ledger the bond's reclaim gates read — bound alongside the escrow so\n * re-pointing either slot later cannot strand the bond. */\n proposerBondLedger: Address;\n /** `maxCapital` after any scaling applied at execute. */\n effectiveMaxCapital: bigint;\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// ProposalState ordering is code-generated from the Solidity enum\n// (contracts/src/interfaces/ISyndicateGovernor.sol) — `npm run codegen`.\n// History: PR #229 inserted GuardianReview at index 2 and this hand-kept\n// mirror drifted for ~2 months, mislabeling Approved (3) as Rejected and\n// making `proposal execute` reject valid approved proposals. The generated\n// module (checked by codegen-drift.test.ts + CI) makes that impossible.\nexport { PROPOSAL_STATE, PROPOSAL_STATES };\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/**\n * Classification for the `open-reviews` keeper (SHE-162), the other leg of\n * `classifyReview`: `GuardianRegistry.openReview(governor, proposalId)` is\n * permissionless, and an unopened review clears by default (`outcomeOf`:\n * `if (!r.opened) return ReviewOutcome.Cleared;`) — nobody opening it means\n * proposals execute unreviewed.\n * - `openable`: a registered, unopened, unresolved review inside the open\n * window `[voteEnd, reviewEnd)` — needs an `openReview` keeper tx.\n * - `none`: never registered (collapsed window, `reviewEnd <= voteEnd`),\n * already opened or resolved, or outside the window. Past `reviewEnd`\n * opening is pointless — that is `classifyReview`'s territory.\n */\nexport type ReviewOpenClass = \"openable\" | \"none\";\n\nexport function classifyReviewOpen(args: {\n opened: boolean;\n resolved: boolean;\n voteEnd: bigint;\n reviewEnd: bigint;\n now: bigint;\n}): ReviewOpenClass {\n const { opened, resolved, voteEnd, reviewEnd, now } = args;\n // Collapsed window ⇒ the review was never registered with the registry;\n // openReview would revert ReviewNotOpen (r.voteEnd == 0).\n const registered = voteEnd > 0n && reviewEnd > voteEnd;\n // Contract gate is `now >= voteEnd` (inclusive); past reviewEnd the open\n // is moot — the review resolves/clears without it.\n const inWindow = now >= voteEnd && now < reviewEnd;\n if (!registered || !inWindow || opened || resolved) return \"none\";\n return \"openable\";\n}\n\n/**\n * Per-proposal scan step shared by the `open-reviews` / `resolve-reviews`\n * keepers. Runs `load` for every id concurrently; an id whose load throws is\n * RECORDED in `failures` (id + error), never silently swallowed — a systemic\n * failure (e.g. an ABI mismatch, the SHE-88/SHE-49 class) must surface as\n * \"N of M failed to load\", not as a clean \"nothing to do\". The loadable ids\n * are still returned so the keeper can process every candidate it CAN see.\n */\nexport interface ReviewScanFailure {\n id: bigint;\n error: unknown;\n}\n\nexport async function scanReviewCandidates<T>(\n ids: readonly bigint[],\n load: (id: bigint) => Promise<T>,\n): Promise<{ candidates: T[]; failures: ReviewScanFailure[] }> {\n const failures: ReviewScanFailure[] = [];\n const settled = await Promise.all(\n ids.map(async (id): Promise<{ ok: true; value: T } | { ok: false }> => {\n try {\n return { ok: true, value: await load(id) };\n } catch (error) {\n failures.push({ id, error });\n return { ok: false };\n }\n }),\n );\n const candidates: T[] = [];\n for (const s of settled) if (s.ok) candidates.push(s.value);\n return { candidates, failures };\n}\n\n/**\n * A mined-but-REVERTED tx still yields a receipt — `waitForReceipt` resolves\n * with `status: \"reverted\"` and does not throw. A keeper counting that as a\n * success would report \"opened/resolved\" for a tx that changed nothing. Call\n * this on every keeper receipt: it throws (like a send failure) unless the\n * tx actually succeeded, so the caller's catch path drives the exit code.\n */\nexport function assertReceiptSuccess(receipt: { status: string }): void {\n if (receipt.status !== \"success\") {\n throw new Error(`transaction mined but reverted on-chain (status=${receipt.status})`);\n }\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\n/**\n * The risk envelope a proposal commits to.\n *\n * `maxCapital` is in ASSET UNITS (the vault's own asset, at its decimals), not\n * a share. `maxDrawdownBps` is the declared loss allowance in basis points,\n * 0..10_000, and is what the settle-price guard sizes its tolerance from — so\n * it is a real declaration to voters and guardians, not a formality.\n */\nexport interface RiskEnvelope {\n maxCapital: bigint;\n maxDrawdownBps: number;\n}\n\n/**\n * @param executeCallCaps one entry per execute call, in ASSET UNITS: the\n * maximum GROSS OUTFLOW of the vault asset measured around that call. A call\n * that moves nothing out (an `approve`, or a settlement that only returns\n * assets) takes 0. Summed per batch and required to be <= `maxCapital`;\n * the execute and settlement batches are bounded independently because they\n * run in separate transactions.\n */\nexport async function propose(\n vault: Address,\n strategy: Address,\n metadataURI: string,\n strategyDuration: bigint,\n envelope: RiskEnvelope,\n executeCalls: BatchCall[],\n executeCallCaps: bigint[],\n settlementCalls: BatchCall[],\n settlementCallCaps: bigint[],\n coProposers: CoProposer[] = [],\n): Promise<{ hash: Hex; proposalId: bigint }> {\n // Fail here rather than as an on-chain `CallCapsLengthMismatch` — the\n // governor's revert names the mismatch but not which batch, and a caller that\n // built the arrays in different places will not know.\n if (executeCallCaps.length !== executeCalls.length) {\n throw new Error(\n `executeCallCaps has ${executeCallCaps.length} entries for ${executeCalls.length} execute calls — every call must declare exactly one cap`,\n );\n }\n if (settlementCallCaps.length !== settlementCalls.length) {\n throw new Error(\n `settlementCallCaps has ${settlementCallCaps.length} entries for ${settlementCalls.length} settlement calls — every call must declare exactly one cap`,\n );\n }\n\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: [\n vault,\n strategy,\n metadataURI,\n strategyDuration,\n { maxCapital: envelope.maxCapital, maxDrawdownBps: envelope.maxDrawdownBps },\n executeCalls,\n executeCallCaps,\n settlementCalls,\n settlementCallCaps,\n coProposers,\n ],\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-split setters (protocol-owner only) ──\n//\n// Post-audit ProtocolConfig holds no per-rate protocol fee — the two-number\n// model exposes the SPLITS of the management and performance fees instead,\n// on the protocol-wide config (resolved via `factory.protocolConfig()`).\n\nexport interface MgmtSplit {\n agentBps: number;\n protocolBps: number;\n guardianBps: number;\n}\n\nexport interface PerfSplit extends MgmtSplit {\n ownerBps: number;\n}\n\nexport async function setMgmtSplit(s: MgmtSplit): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getProtocolConfigAddress(),\n abi: PROTOCOL_CONFIG_ABI,\n functionName: \"setMgmtSplit\",\n args: [s],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function setPerfSplit(s: PerfSplit): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getProtocolConfigAddress(),\n abi: PROTOCOL_CONFIG_ABI,\n functionName: \"setPerfSplit\",\n args: [s],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n","/**\n * AUTO-GENERATED by cli/scripts/codegen-contracts.ts — do not edit.\n * Regenerate: npm run codegen (in cli/)\n *\n * Source of truth: sherwood-protocol src/interfaces/ISyndicateGovernor.sol (enum ProposalState)\n */\n\n/** On-chain `ProposalState` member names, index === Solidity enum value. */\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 type ProposalStateName = (typeof PROPOSAL_STATES)[number];\n\n/** Name → Solidity enum value. */\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"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ENS,
|
|
3
3
|
SHERWOOD
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IAM4VIU2.js";
|
|
5
5
|
import {
|
|
6
6
|
getPublicClient
|
|
7
7
|
} from "./chunk-QRMZRAMG.js";
|
|
@@ -111,4 +111,4 @@ export {
|
|
|
111
111
|
setTextRecord,
|
|
112
112
|
getTextRecord
|
|
113
113
|
};
|
|
114
|
-
//# sourceMappingURL=chunk-
|
|
114
|
+
//# sourceMappingURL=chunk-ZN2MHIB7.js.map
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
revokeAttestation,
|
|
22
22
|
revokeJoinRequest,
|
|
23
23
|
stripReferrerPrefix
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-OUYMZ5ZC.js";
|
|
25
|
+
import "./chunk-IAM4VIU2.js";
|
|
26
26
|
import "./chunk-QRMZRAMG.js";
|
|
27
27
|
import "./chunk-PVTZMRC6.js";
|
|
28
28
|
import "./chunk-3TZIOAPH.js";
|
|
@@ -51,4 +51,4 @@ export {
|
|
|
51
51
|
revokeJoinRequest,
|
|
52
52
|
stripReferrerPrefix
|
|
53
53
|
};
|
|
54
|
-
//# sourceMappingURL=eas-
|
|
54
|
+
//# sourceMappingURL=eas-KMDAMLXW.js.map
|
|
@@ -33,14 +33,15 @@ import {
|
|
|
33
33
|
setExecutionWindow,
|
|
34
34
|
setMaxPerformanceFeeBps,
|
|
35
35
|
setMaxStrategyDuration,
|
|
36
|
-
|
|
36
|
+
setMgmtSplit,
|
|
37
|
+
setPerfSplit,
|
|
37
38
|
setVetoThresholdBps,
|
|
38
39
|
setVotingPeriod,
|
|
39
40
|
settleProposal,
|
|
40
41
|
vetoProposal,
|
|
41
42
|
vote
|
|
42
|
-
} from "./chunk-
|
|
43
|
-
import "./chunk-
|
|
43
|
+
} from "./chunk-YAS52NEF.js";
|
|
44
|
+
import "./chunk-IAM4VIU2.js";
|
|
44
45
|
import "./chunk-QRMZRAMG.js";
|
|
45
46
|
import "./chunk-PVTZMRC6.js";
|
|
46
47
|
import "./chunk-3TZIOAPH.js";
|
|
@@ -80,11 +81,12 @@ export {
|
|
|
80
81
|
setExecutionWindow,
|
|
81
82
|
setMaxPerformanceFeeBps,
|
|
82
83
|
setMaxStrategyDuration,
|
|
83
|
-
|
|
84
|
+
setMgmtSplit,
|
|
85
|
+
setPerfSplit,
|
|
84
86
|
setVetoThresholdBps,
|
|
85
87
|
setVotingPeriod,
|
|
86
88
|
settleProposal,
|
|
87
89
|
vetoProposal,
|
|
88
90
|
vote
|
|
89
91
|
};
|
|
90
|
-
//# sourceMappingURL=governor-
|
|
92
|
+
//# sourceMappingURL=governor-JNSWPJVQ.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lookupAgentIdByWallet,
|
|
3
3
|
registerIdentityCommands
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-6QBGTX2Q.js";
|
|
5
|
+
import "./chunk-OUYMZ5ZC.js";
|
|
6
|
+
import "./chunk-IAM4VIU2.js";
|
|
7
7
|
import "./chunk-QRMZRAMG.js";
|
|
8
8
|
import "./chunk-PVTZMRC6.js";
|
|
9
9
|
import "./chunk-3TZIOAPH.js";
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
lookupAgentIdByWallet,
|
|
13
13
|
registerIdentityCommands
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=identity-
|
|
15
|
+
//# sourceMappingURL=identity-ATWV2O7Y.js.map
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
parseAlignedOverrides,
|
|
32
32
|
resolveToken,
|
|
33
33
|
selectBestFeeTier
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-3IAZQMAW.js";
|
|
35
35
|
import {
|
|
36
36
|
DEFAULT_ISSUING_CHAIN_ID,
|
|
37
37
|
appendVidTag,
|
|
@@ -47,9 +47,10 @@ import {
|
|
|
47
47
|
encodeGuardianStake,
|
|
48
48
|
encodeGuardianUnstake,
|
|
49
49
|
encodeJoinRequest,
|
|
50
|
+
encodeMgmtSplit,
|
|
51
|
+
encodePerfSplit,
|
|
50
52
|
encodePropose,
|
|
51
53
|
encodeProposeWithSandbox,
|
|
52
|
-
encodeProtocolFeeBps,
|
|
53
54
|
encodeRedeem,
|
|
54
55
|
encodeRegisterAgent,
|
|
55
56
|
encodeSettle,
|
|
@@ -64,7 +65,7 @@ import {
|
|
|
64
65
|
setCalldataOnly,
|
|
65
66
|
stripVidTag,
|
|
66
67
|
verifyVidTag
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-6QBGTX2Q.js";
|
|
68
69
|
import {
|
|
69
70
|
createApproval,
|
|
70
71
|
createJoinRequest,
|
|
@@ -74,20 +75,20 @@ import {
|
|
|
74
75
|
queryJoinRequests,
|
|
75
76
|
revokeJoinRequest,
|
|
76
77
|
stripReferrerPrefix
|
|
77
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-OUYMZ5ZC.js";
|
|
78
79
|
import {
|
|
79
80
|
createFund,
|
|
80
81
|
getActiveFunds,
|
|
81
82
|
getFund,
|
|
82
83
|
subdomainExists,
|
|
83
84
|
updateMetadata
|
|
84
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-EVUKJ7CJ.js";
|
|
85
86
|
import {
|
|
86
87
|
resolveFund,
|
|
87
88
|
resolveVaultFund,
|
|
88
89
|
searchFundAcrossChains,
|
|
89
90
|
setTextRecord
|
|
90
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-ZN2MHIB7.js";
|
|
91
92
|
import {
|
|
92
93
|
approveDepositor,
|
|
93
94
|
deposit,
|
|
@@ -110,8 +111,8 @@ import {
|
|
|
110
111
|
removeDepositor,
|
|
111
112
|
setAgentFeeBps,
|
|
112
113
|
setVaultAddress
|
|
113
|
-
} from "./chunk-
|
|
114
|
-
import "./chunk-
|
|
114
|
+
} from "./chunk-XPVXNG2K.js";
|
|
115
|
+
import "./chunk-EA65CDQH.js";
|
|
115
116
|
import {
|
|
116
117
|
PROPOSAL_STATE,
|
|
117
118
|
PROPOSAL_STATES,
|
|
@@ -144,12 +145,13 @@ import {
|
|
|
144
145
|
setExecutionWindow,
|
|
145
146
|
setMaxPerformanceFeeBps,
|
|
146
147
|
setMaxStrategyDuration,
|
|
147
|
-
|
|
148
|
+
setMgmtSplit,
|
|
149
|
+
setPerfSplit,
|
|
148
150
|
setVetoThresholdBps,
|
|
149
151
|
setVotingPeriod,
|
|
150
152
|
settleProposal,
|
|
151
153
|
vote
|
|
152
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-YAS52NEF.js";
|
|
153
155
|
import {
|
|
154
156
|
AERODROME,
|
|
155
157
|
MOONWELL,
|
|
@@ -158,7 +160,7 @@ import {
|
|
|
158
160
|
TOKENS,
|
|
159
161
|
UNISWAP,
|
|
160
162
|
VENICE
|
|
161
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-IAM4VIU2.js";
|
|
162
164
|
import {
|
|
163
165
|
GAS_UNITS,
|
|
164
166
|
estimateGasCushion,
|
|
@@ -977,7 +979,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
977
979
|
process.exit(1);
|
|
978
980
|
}
|
|
979
981
|
if (!opts.agent) opts.agent = proposer;
|
|
980
|
-
const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-
|
|
982
|
+
const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-JNSWPJVQ.js");
|
|
981
983
|
const strategyDuration2 = parseDuration3(opts.duration);
|
|
982
984
|
const chainId = getChain().id;
|
|
983
985
|
try {
|
|
@@ -1208,9 +1210,9 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
1208
1210
|
console.error(chalk3.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
|
|
1209
1211
|
process.exit(1);
|
|
1210
1212
|
}
|
|
1211
|
-
const { propose: propose2 } = await import("./governor-
|
|
1213
|
+
const { propose: propose2 } = await import("./governor-JNSWPJVQ.js");
|
|
1212
1214
|
const { pinJSON } = await import("./ipfs-M56BLMCW.js");
|
|
1213
|
-
const { parseDuration: parseDuration2 } = await import("./governor-
|
|
1215
|
+
const { parseDuration: parseDuration2 } = await import("./governor-JNSWPJVQ.js");
|
|
1214
1216
|
const strategyDuration = parseDuration2(opts.duration);
|
|
1215
1217
|
const metaSpinner = ora2("Pinning metadata to IPFS...").start();
|
|
1216
1218
|
let metadataURI;
|
|
@@ -1242,7 +1244,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
1242
1244
|
metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
|
|
1243
1245
|
}
|
|
1244
1246
|
try {
|
|
1245
|
-
const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-
|
|
1247
|
+
const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-HWJQJW5U.js");
|
|
1246
1248
|
const feeBps = await getAgentFeeBps2(vault);
|
|
1247
1249
|
console.log(
|
|
1248
1250
|
chalk3.yellow(
|
|
@@ -1513,7 +1515,7 @@ function registerStrategyTemplateCommands(strategy2) {
|
|
|
1513
1515
|
let prices = [];
|
|
1514
1516
|
let priceSource = null;
|
|
1515
1517
|
try {
|
|
1516
|
-
const { getTokenPricesInAsset } = await import("./price-
|
|
1518
|
+
const { getTokenPricesInAsset } = await import("./price-YNPYE2EO.js");
|
|
1517
1519
|
prices = await getTokenPricesInAsset({
|
|
1518
1520
|
tokens: allocations.map((a, i) => ({
|
|
1519
1521
|
token: a.token,
|
|
@@ -1943,7 +1945,7 @@ function registerVeniceCommands(program2) {
|
|
|
1943
1945
|
console.log(chalk5.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
|
|
1944
1946
|
console.log(chalk5.dim(" Saved to ~/.sherwood/config.json"));
|
|
1945
1947
|
try {
|
|
1946
|
-
const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-
|
|
1948
|
+
const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-KMDAMLXW.js");
|
|
1947
1949
|
const attestation = await createVeniceProvisionAttestation(account.address);
|
|
1948
1950
|
if (attestation) {
|
|
1949
1951
|
console.log(chalk5.dim(` Attested: ${getEasScanUrl(attestation.uid)}`));
|
|
@@ -2299,7 +2301,7 @@ ${opts.prompt}`;
|
|
|
2299
2301
|
console.log(chalk5.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
|
|
2300
2302
|
}
|
|
2301
2303
|
try {
|
|
2302
|
-
const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-
|
|
2304
|
+
const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-KMDAMLXW.js");
|
|
2303
2305
|
const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
|
|
2304
2306
|
const { getChainContracts: getChainContracts2 } = await import("./config-ZGFS4I7K.js");
|
|
2305
2307
|
const { getChain: getActiveChain } = await import("./network-FEHRFDPJ.js");
|
|
@@ -3298,7 +3300,7 @@ function printSimulationResult(result, callType) {
|
|
|
3298
3300
|
}
|
|
3299
3301
|
async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
|
|
3300
3302
|
try {
|
|
3301
|
-
const xmtp = await import("./xmtp-
|
|
3303
|
+
const xmtp = await import("./xmtp-KW73BGVO.js");
|
|
3302
3304
|
const { getAccount: getAccount2 } = await import("./client-3SE632Q2.js");
|
|
3303
3305
|
const group = await xmtp.getGroup("", subdomain);
|
|
3304
3306
|
const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
|
|
@@ -5386,14 +5388,78 @@ function registerGovernorCommands(program2) {
|
|
|
5386
5388
|
succeed: (v) => `Cooldown period updated to ${v}s (reverts if the vault has an open proposal).`,
|
|
5387
5389
|
failText: "Failed to set cooldown"
|
|
5388
5390
|
});
|
|
5389
|
-
|
|
5390
|
-
const
|
|
5391
|
+
const parseSplitLeg = (raw, label) => {
|
|
5392
|
+
const v = Number(parseBigIntArg(String(raw), label));
|
|
5393
|
+
if (v > 1e4) {
|
|
5394
|
+
console.error(chalk10.red(`--${label} must be <= 10000 bps, got ${v}`));
|
|
5395
|
+
process.exit(1);
|
|
5396
|
+
}
|
|
5397
|
+
return v;
|
|
5398
|
+
};
|
|
5399
|
+
const requireSum = (legs) => {
|
|
5400
|
+
const sum = Object.values(legs).reduce((a, b) => a + b, 0);
|
|
5401
|
+
if (sum !== 1e4) {
|
|
5402
|
+
const parts = Object.entries(legs).map(([k, v]) => `--${k} ${v}`).join(" ");
|
|
5403
|
+
console.error(
|
|
5404
|
+
chalk10.red(`split legs must sum to 10000 bps, got ${sum} (${parts})`)
|
|
5405
|
+
);
|
|
5406
|
+
process.exit(1);
|
|
5407
|
+
}
|
|
5408
|
+
};
|
|
5409
|
+
const fmtSplit = (legs) => Object.entries(legs).map(([k, v]) => `${k} ${Number(v) / 100}%`).join(" / ");
|
|
5410
|
+
governor.command("set-mgmt-split").description("Set the management-fee split on ProtocolConfig (protocol owner only; legs sum to 10000 bps)").requiredOption("--agent <bps>", "Agent share in bps (e.g. 6000 = 60%)").requiredOption("--protocol <bps>", "Protocol share in bps").requiredOption("--guardian <bps>", "Guardian share in bps").action(async (opts) => {
|
|
5411
|
+
const s = {
|
|
5412
|
+
agentBps: parseSplitLeg(opts.agent, "agent"),
|
|
5413
|
+
protocolBps: parseSplitLeg(opts.protocol, "protocol"),
|
|
5414
|
+
guardianBps: parseSplitLeg(opts.guardian, "guardian")
|
|
5415
|
+
};
|
|
5416
|
+
requireSum({ agent: s.agentBps, protocol: s.protocolBps, guardian: s.guardianBps });
|
|
5417
|
+
if (isCalldataOnly()) {
|
|
5418
|
+
try {
|
|
5419
|
+
emitCalldata(
|
|
5420
|
+
encodeMgmtSplit(
|
|
5421
|
+
{ protocolConfig: await getProtocolConfigAddress(), ...s },
|
|
5422
|
+
getChain().id
|
|
5423
|
+
)
|
|
5424
|
+
);
|
|
5425
|
+
} catch (err) {
|
|
5426
|
+
console.error(chalk10.red(formatContractError(err)));
|
|
5427
|
+
process.exit(1);
|
|
5428
|
+
}
|
|
5429
|
+
return;
|
|
5430
|
+
}
|
|
5431
|
+
const spinner = ora8("Setting management-fee split...").start();
|
|
5432
|
+
try {
|
|
5433
|
+
const hash = await setMgmtSplit(s);
|
|
5434
|
+
const configAddress = await getProtocolConfigAddress();
|
|
5435
|
+
spinner.succeed(
|
|
5436
|
+
G4(`Management-fee split updated to ${fmtSplit({ agent: s.agentBps, protocol: s.protocolBps, guardian: s.guardianBps })} on ProtocolConfig (${configAddress}). In-flight proposals keep their propose-time snapshot.`)
|
|
5437
|
+
);
|
|
5438
|
+
console.log(DIM4(` ${getExplorerUrl(hash)}`));
|
|
5439
|
+
} catch (err) {
|
|
5440
|
+
spinner.fail("Failed to set management-fee split");
|
|
5441
|
+
console.error(chalk10.red(formatContractError(err)));
|
|
5442
|
+
process.exit(1);
|
|
5443
|
+
}
|
|
5444
|
+
});
|
|
5445
|
+
governor.command("set-perf-split").description("Set the performance-fee split on ProtocolConfig (protocol owner only; legs sum to 10000 bps)").requiredOption("--agent <bps>", "Agent share in bps (e.g. 5000 = 50%)").requiredOption("--protocol <bps>", "Protocol share in bps").requiredOption("--guardian <bps>", "Guardian share in bps").requiredOption("--owner <bps>", "Vault-owner share in bps").action(async (opts) => {
|
|
5446
|
+
const s = {
|
|
5447
|
+
agentBps: parseSplitLeg(opts.agent, "agent"),
|
|
5448
|
+
protocolBps: parseSplitLeg(opts.protocol, "protocol"),
|
|
5449
|
+
guardianBps: parseSplitLeg(opts.guardian, "guardian"),
|
|
5450
|
+
ownerBps: parseSplitLeg(opts.owner, "owner")
|
|
5451
|
+
};
|
|
5452
|
+
requireSum({
|
|
5453
|
+
agent: s.agentBps,
|
|
5454
|
+
protocol: s.protocolBps,
|
|
5455
|
+
guardian: s.guardianBps,
|
|
5456
|
+
owner: s.ownerBps
|
|
5457
|
+
});
|
|
5391
5458
|
if (isCalldataOnly()) {
|
|
5392
5459
|
try {
|
|
5393
|
-
const value = parseBigIntArg(rawValue, "bps");
|
|
5394
5460
|
emitCalldata(
|
|
5395
|
-
|
|
5396
|
-
{ protocolConfig: await getProtocolConfigAddress(),
|
|
5461
|
+
encodePerfSplit(
|
|
5462
|
+
{ protocolConfig: await getProtocolConfigAddress(), ...s },
|
|
5397
5463
|
getChain().id
|
|
5398
5464
|
)
|
|
5399
5465
|
);
|
|
@@ -5403,16 +5469,16 @@ function registerGovernorCommands(program2) {
|
|
|
5403
5469
|
}
|
|
5404
5470
|
return;
|
|
5405
5471
|
}
|
|
5406
|
-
const spinner = ora8("Setting
|
|
5472
|
+
const spinner = ora8("Setting performance-fee split...").start();
|
|
5407
5473
|
try {
|
|
5408
|
-
const hash = await
|
|
5474
|
+
const hash = await setPerfSplit(s);
|
|
5409
5475
|
const configAddress = await getProtocolConfigAddress();
|
|
5410
5476
|
spinner.succeed(
|
|
5411
|
-
G4(`
|
|
5477
|
+
G4(`Performance-fee split updated to ${fmtSplit({ agent: s.agentBps, protocol: s.protocolBps, guardian: s.guardianBps, owner: s.ownerBps })} on ProtocolConfig (${configAddress}). In-flight proposals keep their propose-time snapshot.`)
|
|
5412
5478
|
);
|
|
5413
5479
|
console.log(DIM4(` ${getExplorerUrl(hash)}`));
|
|
5414
5480
|
} catch (err) {
|
|
5415
|
-
spinner.fail("Failed to set
|
|
5481
|
+
spinner.fail("Failed to set performance-fee split");
|
|
5416
5482
|
console.error(chalk10.red(formatContractError(err)));
|
|
5417
5483
|
process.exit(1);
|
|
5418
5484
|
}
|
|
@@ -7985,9 +8051,9 @@ try {
|
|
|
7985
8051
|
} catch {
|
|
7986
8052
|
}
|
|
7987
8053
|
var require2 = createRequire(import.meta.url);
|
|
7988
|
-
var CLI_VERSION = "0.86.
|
|
8054
|
+
var CLI_VERSION = "0.86.1";
|
|
7989
8055
|
async function loadXmtp() {
|
|
7990
|
-
return import("./xmtp-
|
|
8056
|
+
return import("./xmtp-KW73BGVO.js");
|
|
7991
8057
|
}
|
|
7992
8058
|
async function loadCron() {
|
|
7993
8059
|
return import("./cron-E3UAZF5B.js");
|
|
@@ -8658,7 +8724,7 @@ vaultCmd.command("add").description("Register an agent on a vault (creator only)
|
|
|
8658
8724
|
agentId = BigInt(opts.agentId);
|
|
8659
8725
|
} else {
|
|
8660
8726
|
spinner.text = "Looking up ERC-8004 identity from wallet...";
|
|
8661
|
-
const { lookupAgentIdByWallet } = await import("./identity-
|
|
8727
|
+
const { lookupAgentIdByWallet } = await import("./identity-ATWV2O7Y.js");
|
|
8662
8728
|
const resolved = await lookupAgentIdByWallet(agentWallet);
|
|
8663
8729
|
if (resolved === null) {
|
|
8664
8730
|
spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
|
|
@@ -9371,7 +9437,7 @@ ${info.name} (${info.type})`);
|
|
|
9371
9437
|
}
|
|
9372
9438
|
});
|
|
9373
9439
|
try {
|
|
9374
|
-
const { registerChatCommands } = await import("./chat-
|
|
9440
|
+
const { registerChatCommands } = await import("./chat-ETZSKQDI.js");
|
|
9375
9441
|
registerChatCommands(program);
|
|
9376
9442
|
} catch {
|
|
9377
9443
|
program.command("chat <name> [action] [actionArgs...]").description("Vault chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
|
|
@@ -9381,7 +9447,7 @@ try {
|
|
|
9381
9447
|
process.exit(1);
|
|
9382
9448
|
});
|
|
9383
9449
|
}
|
|
9384
|
-
var { registerSessionCommands } = await import("./session-
|
|
9450
|
+
var { registerSessionCommands } = await import("./session-HVRZ6AJM.js");
|
|
9385
9451
|
registerSessionCommands(program);
|
|
9386
9452
|
registerVeniceCommands(program);
|
|
9387
9453
|
registerAllowanceCommands(program);
|
|
@@ -9390,11 +9456,11 @@ registerProposalCommands(program);
|
|
|
9390
9456
|
registerQueueCommands(program);
|
|
9391
9457
|
registerGovernorCommands(program);
|
|
9392
9458
|
registerGuardianCommands(program);
|
|
9393
|
-
var { registerResearchCommands } = await import("./research-
|
|
9459
|
+
var { registerResearchCommands } = await import("./research-W74PNYPO.js");
|
|
9394
9460
|
registerResearchCommands(program);
|
|
9395
9461
|
var { registerAgentCommands } = await import("./agent-TBLC3WNJ.js");
|
|
9396
9462
|
registerAgentCommands(program);
|
|
9397
|
-
var { registerTradeCommands } = await import("./trade-
|
|
9463
|
+
var { registerTradeCommands } = await import("./trade-EOQY72L7.js");
|
|
9398
9464
|
registerTradeCommands(program);
|
|
9399
9465
|
registerGridCommand(program);
|
|
9400
9466
|
var configCmd = program.command("config");
|