Skip to main content
The Sudo Policy grants unrestricted access to specified contract functions. It’s the simplest policy—and the most powerful.

When to Use Sudo

Target contract is audited and trusted (Uniswap, Aave, Morpho)
No user funds at direct risk (game actions, governance votes)
You need simplicity over granular control
Combined with time limits or usage limits

When NOT to Use Sudo

Agent handles significant user funds without other limits
Target contract has dangerous functions (e.g., approve for arbitrary spenders)
You need spending caps or parameter validation
Indefinite access without time bounds

Basic Usage

const actions = mcNexus.buildSessionAction({
  type: 'transfer',
  data: {
    chainIds: [10],
    contractAddress: UNISWAP_ROUTER,
    policies: [{ type: "sudo" }]
  }
})

Agent Examples

Yield Optimizer Agent

Trust deposits/withdrawals on vetted protocols:
const TRUSTED_PROTOCOLS = {
  morpho: "0xA2Cac0023a4797b4729Db94783405189a4203AFc",
  aave: "0x...",
};

const now = Math.floor(Date.now() / 1000)
const validAfter = now
const validUntil = now + 3600

const timeframePolicy = mcNexus.buildActionPolicy({
  type: "timeframe",
  validAfter, // unix-timestamp when policy becomes active
  validUntil  // unix-timestamp when policy expires
});

// Morpho deposit
const [actionOne] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [10],
    contractAddress: TRUSTED_PROTOCOLS.morpho,
    functionSignature: toFunctionSelector("deposit(uint256,address)"),
    policies: [timeframePolicy]
  }
})

// Morpho withdraw
const [actionTwo] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [10],
    contractAddress: TRUSTED_PROTOCOLS.morpho,
    functionSignature: toFunctionSelector("withdraw(uint256,address,address)"),
    policies: [timeframePolicy]
  }
})

// Aave supply
const [actionThree] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [10],
    contractAddress: TRUSTED_PROTOCOLS.aave,
    functionSignature: toFunctionSelector("supply(address,uint256,address,uint16)"),
    policies: [timeframePolicy]
  }
})

// Aave withdraw
const [actionFour] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [10],
    contractAddress: TRUSTED_PROTOCOLS.aave,
    functionSignature: toFunctionSelector("withdraw(address,uint256,address)"),
    policies: [timeframePolicy]
  }
})

const quote = await meeClient.getSessionQuote({
  mode: "PREPARE",
  enableSession: {
    redeemer: agentSigner.address,
    actions: [actionOne, actionTwo, actionThree, actionFour],
    // Cap gas spend
    maxPaymentAmount: parseUnits("50", 6),
  },
  simulation: { simulate: true },
  feeToken: { address: USDC, chainId: 8453 },
  // Fund SCA
  trigger: {
    tokenAddress: USDC,
    chainId: 8453,
    amount: parseUnits("2", 6),
  },
  // Any additional Instructions
  instructions: [...]
});

// Store the sessions details for later use.
let sessionDetails: SessionDetail[] = [];

if (quote) {
  const { hash } = await meeClient.executeSessionQuote(quote);
  await meeClient.waitForSupertransactionReceipt({ hash });

  if (quote.sessionDetails) sessionDetails = quote.sessionDetails;
}

Gaming Agent

Full access to game contract with usage limits:
const GAME_CONTRACT = "0x...";

const [claimAction] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [8453],
    contractAddress: GAME_CONTRACT,
    functionSignature: toFunctionSelector("claimRewards()"),
    policies: [
      {
        type: "usageLimit",
        limit: 100n // Max 100 claims
      }
    ]
  }
})

const [performAction] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [8453],
    contractAddress: GAME_CONTRACT,
    functionSignature: toFunctionSelector("performAction(uint256)"),
    policies: [
      {
        type: "usageLimit",
        limit: 1000n // Max 1000 actions
      }
    ]
  }
})

Governance Agent

Vote on proposals automatically:
const GOVERNOR = "0x...";

const [castVoteAction] = mcNexus.buildSessionAction({
  type: 'custom',
  data: {
    chainIds: [8453],
    contractAddress: GOVERNOR,
    functionSignature: toFunctionSelector("castVote(uint256,uint8)"),
    policies: [
      // 1 year for governance
      {
        type: "timeframe",
        validAfter: Math.floor(Date.now() / 1000),
        validUntil: Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60
      }
    ]
  }
})

Security Checklist

Timeframe Policy configured
Only specific functions allowed (not entire contract)
Target contract is audited
Usage limit considered for high-risk actions
Gas spend capped (maxPaymentAmount)

Common Mistakes

Granting Sudo to approve() functionThis lets the agent approve arbitrary spenders. Never do this:
// ❌ DANGEROUS
functionSignature: toFunctionSelector("approve(address,uint256)")
No time limitWithout timeframe policy, the permission never expires:
// ❌ BAD - no time limit
const actions = mcNexus.buildSessionAction({
  type: 'transfer',
  data: {
    chainIds: [10],
    contractAddress: UNISWAP_ROUTER,
    policies: [{ type: "sudo" }]
  }
})

// ✅ GOOD - expires in 30 days
const now = Math.floor(Date.now() / 1000)
const validAfter = now
const validUntil = now + 30 * 24 * 60 * 60

const actions = mcNexus.buildSessionAction({
  type: 'transfer',
  data: {
    chainIds: [10],
    contractAddress: UNISWAP_ROUTER,
    policies: [
      { type: "sudo" },
      {
        type: "timeframe",
        validAfter,
        validUntil
      }
    ]
  }
})

When to Upgrade to Universal Action

Switch to Universal Action when you need:
  • Spending limits (per-action or total)
  • Recipient whitelisting
  • Parameter validation
  • Cumulative caps
See Universal Action Policy for details.