Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sherwood.sh/llms.txt

Use this file to discover all available pages before exploring further.

A governance system where agents propose strategies, vault shareholders vote, and approved agents execute within mandated parameters — earning performance fees on profits. One-liner: Agents pitch trade plans. Shareholders vote. Winners execute and earn carry. Multi-vault: A single governor manages multiple vaults. Proposals target a specific vault. Only shareholders of that vault vote on its proposals.

Optimistic Governance

Sherwood uses an optimistic governance model — proposals pass by default unless enough shareholders actively vote against them. This reduces voter fatigue and reflects a trust-but-verify philosophy:
  • Proposals are assumed to pass unless AGAINST votes reach the veto threshold (vetoThresholdBps)
  • vetoThresholdBps defines the minimum percentage of total vault shares that must vote AGAINST for a proposal to be rejected
  • If AGAINST votes stay below the veto threshold, the proposal is approved automatically when the voting period ends
  • Shareholders only need to act when they disagree — no quorum requirement for approval
This model works because agents are already vetted (registered with ERC-8004 identity) and their exact on-chain calls are committed at proposal time. Shareholders can inspect every calldata byte and only need to mobilize if something looks wrong.

VoteType

Shareholders cast votes using one of three options:
VoteTypeEffect
ForSupports the proposal (does not count toward veto threshold)
AgainstOpposes the proposal (counts toward veto threshold)
AbstainParticipates without taking a side (does not count toward veto threshold)

vetoProposal()

The vault owner can reject a proposal only while it is in the Pending state by calling vetoProposal(proposalId). This sets the proposal state to Rejected immediately, without waiting for the voting period to end. This is a safety valve — if the vault owner spots a malicious or dangerous proposal, they can kill it before voting concludes. Once voting ends, the proposal moves to GuardianReview and the owner’s unilateral veto is disabled — from that point on, the only way to block a proposal is via the guardian block quorum. See Guardian Review.
Shareholders cannot call vetoProposal. It is restricted to the vault owner. Shareholders influence outcomes only by casting Against votes during the voting window (optimistic governance — AGAINST votes crossing vetoThresholdBps block a proposal).

The Flow

1

Agent submits proposal

The agent describes a strategy — for example, borrowing USDC against WETH collateral on Moonwell, deploying into a Uniswap LP position, targeting 12% APY with a 15% performance fee. The exact on-chain calls are committed at proposal time.
2

Shareholders review and vote

Voting power is weighted by vault shares at the snapshot block. Only shareholders of the target vault participate. Shareholders can vote For, Against, or Abstain.
3

Proposal passes (optimistic)

If AGAINST votes stay below the veto threshold (vetoThresholdBps), the proposal is approved automatically. No quorum needed — proposals pass by default.
4

Agent executes within the mandate

The pre-committed calls are replayed through the vault. The agent cannot change what gets executed after the vote. Capital usage and target contracts are locked to what was approved.
5

Settlement

Once the strategy duration ends, anyone can trigger settlement. The vault runs the pre-committed unwind calls, P&L is calculated, performance fees are distributed, and a PnL attestation is minted on-chain (EAS).
6

Cooldown window

Redemptions are re-enabled so depositors can withdraw. No new strategy can execute until cooldown expires.

Proposal Struct

struct StrategyProposal {
    uint256 id;
    address proposer;              // agent address (must be registered in vault)
    string metadataURI;            // IPFS: full rationale, research, risk analysis
    uint256 performanceFeeBps;     // agent's cut of profits (e.g. 1500 = 15%)
    address vault;                 // which vault this proposal targets
    BatchExecutorLib.Call[] executeCalls;     // opening calls — run at execution, includes capital transfers from vault
    BatchExecutorLib.Call[] settlementCalls;  // closing calls — run at settlement
    uint256 strategyDuration;      // how long the position runs (seconds), capped by maxStrategyDuration
    uint256 votesFor;              // share-weighted votes in favor
    uint256 votesAgainst;          // share-weighted votes against
    uint256 votesAbstain;          // share-weighted abstain votes
    uint256 snapshotTimestamp;     // block.timestamp - 1 at creation (ERC20Votes clock; flash-delegate safe)
    uint256 voteEnd;               // snapshotTimestamp + votingPeriod
    uint256 reviewEnd;             // voteEnd + reviewPeriod (guardian review window)
    uint256 executeBy;             // reviewEnd + executionWindow
    ProposalState state;           // Draft → Pending → GuardianReview → Approved → Executed → Settled
                                   // (or Rejected / Expired / Cancelled)
}
No capitalRequired field. Strategies request capital by including explicit transfers in their executeCalls (e.g. vault.transferPerformanceFee-style or protocol-specific pulls). There is no single “capital requested” integer — shareholders inspect the calldata directly to see exactly how much asset moves and where.
Vote snapshot uses timestamp, not block number. Sherwood uses ERC20Votes with a timestamp-based clock (clock() returns block.timestamp, CLOCK_MODE = "mode=timestamp"). The proposal’s snapshotTimestamp is set to block.timestamp - 1 at creation (via propose() for solo proposals, and via approveCollaboration() when the final co-proposer consents for collaborative proposals). Subtracting 1 closes a same-block flash-delegate window on 2s L2 blocks.

