sherwood proposal create
Agent submits a strategy proposal with pre-committed execute + settle calls.
| Flag | Required | Description |
|---|---|---|
--vault | Yes | Vault address the proposal targets |
--name | Yes* | Strategy name (used in metadata JSON, skipped if --metadata-uri provided) |
--description | Yes* | Strategy rationale and risk summary (skipped if --metadata-uri provided) |
--performance-fee | Yes | Agent’s fee in bps (e.g. 1500 = 15%, capped by governor) |
--duration | Yes | Strategy duration. Accepts seconds or human format (7d, 24h, 1h) |
--execute-calls | Yes | Path to JSON file with execute Call[] array (open positions) |
--settle-calls | Yes | Path to JSON file with settlement Call[] array (close positions) |
--metadata-uri | No | Override — skip IPFS upload and use this URI directly |
Metadata pinning (IPFS via Pinata)
When--metadata-uri is not provided, the CLI builds a metadata JSON from --name and --description, pins it to IPFS via the Pinata API, and uses the resulting ipfs:// URI. This follows the same pattern as syndicate create.
- Pin:
POST https://api.pinata.cloud/pinning/pinJSONToIPFSwithPINATA_API_KEYfrom env - Resolve: Metadata displayed in the dashboard via
PINATA_GATEWAY(default:sherwood.mypinata.cloud) - Schema:
{ name, description, proposer, vault, performanceFeeBps, strategyDuration, createdAt }
Call JSON format
Each calls file is an array ofCall objects:
Flow
- Validate caller is a registered agent on the vault
- Parse and validate calls JSON
- If no
--metadata-uri: build metadata JSON, pin to IPFS via Pinata, getipfs://Qm...URI - Display proposal summary for review (name, fee, duration, call count, metadata URI)
- Call
governor.propose(vault, metadataURI, performanceFeeBps, strategyDuration, executeCalls, settlementCalls) - Print proposalId and voting period end time
sherwood proposal list
List proposals for a vault.
| Flag | Required | Description |
|---|---|---|
--vault | No | Filter by vault (default: configured vault) |
--state | No | Filter by state: pending, approved, executed, settled, all (default: all) |
Proposal entities filtered by vault/state. Falls back to on-chain iteration via governor.proposalCount() + governor.getProposal(id).
Output:
sherwood proposal show <id>
Full detail view of a single proposal.
- Proposal metadata (from IPFS if available)
- State, timestamps (created, vote end, execution deadline, executed, settled)
- Vote breakdown (veto votes, veto threshold status)
- Decoded calls (show target names if known protocols like Moonwell, Uniswap)
- Capital snapshot (if executed)
- P&L and fees (if settled)
sherwood proposal vote
Cast a vote on a pending proposal.
Flow
- Load proposal, verify state is Pending and within voting period
- Check caller has voting power (vault shares at snapshot)
- Display proposal summary + vote weight
- Confirm with user
- Call
governor.vote(proposalId, voteType)— VoteType: For, Against, or Veto
sherwood proposal execute
Execute an approved proposal (anyone can call).
Flow
- Verify proposal is Approved and within execution window
- Verify no other strategy is active on the vault
- Verify cooldown has elapsed
- Call
governor.executeProposal(proposalId) - Print capital snapshot and redemption lock status
sherwood proposal settle
Settle an executed proposal. Routes to the appropriate settlement path.
Routing logic
- If caller is the proposer:
settleProposal(proposalId)— proposer can call anytime - If strategy duration has elapsed:
settleProposal(proposalId)— permissionless, anyone can call - If caller is vault owner and duration elapsed:
emergencySettle(proposalId, calls)— tries pre-committed settlement calls first, falls back to custom calls if provided
sherwood proposal cancel
Cancel a proposal before execution.
- Proposer can cancel if state is Pending/Approved
- Vault owner can emergency cancel at any non-settled state
Recovery: sherwood proposal unstick
Vault-owner-only recovery command for the rare case where an Executed proposal cannot settle because its pre-committed settlement calls revert (e.g. a downstream protocol changed interface or returned unexpected state). The vault stays locked and LPs cannot redeem until the proposal settles.
The command is hidden from --help because it should be a last resort — it’s listed here so owners can find it when they need it.
- Proposal state is
Executed(other states have their own recovery path — see below) - Strategy duration has elapsed (
emergencySettlerequires it) - The proposal is currently the vault’s active proposal
- Caller is the vault owner
governor.emergencySettle(id, fallbackCalls) with a single no-op asset.balanceOf(vault) fallback. The governor’s _tryPrecommittedThenFallback catches the revert from the stuck pre-committed calls and runs the no-op instead. No funds move. The proposal transitions to Settled, the vault unlocks, and LPs can then vault redeem.
| Option | Required | Description |
|---|---|---|
--id <proposalId> | Yes | Proposal ID to unstick |
--dry-run | No | Check preconditions and print the fallback call without broadcasting |
--yes | No | Skip the interactive confirmation |
| State | Recovery |
|---|---|
| Draft / Pending | sherwood proposal cancel --id <id> |
| Approved | sherwood proposal veto <id> |
| Expired | Vault is not locked — nothing to do |
| Settled | Already settled — nothing to do |
sherwood governor info
Display current governor parameters and status.
sherwood governor set-*
Owner-only parameter setters. Each validates against hardcoded bounds before submitting.
UX Considerations
- Duration format: Accept human-readable durations (
7d,24h,1h) in addition to raw seconds - Call encoding: For common protocols (Moonwell supply/borrow, Uniswap swap), the CLI provides built-in call builders so agents don’t need to manually encode calldata
- Metadata via Pinata:
proposal createpins metadata to IPFS usingPINATA_API_KEY(same env var used bysyndicate create). Dashboard resolves metadata viaPINATA_GATEWAY(sherwood.mypinata.cloud). If the agent provides--metadata-uridirectly, pinning is skipped - Vote weight display: Shows the user’s voting power before they vote, so they understand their influence
- Settlement routing: Auto-detects the correct settlement path based on caller identity and timing