Protocol Security
Recipe - Invariants & Guards
Enforcing protocol safety rules.
Recipe: Invariants & Guards
These recipes show how to use Matador to enforce "Safety Invariants"—rules that must always be true for the protocol to be healthy.
TVL Cap: Stop deposits when total assets exceed the approved ceiling.
Oracle Guard: Pause or block actions when price feeds deviate.
Rate Limit: Throttle sensitive functions to slow down exploits.
Invariants are evaluated every tx
Policies act as a last line of defense, even if core logic has a bug.
Recipe 1: The TVL Cap
Prevent a new vault from accepting too many deposits before it's battle-tested.
// Parameters
const MAX_TVL = 1000000 * 10^18; // 1M ETH (or tokens)
const VAULT = 0xVAULT_ADDRESS;
// Allow deposits ONLY if post-tx TVL is safe
if (function == "deposit") {
// Check state AFTER execution
// (Assuming vault has a totalAssets() view)
check_after VAULT.totalAssets() <= MAX_TVL
allow
}Recipe 2: The Circuit Breaker (Oracle Guard)
Prevent operations if the Oracle price is deviating wildly (a sign of manipulation or a crash).
permission OracleDeviationGuard -> 1.0.0 {
parameters: {
feed: address,
maxAnswer: uint256,
minTwap: uint256
}
pub fn oracleInBounds(answer: uint256, twap: uint256) -> bool {
if (answer > parameters.maxAnswer) {
return false;
}
return twap >= parameters.minTwap;
}
fn main() -> bool {
return context.target == parameters.feed;
}
}Recipe 3: Function Rate Limit
Limit how often a sensitive function (like harvest()) can be called to prevent MEV spam.
permission HarvestRateLimit -> 1.0.0 {
parameters: {
harvester: address
}
fn main() -> bool {
return context.caller == parameters.harvester;
}
}