Skip to content

Security and permissions

Understand the boundaries.

Yield agents can move your lending position between Aave, Venus and idle funds through a restricted router. They cannot choose a different recipient. Review the deployed contracts and their limitations below.

This page covers the yield routers. Trading, loan-protection and liquidity agents have different permissions, shown during their setup. Restricted permissions do not remove market or smart-contract risk.

USDT router

Reading balances and rotation history from BNB Smart Chain.

USDC router

Reading balances and rotation history from BNB Smart Chain.

Why a compromised agent key cannot drain these funds

A session key on BNB Smart Chain can be scoped to a target contract and a set of selectors, but not to the arguments of a call. Scope an agent to Aave's withdraw(asset, amount, to) and it picks to itself. The router exists to take that choice away. Every claim below is in contracts/src/AgripinaaYieldRouter.sol.

  • Three entrypoints, none of which takes an argument

    toAave() (0xdb1a4d6d), toVenus() (0x88b480df), and toIdle() (0x18b5e866). A key scoped to this address and these three selectors has nothing left to choose beyond which of the three to call.

  • Every recipient is hardcoded to msg.sender

    Aave mints its aTokens straight to the calling account, the Venus vTokens minted in a call are transferred back to it, and an unwind sends the stablecoin back to it. The contract has no address parameter anywhere for a caller to point at itself.

  • Delta accounting, so a donation cannot be swept

    _collectUsdt records the router's balance on entry and pays out only what that call brought in. Anything sitting in the router beforehand, whether a stray transfer or a deliberate donation, stays where it is. This is the fix for audit finding L-1, and it is why the router being empty is a property rather than a coincidence.

  • No owner, no admin, no upgrade path

    No owner variable, no privileged role, no proxy, no delegatecall, no selfdestruct. Runtime bytecode cannot change after deployment, so a security fix requires a new address instead of silently changing either contract above.

What the fuzzers checked

contracts/test/fuzz/RouterFuzz.sol drives deposits, rotations, withdrawals, and out-of-band donations across three independent actors, against mocks of BSC USDT, Aave V3, and Venus. It asserts two properties:

  • echidna_no_actor_exceeds_deposits: no actor ever holds more value than they deposited, so an attacker who deposited nothing ends with nothing, and nobody sweeps another actor's principal.
  • echidna_router_holds_only_donations: the router never custodies more than what was donated to it.

The repository runs stateful Medusa properties alongside fork tests against BNB Smart Chain state, including donated balances, ordinary venue debt, Venus VAI debt, same-target no-ops, and zero-share mint protection.

Debt guard deployment status

A compromised session key cannot move funds anywhere except back to their owner. That is the property the design above enforces and the fuzzing covers, and it is the whole claim: not that a compromised key is harmless, only that it has nowhere to send anything.

The published 2026-08-26 addresses are debt-guard version 3. They cover Aave aggregate debt, ordinary Venus market borrows, and Venus's separate VAI debt ledger. Their runtime hashes are pinned in the shared manifest and checked against live bytecode before activation or runner execution. Superseded version-2 and version-1 addresses remain owner-recovery-only; an old session cannot authorize either active replacement address.

Source: contracts/src/AgripinaaYieldRouter.sol, contracts/test/AgripinaaYieldRouter.t.sol, and contracts/test/fuzz/RouterFuzz.sol in this repository. Contract custody and raw calls on this page are read from BNB Smart Chain, not from a managed-session indexer.