| name | moonwell-supply |
| description | Moonwell USDC supply strategy via governance proposals โ supply to lending market, earn yield, redeem on settlement |
| allowed-tools | Read, Glob, Grep, Bash(sherwood *), Bash(npm *), Bash(npx *), WebFetch, WebSearch, AskUserQuestion |
| model | sonnet |
| license | MIT |
| metadata | {"author":"sherwood","version":"0.1.0"} |
Moonwell Supply Strategy
Supply USDC (or other supported tokens) to Moonwell's lending market to earn yield. Uses MoonwellSupplyStrategy (ERC-1167 clonable) โ any syndicate, any agent, any proposal can use it as a lego block.
Overview
Vault (holds USDC)
โ governance proposal
MoonwellSupplyStrategy clone
โ execute: pull USDC โ approve mToken โ mint mUSDC
Strategy holds mUSDC (accruing yield)
โ settle: redeem all mUSDC โ verify min output โ push USDC back to vault
Vault (holds USDC + yield)
Workflow
Step 1: Prerequisites
sherwood config show
sherwood identity show
sherwood vault info --vault <vault-address>
Step 2: Add allowlist targets
The vault must allowlist the protocol addresses used by the strategy. Do this before creating a proposal.
sherwood vault add-target --target 0xEdc817A28E8B93B03976FBd4a3dDBc9f7D176c22
sherwood vault add-target --target 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Step 3: Clone + init + build calls (all-in-one)
The strategy propose command handles everything: clones the template, initializes it, builds batch calls, and optionally submits the proposal.
sherwood strategy propose moonwell-supply \
--vault <vault-address> \
--amount 100 \
--min-redeem 99.5 \
--token USDC \
--write-calls ./moonwell-calls
sherwood vault add-target --target <clone-address>
sherwood proposal create \
--vault <vault-address> \
--name "Moonwell USDC Yield" \
--description "Supply 100 USDC to Moonwell for 7 days" \
--performance-fee 1000 \
--duration 7d \
--execute-calls ./moonwell-calls/execute.json \
--settle-calls ./moonwell-calls/settle.json
Or submit directly (skip --write-calls):
sherwood strategy propose moonwell-supply \
--vault <vault-address> \
--amount 100 --min-redeem 99.5 --token USDC \
--name "Moonwell USDC Yield" --performance-fee 1000 --duration 7d
Step 4: Proposal lifecycle
sherwood proposal list
sherwood proposal execute --id <proposal-id>
sherwood proposal settle --id <proposal-id>
Settlement calls strategy.settle() which:
- Redeems all mUSDC held by the strategy clone
- Verifies redeemed USDC >=
minRedeemAmount (slippage protection)
- Pushes all USDC back to the vault
The governor then calculates P&L (new vault balance minus snapshot) and distributes fees.
Step 5: Update params (optional)
While the strategy is in Executed state, the proposer can tune params without a new proposal:
Example Batch Call JSON
execute.json
[
{
"target": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"data": "0x095ea7b3<clone-address-padded><amount-padded>",
"value": "0"
},
{
"target": "<strategy-clone-address>",
"data": "0x61461954",
"value": "0"
}
]
- Call 1:
USDC.approve(strategyClone, supplyAmount)
- Call 2:
strategyClone.execute() โ pulls USDC, mints mUSDC
settle.json
[
{
"target": "<strategy-clone-address>",
"data": "0x845980e8",
"value": "0"
}
]
- Call 1:
strategyClone.settle() โ redeems mUSDC, pushes USDC to vault
The CLI generates these automatically via sherwood strategy propose --write-calls.
Contract Details
InitParams
| Field | Type | Description |
|---|
underlying | address | Token to supply (e.g., USDC) |
mToken | address | Moonwell market token (e.g., mUSDC) |
supplyAmount | uint256 | Amount of underlying to supply |
minRedeemAmount | uint256 | Minimum underlying to accept on settlement (slippage protection) |
Lifecycle
Pending โ execute() โ Executed โ settle() โ Settled
- Tunable params (proposer only, while Executed):
supplyAmount, minRedeemAmount
- Pass
abi.encode(uint256, uint256) to updateParams() โ pass 0 to keep current value
Governor Integration
- Allowlisting: The vault must allowlist the strategy clone address and the mToken (e.g., mUSDC) and underlying (e.g., USDC) as batch targets via
sherwood vault add-target. Without this, executeGovernorBatch will revert.
- Gas costs: The proposer (agent) pays gas for clone deployment + initialization. The governor pays gas for proposal execution and settlement (called by proposer or anyone after duration).
- updateParams(): Callable directly by the proposer while strategy is in Executed state. No governance proposal needed โ it's a direct transaction on the strategy clone.
- No post-settlement claim: Unlike Venice, Moonwell redemption is instant. Settlement returns USDC to vault in a single transaction.
Key Addresses (Base Mainnet)
| Contract | Address |
|---|
| USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 (6 decimals) |
| Moonwell mUSDC | 0xEdc817A28E8B93B03976FBd4a3dDBc9f7D176c22 |
| Moonwell mWETH | 0x628ff693426583D9a7FB391E54366292F509D457 |
| Moonwell Comptroller | 0xfBb21d0380beE3312B33c4353c8936a0F13EF26C |
Required Allowlist Targets
sherwood vault add-target --target 0xEdc817A28E8B93B03976FBd4a3dDBc9f7D176c22
sherwood vault add-target --target 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
sherwood vault add-target --target <strategy-clone-address>