Ethereum Policies
This section provides examples of common Ethereum policies.
Allow USDC Transfer
This policy allows a specific user (alice_user_id) to send USDC to either Bob or Charlie, provided the amount is less than or equal to 20 USDC.
{
"version": "1.0",
"description": "Alice can send up to 20 USDC to Bob or Charlie.",
"rules": [
{
"description": "Allow USDC transfer to Bob or Charlie under 20 limit",
"issuer": [
{
"type": "UserId",
"id": "alice_user_id"
}
],
"action": "allow",
"logic": "and",
"chain_type": "ethereum",
"conditions": [
{
"logic": "and",
"abi": {
"name": "transfer",
"type": "function",
"inputs": [
{ "name": "to", "type": "address" },
{ "name": "value", "type": "uint256" }
]
},
"group": [
{
"transaction_type": "erc20",
"transaction_attr": "to",
"operator": "in",
"value": ["0xBobAddress...", "0xCharlieAddress..."]
},
{
"transaction_type": "erc20",
"transaction_attr": "amount",
"operator": "lte",
"value": 20
}
]
}
]
}
]
}
Tiered Signing Requirements
This policy enforces different signing requirements based on the transaction amount.
- < 1 Million: Only Alice needs to sign.
- >= 1 Million: Both Alice AND Bob must sign (multi-approval is handled at the issuer level).
{
"version": "1.0",
"description": "Tiered signing requirements based on transaction amount.",
"rules": [
{
"description": "Rule 1. 1 Mil limit requires both Alice and Bob as issuers",
"issuer": [
{
"type": "UserId",
"id": "alice_user_id"
},
{
"type": "UserId",
"id": "bob_user_id"
}
],
"action": "allow",
"logic": "and",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "erc20",
"transaction_attr": "amount",
"operator": "gte",
"value": 1000000,
"abi": {
"name": "transfer",
"type": "function",
"inputs": [
{ "name": "to", "type": "address" },
{ "name": "amount", "type": "uint256" }
],
"outputs": [{ "name": "", "type": "bool" }]
}
}
]
},
{
"description": "Rule 2. Less than 1 Mil limit requires only Alice as issuer",
"issuer": [
{
"type": "UserId",
"id": "alice_user_id"
}
],
"action": "allow",
"logic": "and",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "erc20",
"transaction_attr": "amount",
"operator": "lt",
"value": 1000000,
"abi": {
"name": "transfer",
"type": "function",
"inputs": [
{ "name": "to", "type": "address" },
{ "name": "amount", "type": "uint256" }
],
"outputs": [{ "name": "", "type": "bool" }]
}
}
]
}
]
}
Allow specific smart contract function calls
Allow calling a specific function (e.g., approve) on a specific contract address.
{
"version": "1.0",
"description": "Allow approve on USDT contract",
"rules": [
{
"description": "Allow approve function on USDT",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"logic": "and",
"chain_type": "ethereum",
"conditions": [
{
"logic": "and",
"abi": {
"name": "approve",
"type": "function",
"inputs": [
{ "name": "spender", "type": "address" },
{ "name": "amount", "type": "uint256" }
]
},
"group": [
{
"transaction_type": "erc20",
"transaction_attr": "receiver",
"operator": "eq",
"value": "0xSmartContractAddress"
},
{
"transaction_type": "erc20",
"transaction_attr": "spender",
"operator": "eq",
"value": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
]
}
]
}
]
}
Allow specific NFT Transfer
Allow transferring a specific NFT token (identified by tokenId) from a specific NFT contract.
{
"version": "1.0",
"description": "Allow specific NFT transfer",
"rules": [
{
"description": "Allow BAYC NFT transfer",
"issuer": [
{ "type": "UserId", "id": "alice" }
],
"action": "allow",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "erc721",
"transaction_attr": "receiver",
"operator": "eq",
"value": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"
},
{
"transaction_type": "erc721",
"transaction_attr": "tokenId",
"operator": "eq",
"value": 12345,
"abi": {
"name": "safeTransferFrom",
"type": "function",
"inputs": [
{ "name": "from", "type": "address" },
{ "name": "to", "type": "address" },
{ "name": "tokenId", "type": "uint256" }
],
"outputs": []
}
}
]
}
]
}
Native ETH Transfer Limit
Restrict ETH transfers to a maximum of 0.1 ETH.
{
"version": "1.0",
"description": "Cap ETH transfers at 0.1 ETH",
"rules": [
{
"description": "Allow ETH transfer <= 0.1",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"logic": "and",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "100000000000000000"
}
]
}
]
}
EIP-712 Domain Restriction
Only allow signing EIP-712 messages for a specific contract.
{
"version": "1.0",
"description": "Restrict EIP-712 signing to specific contract",
"rules": [
{
"description": "Allow EIP-712 for Contract X",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"logic": "and",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "eip712",
"transaction_attr": "verifyingContract",
"operator": "eq",
"value": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
}
]
}
]
}
Allowlist recipients of a transaction
This policy restricts ETH transfers to a specific set of allowed recipient addresses.
{
"version": "1.0",
"description": "Allow ETH transfer only to whitelisted addresses",
"rules": [
{
"description": "Allow transfer to whitelist",
"issuer": [
{
"type": "*",
"id": "*"
}
],
"action": "allow",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "to",
"operator": "in",
"value": ["0xTrustedAddress1...", "0xTrustedAddress2..."]
}
]
}
]
}
Denylist recipients of a transaction
This policy blocks transfers to specific addresses (e.g., known malicious addresses). Since DENY rules take precedence, this will block the transaction even if other rules allow it.
{
"version": "1.0",
"description": "Block transfers to denylisted addresses",
"rules": [
{
"description": "Deny transfer to blacklisted addresses",
"issuer": [
{
"type": "*",
"id": "*"
}
],
"action": "deny",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "to",
"operator": "in",
"value": ["0xMaliciousAddress1...", "0xMaliciousAddress2..."]
}
]
}
]
}
Restrict transactions to specific chains
This policy ensures that transactions are only signed for a specific Chain ID (e.g., Ethereum Mainnet 1).
{
"version": "1.0",
"description": "Restrict transactions to Ethereum Mainnet",
"rules": [
{
"description": "Allow only on Mainnet (ChainID 1)",
"issuer": [
{
"type": "*",
"id": "*"
}
],
"action": "allow",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "chainId",
"operator": "eq",
"value": 1
}
]
}
]
}
Restrict to ETH and specific ERC20 tokens
This policy restricts Alice to only transacting with ETH or specific ERC20 tokens (e.g., USDC, USDT). She cannot interact with other contracts or tokens.
{
"version": "1.0",
"description": "Alice restricted to ETH and specific ERC20 tokens",
"rules": [
{
"description": "Allow ETH transfers and interaction with specific ERC20s",
"issuer": [
{ "type": "UserId", "id": "alice" }
],
"action": "allow",
"logic": "or",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "gte",
"value": "0"
},
{
"transaction_type": "erc20",
"transaction_attr": "receiver",
"operator": "in",
"value": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"]
}
]
}
]
}
Use abi prefix to avoid collision with built-in transaction attribute
When a smart contract function argument has the same name as a built-in transaction attribute (e.g., value, nonce, gasPrice), use the abi: prefix to reference the function argument.
In this example, the function updateValue(uint256 value) has an argument named value. To restrict this argument, we use abi_value.
{
"version": "1.0",
"description": "Disambiguate 'value' argument",
"rules": [
{
"description": "Allow updateValue if arg 'value' <= 100",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "erc20",
"transaction_attr": "abi:value",
"operator": "lte",
"value": 100,
"abi": [
{
"name": "updateValue",
"type": "function",
"inputs": [
{
"name": "value",
"type": "uint256"
}
]
}
]
}
]
}
]
}
Avoid adding conditions that may override other conditions
Below is the policy that has second condition (transfer max 5 ETH) override first condition (maximum 1)
{
"version": "1.0",
"description": "Conflicting rules example",
"rules": [
{
"description": "Allow transfer up to 1 ETH",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"chain_type": "ethereum",
"logic": "or",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "1000000000000000000"
},
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "5000000000000000000"
}
]
}
]
}