Yearn TimelockController - 25/09/2026 18:06 - MEDIUM
Revision 2 — corrected. The first version of this report did not identify the vaults or strategies by name. It called the Spark looper an Aave looper, treated the
max_debtunits and theadd_to_queueflag as unknown, and wrongly said the debt-setting calls were unverified. Every figure below was read on-chain on 25/09/2026, and the four calls were re-simulated as one sequential batch.
- Protocol: YEARN_TIMELOCK
- Contract: Yearn TimelockController —
0x88Ba032be87d5EF1fbE87336B7090767F367BF73 - Chain: Mainnet (chain id 1)
- Delay: 7d
- Risk: MEDIUM
- Tx:
0x27144919a3b6fc636c9dc0ed2369b82f9cf03c949018ca51979d30010232d788
Summary
Adds Flex WETH yVault as a strategy of the yETH Recovery Vault with a 500 WETH max debt, and puts it in the default queue. Adds the wstETH/WETH Spark Looper (wstETH looped about 8× on SparkLend) to yvWETH-2 with a 10,000 WETH max debt, and leaves it out of the default queue. The 10,000 WETH cap is the same as every other yvWETH-2 strategy and the vault's deposit limit, but it is about 8.6× the vault's current 1,164 WETH in assets, so it does not limit anything in practice. No funds move until a debt allocator calls update_debt. MEDIUM
Analysis
Call 1–2: Flex WETH yVault → yETH Recovery Vault
0xd7a540ba3626c0aa66e7DB4088971d0CD64695B6 is the Yearn yETH Recovery Vault (yETH-Recovery), a V3 vault on API 3.0.4 whose asset is WETH (18 decimals).
add_strategy(new_strategy, add_to_queue=True)registers0xfaC55fAFD0b55BFb8dD41F735EfCc195adA9891F, the Flex WETH yVault (yvFlexWETH, V3 API 3.1.0, WETH asset). The vault asserts thatstrategy.asset() == vault.asset, which holds here. Becauseadd_to_queue=True, the strategy is appended to the default queue. That queue is used for withdrawals and for allocators that read it.update_max_debt_for_strategy(strategy, 500e18)sets the cap to 500 WETH.max_debtis denominated in the vault's asset.
| yETH Recovery Vault | Now |
|---|---|
| Total assets | 2,445.35 WETH, fully deployed, 0 idle |
| Deposit limit | 3,000 WETH |
| Default queue | WETH-1 yVault (1,956.28 WETH debt, uncapped max_debt) → WETH-2 yVault (489.07 WETH debt, 500 WETH cap) |
| Flex WETH yVault params | not active (activation = 0, max_debt = 0) |
The new 500 WETH cap equals the vault's existing cap for yvWETH-2 and is about 20% of current assets.
The Flex WETH yVault is small, with 10.01 WETH in total assets. All of it sits in the Flex yvWETH-2/WETH Lender (0x7E4a6A89583e117C641aB3ce8897209800A3F2E3); the WETH-1 yVault is also in its queue with 0 debt. Judging by the lender's name, it lends WETH against yvWETH-2 collateral. If so, Recovery Vault funds sent to Flex would take credit exposure to yvWETH-2, a vault the Recovery Vault already allocates to directly. I haven't verified this beyond the contract name.
Call 3–4: wstETH/WETH Spark Looper → yvWETH-2
0xAc37729B76db6438CE62042AE1270ee574CA7571 is the WETH-2 yVault (yvWETH-2, V3 API 3.0.2, WETH asset).
add_strategy(new_strategy, add_to_queue=False)registers0x68A14629cb07c74259f481382fE8b6cFD8970121, the wstETH/WETH Spark Looper (ysWETH). "LSTAaveLooper" is only its Etherscan contract name. Withadd_to_queue=False, the looper stays out of the default queue: it can receive debt throughupdate_debt, but default-queue withdrawals will not pull from it unless the queue is changed or a custom queue is passed.update_max_debt_for_strategy(strategy, 10_000e18)sets the cap to 10,000 WETH.
| WETH-2 yVault | Now |
|---|---|
| Total assets | 1,163.81 WETH, fully deployed, 0 idle |
| Deposit limit | 10,000 WETH |
| Default queue (debt / max debt) | WETH-1 yVault 190.51 / 10,000 · Morpho Y-WETH Compounder 0 / 10,000 · Spark wstETH to yvUSD Lender Borrower Accumulator 921.82 / 10,000 · Spark WETH/USDS (yvUSD) Lender Borrower 51.49 / 10,000 |
| Spark Looper params | not active (activation = 0, max_debt = 0) |
The 10,000 WETH cap matches the vault's existing convention: every current strategy is capped at 10,000 WETH, which is also the deposit limit. The cap therefore is not a real limit, and a debt allocator could move all of yvWETH-2 into the looper.
Looper position:
| Spark Looper | Now |
|---|---|
| Lending pool | SparkLend Pool 0xC13e21B648A5Ee794902342038FF3aDAB66BE987 (addresses provider 0x02C3eA4e34C0cBd694D2adFa2c690EECbC1793eE) |
| Collateral | wstETH 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 |
| Leverage | 7.98× current, 8.0× target, 8.5× max |
| LTV | 87.47% current vs 93% liquidation collateral factor |
| Total assets | 1,034.03 WETH |
| Existing depositor | WETH-1 yVault 0xc56413869c6CDf96496f2b1eF801fEDBdFA7dDB0, 1,033.63 WETH debt with a 2,000 WETH cap; it holds all of the looper's shares |
| Performance fee | 0 |
yvWETH-2 already has indirect exposure to this looper through its 190.51 WETH allocation to WETH-1. This change would give it direct exposure, with a cap five times the one WETH-1 uses.
Execution check
A Tenderly sequential bundle simulation, with all calls sent from the timelock in batch order, succeeds for all four calls. Gas per call: 114,879 / 53,526 / 88,019 / 53,469. The earlier "reverted" diagnostics for calls 2 and 4 came from simulating each call on its own, where update_max_debt_for_strategy runs before its strategy exists and fails assert activation != 0, "inactive strategy". The timelock holds the required ADD_STRATEGY_MANAGER and MAX_DEBT_MANAGER roles on both vaults.
Risk assessment
MEDIUM. No assets move when this executes. It opens two new allocation paths:
- Recovery Vault → Flex WETH (500 WETH, in default queue). The Flex vault is new and small (10 WETH), and it may lend against yvWETH-2 collateral, which would add a layer of credit exposure to a vault the Recovery Vault already uses.
- yvWETH-2 → Spark Looper (10,000 WETH, not in queue). The looper runs an ~8× leveraged wstETH/WETH position on SparkLend. The main risks are liquidation from a wstETH/ETH depeg (87.5% LTV vs 93% liquidation), WETH borrow-rate spikes above staking yield, and exit slippage when unwinding. In practice the cap does not bind. Keeping the looper out of the default queue means ordinary withdrawals will not force an unwind.
Both paths depend on later update_debt calls, so real exposure is set by the debt allocator, not by this transaction.
Call Flow
From: 0x88Ba032be87d5EF1fbE87336B7090767F367BF73
add_strategy(address,bool)on0xd7a540ba3626c0aa66e7DB4088971d0CD64695B6(Yearn yETH Recovery Vault, yETH-Recovery)address new_strategy:0xfaC55fAFD0b55BFb8dD41F735EfCc195adA9891F(Flex WETH yVault, yvFlexWETH)bool add_to_queue:True- Batch simulation: SUCCESS, gas 114,879
update_max_debt_for_strategy(address,uint256)on0xd7a540ba3626c0aa66e7DB4088971d0CD64695B6(Yearn yETH Recovery Vault)address strategy:0xfaC55fAFD0b55BFb8dD41F735EfCc195adA9891F(Flex WETH yVault)uint256 new_max_debt:500,000,000,000,000,000,000(≈ 500 WETH)- Batch simulation: SUCCESS, gas 53,526
add_strategy(address,bool)on0xAc37729B76db6438CE62042AE1270ee574CA7571(WETH-2 yVault, yvWETH-2)address new_strategy:0x68A14629cb07c74259f481382fE8b6cFD8970121(wstETH/WETH Spark Looper, ysWETH)bool add_to_queue:False- Batch simulation: SUCCESS, gas 88,019
update_max_debt_for_strategy(address,uint256)on0xAc37729B76db6438CE62042AE1270ee574CA7571(WETH-2 yVault)address strategy:0x68A14629cb07c74259f481382fE8b6cFD8970121(wstETH/WETH Spark Looper)uint256 new_max_debt:10,000,000,000,000,000,000,000(≈ 10,000 WETH)- Batch simulation: SUCCESS, gas 53,469
Reference
| Address | Label | Role |
|---|---|---|
0x88Ba032be87d5EF1fbE87336B7090767F367BF73 |
Yearn TimelockController | Executor |
0xd7a540ba3626c0aa66e7DB4088971d0CD64695B6 |
Yearn yETH Recovery Vault (yETH-Recovery) | Call target, calls 1–2 |
0xfaC55fAFD0b55BFb8dD41F735EfCc195adA9891F |
Flex WETH yVault (yvFlexWETH) | New strategy, calls 1–2 |
0xAc37729B76db6438CE62042AE1270ee574CA7571 |
WETH-2 yVault (yvWETH-2) | Call target, calls 3–4 |
0x68A14629cb07c74259f481382fE8b6cFD8970121 |
wstETH/WETH Spark Looper (ysWETH) | New strategy, calls 3–4 |
0xc56413869c6CDf96496f2b1eF801fEDBdFA7dDB0 |
WETH-1 yVault | Existing looper depositor |
0x7E4a6A89583e117C641aB3ce8897209800A3F2E3 |
Flex yvWETH-2/WETH Lender | Flex WETH yVault's strategy |
0xC13e21B648A5Ee794902342038FF3aDAB66BE987 |
SparkLend Pool | Looper lending market |
0xb3bd6B2E61753C311EFbCF0111f75D29706D9a41 |
RoleManager | role_manager of all three vaults |