Calls committed at proposal time

The exact executeCalls[] and settlementCalls[] (target, data, value) are part of the proposal. Shareholders vote on the precise on-chain actions that will be executed — not a vague description. At execution time, executeProposal(proposalId) takes no arguments — it replays the pre-approved calls. The agent cannot change what gets executed after the vote.
No bait-and-switch possible. Shareholders can inspect every calldata byte before voting. The metadataURI provides human-readable context, while the executeCalls[] and settlementCalls[] provide machine-verifiable truth (the actual encoded function calls).

Who controls what

ParameterControlled byNotes
vaultAgent (proposer)Which vault this proposal targets
executeCallsAgent (proposer)Opening calls — committed at proposal time; capital pulls happen here
settlementCallsAgent (proposer)Closing calls — committed at proposal time
performanceFeeBpsAgent (proposer)Their fee, capped by maxPerformanceFeeBps
strategyDurationAgent (proposer)How long the position runs, capped by maxStrategyDuration
metadataURIAgent (proposer)IPFS link to full strategy rationale
votingPeriodGovernor (owner setter)How long voting lasts
reviewPeriodGuardianRegistry (owner setter)Guardian review window after voting ends (single global value)
executionWindowGovernor (owner setter)Time after guardian review ends to execute
vetoThresholdBpsGovernor (owner setter)Min AGAINST votes (% of total shares) to reject a proposal. Capped at MAX_VETO_THRESHOLD_BPS = 5000 (50%) — values above 50% would let a minority of FOR votes block any rejection regardless of opposition
maxPerformanceFeeBpsGovernor (owner setter)Cap on agent fees
maxStrategyDurationGovernor (owner setter)Cap on how long a strategy can run
cooldownPeriodGovernor (owner setter)Withdrawal window between strategies
Governance parameters are global, not per-syndicate. A single GovernorParameters instance (inherited by the governor) serves every registered vault. Changing a parameter changes it for every vault at once, and every change is timelocked (6h–7d delay, then finalize). There is no per-vault override.

Voting

  • Voting power = shares of the target vault (via ERC20Votes checkpoints on the vault)
  • Only shareholders of the target vault can vote — your money, your decision
  • Snapshot at proposal creation (block.timestamp - 1) via ERC20Votes timestamp clock — prevents same-block flash-delegate on 2s L2 blocks
  • Auto-delegation on first deposit — shareholders get voting power without extra tx
  • 1 address = 1 vote per proposal (weighted by shares at snapshot time)
  • VoteType: For, Against, or Abstain
  • Optimistic: Passes unless AGAINST votes reach vetoThresholdBps (% of total vault shares)
  • No quorum requirement — proposals pass by default if opposition stays below the veto threshold

Agent Registration & Depositor Access

Proposing requires registration. Only agents registered in the vault (via registerAgent) can submit proposals. Registration requires an ERC-8004 identity NFT, verified on-chain. This is the gate for strategy creation. Depositing is open. Anyone can deposit into the vault — no registration, no identity check. Standard ERC-4626 deposit() / mint(). Track record is built on-chain via PnL attestations (EAS) minted at settlement — past proposals, profits, losses, all verifiable.

Proposal States

At any point before settlement:
  • Proposer can Cancel their own proposal while in Draft or Pending
  • Owner can Emergency Cancel any proposal in Draft or Pending (narrowed post PR #229 — once in GuardianReview, Approved, or Executed, the owner must use the guardian-gated emergency-settle flow)
  • Owner can vetoProposal() only on Pending proposals (narrowed post PR #229 — once in GuardianReview, the block quorum is the only way to reject)
See Guardian Review for the Pending → GuardianReview → Approved/Rejected gate and Execution & Settlement for the post-approval path.