Move digital assets within your limits.

Keep transfers by AI agents and automated services within approved assets, destinations, and amounts. Require approval where your business needs it.

What if…

Your hot wallet gets hit like Binance?

Binance lost about $6.3B in October 2026. On Ethereum, signed delegations let an attacker take over a hot wallet.You choose whether your wallet can delegate.Case and policy

The delegation pointed to a sweeper contract. It could move funds and collect new deposits without another wallet signature. This was one part of the multichain theft.

Need delegates? Choose which contracts can act for your wallet and on which networks. Require approval before granting that access, or keep delegation off entirely.

Choose who can act for your wallet

authority "delegation-control" {
    intent = "evm.7702"
    version = "1"

    config {
        chainId = 1
    }

    approver security {
        type = "reference"
        id = "security"
        ref = "security@sha256:<digest>"
    }

    policy "delegation-control" {
        allow when {
            chainId == 1
            address == "0x1111111111111111111111111111111111111111"
            nonce == 7
        }

        require security
    }
}

The recipient changes after approval?

Bybit’s signers saw a routine transfer in the wallet interface. The compromised interface submitted a different transaction for signing. The February 2025 theft cost about $1.5B.You approve the transfer that actually gets signed.Case and policy

The compromised Safe interface hid a transaction that gave the attacker control of the wallet.

The mandate and approvals are cryptographically bound to the exact transaction and signing key. A different recipient, amount, or transaction requires a new mandate and fresh approvals.

How approvals cover the request

A trusted dApp asks you to approve a drainer?

Malicious Ledger Connect Kit releases made dApps request draining transactions in December 2023.You control which contracts your key can call.Case and policy

A phished npm account let the attacker publish modified JavaScript through the usual package channel.

Choose the contracts and methods your services may use, then set limits for each call. Unlisted calls can’t get your signature. MPC keeps a compromised app from extracting the full key and signing around those controls.

Choose contracts and methods

contract usdc: evm {
    address = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"

    fn transfer(to: address, amount: uint256)

    fn approve(spender: address, amount: uint256)
}

let USDC = 1000000
let router = "0xe592427a0aece92de3edee1f18e0157c05861564"

approver treasury {
    type = "reference"
    id = "treasury"
    ref = "treasury@sha256:<digest>"
}

approver security {
    type = "reference"
    id = "security"
    ref = "security@sha256:<digest>"
}

policy "token-spending" {
    allow "transfer" when {
        usdc.transfer != null
        usdc.transfer.amount > 0
        usdc.transfer.amount <= 10000 * USDC
        transaction.value == 0
        transaction.gasLimit <= 100000
    }

    allow "bounded-allowance" when {
        usdc.approve != null
        usdc.approve.spender == router
        usdc.approve.amount > 0
        usdc.approve.amount <= 1000 * USDC
        transaction.value == 0
    }

    allow "revoke-allowance" when {
        usdc.approve != null
        usdc.approve.amount == 0
        transaction.value == 0
    }

    require 2 of [treasury, security] if (
        usdc.transfer != null and usdc.transfer.amount > 1000 * USDC
    )
    require security if (usdc.approve != null and usdc.approve.amount > 0)
}

Security Model

Declare the contract. Control the call.

Choose which contracts and methods your services can use. Set separate limits for transfers and token allowances.

Read the technical guide
Contract and policytransfer-limits.edict
authority "transfer-limits" {
    intent = "evm.transaction"
    version = "1"

    config {
        chainId = 1
    }

    contract usdc: evm {
        address = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"

        fn transfer(to: address, amount: uint256)

        fn approve(spender: address, amount: uint256)
    }

    let USDC = 1000000
    let router = "0xe592427a0aece92de3edee1f18e0157c05861564"

    approver treasury {
        type = "reference"
        id = "treasury"
        ref = "treasury@sha256:<digest>"
    }

    approver security {
        type = "reference"
        id = "security"
        ref = "security@sha256:<digest>"
    }

    policy "token-spending" {
        allow "transfer" when {
            usdc.transfer != null
            usdc.transfer.amount > 0
            usdc.transfer.amount <= 10000 * USDC
            transaction.value == 0
            transaction.gasLimit <= 100000
        }

        allow "bounded-allowance" when {
            usdc.approve != null
            usdc.approve.spender == router
            usdc.approve.amount > 0
            usdc.approve.amount <= 1000 * USDC
            transaction.value == 0
        }

        allow "revoke-allowance" when {
            usdc.approve != null
            usdc.approve.amount == 0
            transaction.value == 0
        }

        require 2 of [treasury, security] if (
            usdc.transfer != null and usdc.transfer.amount > 1000 * USDC
        )
        require security if (usdc.approve != null and usdc.approve.amount > 0)
    }
}

Consistent controls. Across your assets.

Use one approval process across Bitcoin, EVM networks, Solana, TRON, XRP, and Stellar. Choose transfer limits and destinations for each asset.

Read the technical guide

Protect funds beyond a single host.

Distribute transfer authority across independent peers. Configure the threshold and deployment size around the compromise and outage tolerance your business needs.

How MPC works