# Card contract architecture and security

Learn how Stripe card contracts pull funds from non-custodial wallets and keep customer funds secure.

Stablecoin-backed cards can draw funds from your cardholders’ existing non-custodial wallets. The wallet owner grants a Stripe-controlled smart contract permission to pull funds at authorization. This page explains how the contract works and the security measures that protect cardholder funds.

To submit an approval, see [set up non-custodial wallet approvals](https://docs.stripe.com/issuing/bridge-stablecoin-cards/noncustodial-wallets.md). The diagrams on this page use EVM terms. On Solana, the equivalent of a program’s approval address is a program-derived address for your program.

## Security guarantees

The contract’s code enforces these guarantees, so they can’t be bypassed:

- **Funds stay separate**: Customer funds stay in each user’s own wallet until a card authorization transfers them to Stripe.
- **Approvals are scoped to one program**: An approval granted to one Stripe Issuing program can’t be used by another program.
- **Funds have a fixed destination**: Funds can only move to a secure Stripe wallet (rather than an arbitrary address), which requires coordination among multiple Stripe employees to access.

## Program setup

When Stripe sets up your card program, the contract creates an approval address that belongs to your program and sets a fixed destination for it. Funds can only ever move from a user’s wallet to that destination, which is a Stripe-controlled wallet that requires signatures from multiple Stripe employees to move funds out of.

Stripe's backend registers Issuing Program A with the Stripe card contract and sets destination 0x123. The contract creates approval address 0xabc for Program A, which can only transfer funds to 0x123 (See full diagram at https://docs.stripe.com/issuing/bridge-stablecoin-cards/contract-security)

```text
[Stripe’s backend] -- Register Issuing Program A with destination 0x123 --> [Stripe card contract]
[Stripe card contract] -- Create approval address 0xabc for Program A --> [Stripe’s backend]
```

## Approval structure

The contract creates a dedicated approval address for each card program. Wallet owners approve your program’s address, allowing the contract to pull funds from their wallets only for your program. Other programs can’t use that approval.

The Stripe card contract controls a separate approval address for each issuing program: 0xabc for Program A and 0xdef for Program B. User A's and User B's wallets approve Program A's address, and User C's wallet approves Program B's address (See full diagram at https://docs.stripe.com/issuing/bridge-stablecoin-cards/contract-security)

```text
[Stripe card contract] --> [Program A: 0xabc…]
[Stripe card contract] --> [Program B: 0xdef…]
[User A’s wallet] --> [Program A: 0xabc…]
[User B’s wallet] --> [Program A: 0xabc…]
[User C’s wallet] --> [Program B: 0xdef…]
```

In this diagram, Program A’s address is shared by User A’s and User B’s wallets, and Program B’s address by User C’s wallet. Green borders mark parts that Stripe controls, and orange borders mark wallets that your users control.

The contract supports these approval standards:

- **ERC-20 approval**: A one-time approval for a fixed or unlimited amount.
- **[Permit2](https://docs.uniswap.org/contracts/permit2/overview) approval**: A one-time approval for a fixed or unlimited amount that expires after a set period.

## Debit flow

When a card is authorized, Stripe instructs the contract to debit the cardholder’s wallet. The contract transfers the funds directly to your program’s designated Stripe wallet and prevents transfers to any other address.

When a Program A card is authorized, Stripe's backend asks the Stripe card contract to debit User A's wallet. The contract uses Program A's approval address to move the funds directly from User A's wallet to the secure Stripe wallet, which is the only destination it allows (See full diagram at https://docs.stripe.com/issuing/bridge-stablecoin-cards/contract-security)

```text
[Stripe’s backend] -- Debit for a Program A authorization --> [Stripe card contract]
[Stripe card contract] -- Pull funds with Program A’s approval --> [User A’s wallet]
[User A’s wallet] -- Funds move to the secure wallet --> [Secure Stripe wallet]
```

## Security review

Every Stripe smart contract passes an internal security review and an audit by an independent smart contract auditing firm before it’s used in production.
