Matador Docs
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;
    }
}

On this page