<!-- canonical: https://0xsimao.com/findings/symbiotic-relay-epoch-duration-completely-slashers -->

# Changing the epoch duration will completely break the vault and the slashers

Medium · Sherlock · Staking · 19th June 2025

Finding M-5 of the Symbiotic Relay competition.

- Protocol: https://audits.sherlock.xyz/contests/967
- Codebase: https://github.com/0xsimao/2025-06-symbiotic-relay/tree/435a21fd81bcd588439feef3108580f535b9e5eb
- Source: https://github.com/sherlock-audit/2025-06-symbiotic-relay-judging/issues/410

---

### Summary

The [vault](https://github.com/sherlock-audit/2025-06-symbiotic-relay/blob/main/middleware-sdk/src/contracts/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#L19-L20) and slashers in scope of the protocol in `OpNetVaultAutoDeploy` are `BASE_VAULT_VERSION` and `TOKENIZED_VAULT_VERSION`, [`SlasherType.INSTANT`](https://github.com/sherlock-audit/2025-06-symbiotic-relay/blob/main/middleware-sdk/src/contracts/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#L203) and [`SlasherType.VETO`](https://github.com/sherlock-audit/2025-06-symbiotic-relay/blob/main/middleware-sdk/src/contracts/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#L214).

The issue is that the epoch duration can not be updated in these contracts, they always use the same value. As a result, whenever it is changed in the epoch manager via `EpochManager::setEpochDuration()`, it will completely ruin the vault's staking and slashing mechanism, as they rely on the epoch duration. For example, the instant slasher requires the slashing to be [within](https://github.com/symbioticfi/core/blob/main/src/contracts/slasher/Slasher.sol#L36-L39) 1 epoch duration, but if the epoch duration is now bigger/smaller, slashing will fail for a significant period of time. [Slashing](https://github.com/sherlock-audit/2025-06-symbiotic-relay/blob/main/middleware-sdk/src/contracts/modules/voting-power/extensions/logic/BaseSlashingLogic.sol#L34-L59) also has several checks which don't allow slashing whenever the operator, token or vault is not registered in that epoch, which can make slashing impossible via `slashVault()` in case of epoch duration change.

Additionally, the [slashing window](https://github.com/sherlock-audit/2025-06-symbiotic-relay/blob/main/middleware-sdk/src/contracts/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#L147-L149) must be bigger than the epoch duration, but the slasher's and vault's epoch duration can't be changed, so this will also not work properly. The same happens for the [veto duration](https://github.com/sherlock-audit/2025-06-symbiotic-relay/blob/main/middleware-sdk/src/contracts/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#L218) of the veto [slasher](https://github.com/symbioticfi/core/blob/main/src/contracts/slasher/VetoSlasher.sol#L274-L276).

`Vault::onSlash()` requires the epoch to be [no older](https://github.com/symbioticfi/core/blob/main/src/contracts/vault/Vault.sol#L224-L226) than `currentEpoch_ - 1`, but a different duration means this will fail. For example, if the duration is halved, calling at duration / 2 + 1 after the current epoch will revert as this is already 2 epochs in the past.

### Root Cause

In `EpochManager:115`, setting a new epoch duration will always break the vault and their slasher.

### Internal Pre-conditions

None

### External Pre-conditions

None

### Attack Path

1. `EpochManager::setEpochDuration()` is called.

### Impact

Epoch duration is out of sync between the vaults, slashers and the epoch manager, so slashing will fail or be impossible.

### PoC

_No response_

### Mitigation

Non trivial.

---

Related findings:

- [Finalize-window vote-changing vulnerability: auto-voters can alter choices post-epoch to manipulate results](https://0xsimao.com/findings/bmx-vote-vulnerability-choices-epoch): BMX
- [Changing providers might lead to lost assets in BorrowingVault and YieldVault](https://0xsimao.com/findings/fuji-finance-changing-providers-lost-yield): Fuji Finance
- [`ManagedLeveragedVault::executeWithdrawalEpoch()` will never work because `cd.prevICR` is not set](https://0xsimao.com/findings/beraborrow-i-withdrawal-epoch-prev-icr): Beraborrow Managed Dens
- [`ManagedLeveragedVault::executeWithdrawalEpoch()` incorrect ICR and DoSed withdrawals due to not accouting for fees](https://0xsimao.com/findings/beraborrow-i-withdrawal-epoch-withdrawals-fees): Beraborrow Managed Dens
