> For the complete documentation index, see [llms.txt](https://docs.ur.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ur.app/api-reference/smart-contracts.md).

# Smart contracts

## Source code & audits

* **Contract Source Code**: <https://github.com/ur-app/ur-contracts>
* **Audit Reports**: <https://github.com/ur-app/ur-contracts/tree/main/Audits>

## Environment

Most of UR's core functionalities, including account management and card operations, are deployed and executed exclusively on the **Mantle Network**. Interactions with other chains (such as Ethereum, Arbitrum, Base, Monad, and Tempo) are only required for specific features like **Deposit** and **Cash to Crypto**.

For deployment, we recommend using [QuickNode](https://www.quicknode.com/) or [Alchemy](https://www.alchemy.com/) as your RPC provider.

### Mantle mainnet

* **Chain ID**: 5000
* **RPC Endpoint**: <https://rpc.mantle.xyz>

### Mantle Sepolia testnet

* **Chain ID**: 5003
* **RPC Endpoint**: <https://rpc.sepolia.mantle.xyz>

### Chain explorers

| Network      | Mainnet                      | Testnet                              |
| ------------ | ---------------------------- | ------------------------------------ |
| Mantle       | <https://mantlescan.xyz/>    | <https://sepolia.mantlescan.xyz/>    |
| Ethereum     | <https://etherscan.io/>      | <https://sepolia.etherscan.io/>      |
| Arbitrum One | <https://arbiscan.io/>       | <https://sepolia.arbiscan.io/>       |
| Base         | <https://basescan.org/>      | <https://sepolia.basescan.org/>      |
| BSC          | <https://bscscan.com/>       | <https://testnet.bscscan.com/>       |
| Monad        | <https://monadscan.com/>     | <https://testnet.monadscan.com/>     |
| Tempo        | <https://explore.tempo.xyz/> | <https://explore.testnet.tempo.xyz/> |

## Functions

### Account

Our account model is based on the ERC721 NFT standard; each user has a unique UR ID (Token ID) that identifies and manages their assets and permissions on the UR platform.\
The user's KYC status is recorded in the contract's `status` mapping, with each status corresponding to a numeric value as follows:

#### **Contract addresses**

| Network | Address                                                                                                                           |
| ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Mainnet | [`0x4a05148119683E0A41b52fb973EEF0EE81536c47`](https://mantlescan.xyz/address/0x4a05148119683E0A41b52fb973EEF0EE81536c47)         |
| Testnet | [`0xfE6fB4aE524c8f032E14691C3B2465cc5bcB9677`](https://sepolia.mantlescan.xyz/address/0xfE6fB4aE524c8f032E14691C3B2465cc5bcB9677) |

#### **Methods**

| Function Name         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ownerOf`             | Query EVM wallet address by URID.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `tokenOfOwnerByIndex` | Query URID by EVM wallet address. This ERC721Enumerable method returns the token ID owned by an address at a given index. Since each user should hold one Account NFT, use `index = 0` to get the user's URID.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `status`              | <p>Status: KYC passed, status is <code>Live</code>. Functions for <code>non-Live</code> statuses are restricted.<br><br><code>SoftBlocked, // 1</code><br><code>Tourist, // 2</code><br><code>Blocked, // 3</code><br><code>Closed, // 4</code><br><code>Live // 5</code></p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `limit`               | <p>Query user monthly transaction limit by URID.<br>All outgoing Fiat transactions count towards this limit.<br>For KYC-verified users, the default monthly limit is <strong>30,000 CHF</strong>.<br><br>Returns <code>usedLimit</code> (uint256), <code>clientLimit</code> (uint256), <code>startLimitDate</code> (uint256).<br><br>Users receive a spending limit that refreshes every 30 days.<br><br>- <strong>usedLimit</strong> (<code>uint256</code>): Amount of the limit already used in the <em>current</em> 30-day cycle. This value is reset every 30 days.<br>- <strong>clientLimit</strong> (<code>uint256</code>): Total allowed limit for the current 30-day period.<br>- <strong>startLimitDate</strong> (<code>uint256</code>): Timestamp of the last limit reset (start time of the current 30-day cycle).</p> |

#### **ABI**

[Fiat24Account.sol](https://github.com/ur-app/ur-contracts/blob/main/src/Fiat24Account.sol)

#### Example: get URID by wallet address (TypeScript + viem)

```typescript
import { createPublicClient, http, parseAbi } from 'viem'
import { mantle } from 'viem/chains'

const client = createPublicClient({
  chain: mantle,
  transport: http('https://rpc.mantle.xyz')
})

const abi = parseAbi([
  'function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)'
])

const accountContractAddress = '0x4a05148119683E0A41b52fb973EEF0EE81536c47'
const userAddress = '0x...' // Replace with the user's wallet address

async function getUrid() {
  try {
    const tokenId = await client.readContract({
      address: accountContractAddress,
      abi: abi,
      functionName: 'tokenOfOwnerByIndex',
      args: [userAddress, 0n]
    })

    console.log(`URID: ${tokenId.toString()}`)
  } catch (error) {
    console.error('Error fetching URID:', error)
  }
}

getUrid()
```

### Fiat balance

#### **Contract addresses**

| Currency | Mainnet                                                                                                                   | Testnet                                                                                                                           |
| -------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| USD      | [`0xD598839598bBF508b97697b7D9e80054D4bcaaCC`](https://mantlescan.xyz/address/0xD598839598bBF508b97697b7D9e80054D4bcaaCC) | [`0xdf79470986629ae4893BfCE0c6C0F4d085E99741`](https://sepolia.mantlescan.xyz/address/0xdf79470986629ae4893BfCE0c6C0F4d085E99741) |
| EUR      | [`0x0578be9C858e6562dd8cd11a738b89Ca48194dA5`](https://mantlescan.xyz/address/0x0578be9C858e6562dd8cd11a738b89Ca48194dA5) | [`0x5E52c8993283023B83e87eF577f7f51Fa1c5B007`](https://sepolia.mantlescan.xyz/address/0x5E52c8993283023B83e87eF577f7f51Fa1c5B007) |
| CHF      | [`0x53587A05ccDdCE555C2Cd7cE4C9c5Bc3D912E2f3`](https://mantlescan.xyz/address/0x53587A05ccDdCE555C2Cd7cE4C9c5Bc3D912E2f3) | [`0x52837070C96C6D5E23ed90a43479c0237c41864c`](https://sepolia.mantlescan.xyz/address/0x52837070C96C6D5E23ed90a43479c0237c41864c) |
| CNH      | [`0xa0af0C397CB0A52F5E8Bc7BB89068dDDfaE9F211`](https://mantlescan.xyz/address/0xa0af0C397CB0A52F5E8Bc7BB89068dDDfaE9F211) | [`0x4AfbC767e6d310296657b7759a5F2c303F26B327`](https://sepolia.mantlescan.xyz/address/0x4AfbC767e6d310296657b7759a5F2c303F26B327) |
| SGD      | [`0x8F7F92F2A0247cc8660C4C4EF69582Bc6849B4d9`](https://mantlescan.xyz/address/0x8F7F92F2A0247cc8660C4C4EF69582Bc6849B4d9) | [`0x2FEb2d95ce8eC88931c4031cdd2875C90EDC87FE`](https://sepolia.mantlescan.xyz/address/0x2FEb2d95ce8eC88931c4031cdd2875C90EDC87FE) |
| JPY      | [`0x3bC9fC0460cAC2DdD352848ECc0BFe204c220717`](https://mantlescan.xyz/address/0x3bC9fC0460cAC2DdD352848ECc0BFe204c220717) | [`0x8af3be43607cb1e57b6e37fda99b6b988c5b48f0`](https://sepolia.mantlescan.xyz/address/0x8af3be43607cb1e57b6e37fda99b6b988c5b48f0) |
| HKD      | [`0x64266a15432004708e5fCA0239f664d069853374`](https://mantlescan.xyz/address/0x64266a15432004708e5fCA0239f664d069853374) | [`0x30c94bCF88c5c8f3Ff08F38242a38C656Bb28a6d`](https://sepolia.mantlescan.xyz/address/0x30c94bCF88c5c8f3Ff08F38242a38C656Bb28a6d) |

#### **Methods**

| Method      | Description                                                                                                                                                                                                     |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `balanceOf` | Query a user's fiat token balance by their address.                                                                                                                                                             |
| `decimals`  | Precision of the token. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`).                                                             |
| `allowance` | This function can be used to query the amount a user has approved for a given spender. Generally, for an unlimited approval, we call the approve method with value set to the maximum of uint256, i.e. 2^256-1. |

#### **ABI**

[Fiat24Token.sol](https://github.com/ur-app/ur-contracts/blob/main/src/Fiat24Token.sol)

#### Example: get balance (TypeScript + viem)

```typescript
import { createPublicClient, http, parseAbi, formatUnits } from 'viem'
import { mantle } from 'viem/chains'

// 1. Create a client connected to Mantle Mainnet
const client = createPublicClient({
  chain: mantle,
  transport: http('https://rpc.mantle.xyz')
})

// 2. Define the ABI for balanceOf and decimals
const abi = parseAbi([
  'function balanceOf(address owner) view returns (uint256)',
  'function decimals() view returns (uint8)'
])

// 3. Contract and User addresses
const eurContractAddress = '0x0578be9C858e6562dd8cd11a738b89Ca48194dA5' // EUR on Mantle Mainnet
const userAddress = '0x...' // Replace with the user's wallet address

async function getBalance() {
  try {
    // 4. Read contract data
    const [balance, decimals] = await Promise.all([
      client.readContract({
        address: eurContractAddress,
        abi: abi,
        functionName: 'balanceOf',
        args: [userAddress]
      }),
      client.readContract({
        address: eurContractAddress,
        abi: abi,
        functionName: 'decimals'
      })
    ])

    // 5. Format and display the balance
    console.log(`Raw Balance: ${balance}`)
    console.log(`Decimals: ${decimals}`)
    console.log(`Formatted Balance: ${formatUnits(balance, decimals)} EUR`)
    
  } catch (error) {
    console.error('Error fetching balance:', error)
  }
}

getBalance()
```

### Money transfer

#### **Contract addresses**

**Contract refers to the** [**currency contracts**](#contract-address-1)**.**

#### **Methods**

> **Note:** Only users in **Live** status (`status == 5`) are allowed to transfer their fiat tokens out in any form.

| Method                | Description                                                                                                                                                                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transfer`            | Transfer fiat token to any EVM address.                                                                                                                                                                                               |
| `transferByAccountId` | Transfer fiat tokens to the target user by their URID.                                                                                                                                                                                |
| `clientPayout`        | <p>User to transfer their currency out via bank transfer to a UR-supported bank account.<br>Before the user calls this contract function, a payout account (contactId) must be created through UR's API (The API is coming soon).</p> |

#### Example: transfer fiat (TypeScript + viem)

```typescript
import { createWalletClient, http, parseAbi, parseUnits } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mantle } from 'viem/chains'

// 1. Setup Wallet Client (Required for write operations)
// ⚠️ NEVER hardcode private keys in production code
const account = privateKeyToAccount('0x...') 
const client = createWalletClient({
  account,
  chain: mantle,
  transport: http('https://rpc.mantle.xyz')
})

// 2. Define ABI for transfer
const abi = parseAbi([
  'function transfer(address to, uint256 amount) returns (bool)'
])

// 3. Configuration
const eurContractAddress = '0x0578be9C858e6562dd8cd11a738b89Ca48194dA5' // EUR Contract
const recipientAddress = '0x...' // Receiver's address
const amountToSend = '10' // Amount in EUR

async function transferFiat() {
  try {
    // 4. Send Transaction
    // Note: Ensure the sender has enough balance and ETH(MNT) for gas
    const hash = await client.writeContract({
      address: eurContractAddress,
      abi: abi,
      functionName: 'transfer',
      args: [
        recipientAddress, 
        parseUnits(amountToSend, 2) // Assuming 2 decimals for EUR
      ]
    })

    console.log(`Transaction sent! Hash: ${hash}`)
  } catch (error) {
    console.error('Transfer failed:', error)
  }
}

transferFiat()
```

### Money exchange

Also known as foreign-exchange conversion, used for exchanging between fiat currencies.

#### **Contract addresses**

| Network                | Address                                                                                                                           |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Mantle Mainnet         | [`0x9F88e04D129d4a4247F009833ba0Bd5D8F6A2146`](https://mantlescan.xyz/address/0x9F88e04D129d4a4247F009833ba0Bd5D8F6A2146)         |
| Mantle Sepolia Testnet | [`0x2C2E6BC745e583629a4157c2D8a9234d59F4067e`](https://sepolia.mantlescan.xyz/address/0x2C2E6BC745e583629a4157c2D8a9234d59F4067e) |

#### **Methods**

> **Note:** Only users in **Live** status (`status = 5`) are allowed to do money exchange.

| Method                 | Description                                                             |
| ---------------------- | ----------------------------------------------------------------------- |
| `moneyExchangeExactIn` | Exchange between 2 currencies                                           |
| `getExchangeRate`      | Query the exchange rate between two specified currency token addresses. |

#### **ABI**

[Fiat24CryptoRelay.sol](https://github.com/ur-app/ur-contracts/blob/main/src/Fiat24CryptoRelay.sol)

#### Example: money exchange (TypeScript + viem)

This process involves two steps:

1. Query the current exchange rate using `getExchangeRate`.
2. Execute the exchange using `moneyExchangeExactin`.

```typescript
import { createPublicClient, createWalletClient, http, parseAbi, parseUnits, formatUnits } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mantle } from 'viem/chains'

// 1. Setup Clients
const account = privateKeyToAccount('0x...')
const publicClient = createPublicClient({
  chain: mantle,
  transport: http('https://rpc.mantle.xyz')
})
const walletClient = createWalletClient({
  account,
  chain: mantle,
  transport: http('https://rpc.mantle.xyz')
})

// 2. Define ABI
const abi = parseAbi([
  'function getExchangeRate(address srcToken, address destToken) view returns (uint256)',
  'function moneyExchangeExactin(address srcToken, address destToken, uint256 srcAmount, uint256 minDestAmount) returns (uint256)'
])

// 3. Configuration
const exchangeContractAddress = '0x9F88e04D129d4a4247F009833ba0Bd5D8F6A2146'
const eurAddress = '0x0578be9C858e6562dd8cd11a738b89Ca48194dA5' // Source: EUR
const usdAddress = '0xD598839598bBF508b97697b7D9e80054D4bcaaCC' // Destination: USD
const amountInEur = '100' // Exchange 100 EUR

async function exchangeCurrency() {
  try {
    // 4. Step 1: Get Exchange Rate
    const rate = await publicClient.readContract({
      address: exchangeContractAddress,
      abi: abi,
      functionName: 'getExchangeRate',
      args: [eurAddress, usdAddress]
    })
    console.log(`Current Rate: ${formatUnits(rate, 18)}`) // Rate has 18 decimals

    // 5. Calculate Minimum Destination Amount (Slippage Protection)
    // Example: Allow 1% slippage
    const srcAmount = parseUnits(amountInEur, 2) // EUR has 2 decimals
    const expectedDestAmount = (srcAmount * rate) / parseUnits('1', 18)
    const minDestAmount = (expectedDestAmount * 99n) / 100n 

    // 6. Step 2: Execute Exchange
    const hash = await walletClient.writeContract({
      address: exchangeContractAddress,
      abi: abi,
      functionName: 'moneyExchangeExactin',
      args: [eurAddress, usdAddress, srcAmount, minDestAmount]
    })

    console.log(`Exchange submitted! Hash: ${hash}`)
  } catch (error) {
    console.error('Exchange failed:', error)
  }
}

exchangeCurrency()
```

### Deposit (off-ramp)

#### **Contract addresses**

| Network      | Mainnet                                                                                                                                   | Testnet                                                                                                                                            |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Mantle       | [`0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083`](https://mantlescan.xyz/address/0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083)                 | [`0xd6d4C6eB84697cB9bf0045e88b8f3A0bD42D3d66`](https://sepolia.mantlescan.xyz/address/0xd6d4C6eB84697cB9bf0045e88b8f3A0bD42D3d66)                  |
| Arbitrum     | [`0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083`](https://arbiscan.io/address/0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083#readProxyContract)  | [`0xCa8eFFac628001B86e068b8367174F91E7E88357`](https://sepolia.arbiscan.io/address/0xCa8eFFac628001B86e068b8367174F91E7E88357)                     |
| Ethereum     | [`0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083`](https://etherscan.io/address/0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083#readProxyContract) | [`0xF67b89d376D3aAA872E151B4526271D9394aE192`](https://sepolia.etherscan.io/address/0xF67b89d376D3aAA872E151B4526271D9394aE192)                    |
| Base Network | [`0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083`](https://basescan.org/address/0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083)                   | [`0xd6d4C6eB84697cB9bf0045e88b8f3A0bD42D3d66`](https://sepolia.basescan.org/address/0xd6d4C6eB84697cB9bf0045e88b8f3A0bD42D3d66#writeProxyContract) |
| Monad        | [`0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083`](https://monadscan.com/address/0xd08B421A33F9b09A59E2ebf72afEF2365ce5b083)                  | [`0x886DCF3BCb4fe8b2b07366C9F9aEbD3e471E8abA`](https://testnet.monadscan.com/address/0x886DCF3BCb4fe8b2b07366C9F9aEbD3e471E8abA)                   |
| Tempo        | [`0xd69016A2C64cF7f075F8644b96419421afd44e71`](https://explore.tempo.xyz/address/0xd69016A2C64cF7f075F8644b96419421afd44e71)              | [`0xe20C2CF90f1e4AA8ABE20a6562C16B3601ad29BF`](https://explore.testnet.tempo.xyz/address/0xe20C2CF90f1e4AA8ABE20a6562C16B3601ad29BF)               |

#### **Methods**

> Note: Only users with status **Live (5)** or **SoftBlocked (1)** can perform deposit(off-ramp) transactions.

| Method                               | Description                                                                                                                                                                                                                                                                                 |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `depositTokenViaUsdc`                | The user deposits USDC into the contract and receives fiat currency in their UR account.                                                                                                                                                                                                    |
| `depositTokenViaAggregator`          | <p>Supports users depositing a specific crypto asset and receiving fiat currency in their UR account.<br><br><em>The prerequisite is that the frontend must integrate a DEX/aggregator API(API is coming soon) and construct the Crypto → USDC swap as calldata.</em></p>                   |
| `depositTokenViaAggregatorToAccount` | Same as `depositTokenViaAggregator`, with one extra parameter `_targetAccount`: the user's UR Account address that receives the resulting fiat. Used when the signing Crypto Wallet is **not** the user's UR Account itself (e.g., a Partner-side external wallet in Managed Custody Mode). |
| `depositWithFee`                     | Tempo chain only. The user deposits a supported stablecoin into the contract and receives fiat currency in their UR Account. No external DEX aggregator is required.                                                                                                                        |
| `depositWithFeeTo`                   | Tempo chain only. Same as `depositWithFee`, with one extra parameter `recipient`: the address that receives the resulting fiat. Used when the signing wallet is not the user's UR Account itself.                                                                                           |

#### **ABI**

[Fiat24CryptoDeposit.sol](https://github.com/ur-app/ur-contracts/blob/main/src/Fiat24CryptoDeposit.sol)

[Fiat24CryptoDeposit\_Tempo.sol](https://github.com/ur-app/ur-contracts/blob/main/src/Fiat24CryptoDeposit_Tempo.sol)

### Onramp

{% hint style="warning" %}
**Available soon.** On-ramp (fiat-to-crypto) is not yet available for integration and will be enabled in a future release. The reference below is provided for preview only.
{% endhint %}

#### **Contract addresses**

| Network                    | Mainnet                                                                                                                      | Testnet                                                                                                                              |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Mantle                     | [`0x2460634bf887A0F4E885278B93E10f91D48a5a8c`](https://mantlescan.xyz/address/0x2460634bf887A0F4E885278B93E10f91D48a5a8c)    | [`0x9291da7e1807bc6Ea230241fFd5BC25E2f105DAB`](https://sepolia.mantlescan.xyz/address/0x9291da7e1807bc6Ea230241fFd5BC25E2f105DAB)    |
| Arbitrum/Base/Ethereum/BSC | `0xAACe017F0a6Bb9890E449d5b27fbcA9C440b81e9`                                                                                 |                                                                                                                                      |
| Tempo                      | [`0xb4aB250c3Bf849B3C9529AE7dac3c97267febF92`](https://explore.tempo.xyz/address/0xb4aB250c3Bf849B3C9529AE7dac3c97267febF92) | [`0xc88AC8d0c118D231E5E88Ac6819a4E546457b1B6`](https://explore.testnet.tempo.xyz/address/0xc88AC8d0c118D231E5E88Ac6819a4E546457b1B6) |

> **Note:** Partners only need the **Mantle** address. Onramp is initiated and settled against the user's fiat balance on Mantle. The contracts on the other chains (Arbitrum, Base, Ethereum, BSC, Tempo) run automatically: after the funds bridge out, the swap on the destination chain is triggered by the contract itself through LayerZero. Partners never call the non-Mantle addresses directly, so those addresses are listed for reference only.

#### **Methods**

#### **ABI**

[BufferPool.sol](https://github.com/ur-app/ur-contracts/blob/main/src/BufferPool.sol)

### Card

#### **Contract addresses**

**Contract refers to the** [**currency contracts**](#contract-address-1)**.**

**Spender Contract (Card Authorization):**

| Network | Address                                                                                                                           |
| ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Mainnet | [`0xb9d38DDE25f67D57af5b91C254F869F90d483d05`](https://mantlescan.xyz/address/0xb9d38DDE25f67D57af5b91C254F869F90d483d05)         |
| Testnet | [`0x25d66C564532258eD9cdBB6215E260AFf41d8bae`](https://sepolia.mantlescan.xyz/address/0x25d66C564532258eD9cdBB6215E260AFf41d8bae) |

#### Methods

To use the UR debit card, users must authorize the **Spender Contract** to spend their **Fiat** or **USDe** balance via `approve` or `permit` methods.

| Method               | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `approve` / `permit` | <p>Authorize the <strong>Spender Contract</strong> to spend funds.<br><br>The debit card payments are booked by the Spender contract via the <code>authorize()</code> function. Therefore, the card owner needs to approve a certain limit to the Spender contract for future card spendings.<br><br><strong>Supported Assets:</strong><br>- <strong>Fiat Tokens:</strong> Users must approve the corresponding Fiat token contract.<br>- <strong>USDe:</strong> Users can also authorize USDe directly for consumption.<br><br><strong>Usage Notes:</strong><br>- <strong>Enable Authorization:</strong> It is common practice to approve the maximum <code>uint256</code> value (<code>2^256 - 1</code>) to ensure uninterrupted service.<br>- <strong>Revoke Authorization:</strong> To cancel the authorization, call the <code>approve</code> method with an amount of <code>0</code>.</p> |

#### **ABI**

[Fiat24Token.sol](https://github.com/ur-app/ur-contracts/blob/main/src/Fiat24Token.sol)

#### Card transaction flow

![Card Transaction Flow](/files/W751uXZkIj6dW6dQBFB6)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ur.app/api-reference/smart-contracts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
