Skip to main content

Anti Patterns

This section provides examples of common mistakes that will lead to unintended behavior and must be strictly avoided.

Avoid adding conflicting allow and deny rules

Ethereum

Below is an example policy where the first rule denies transfers above 1 ETH, while the second rule allows transfers up to 5 ETH.

  • A transaction with a transfer amount between 1 ETH and 5 ETH matches both rules.
  • Deny rule will implicitly override allow rule due to higher precedence.
{
"version": "1.0",
"description": "Conflicting allow and deny rules example",
"rules": [
{
"description": "Deny transfer above 1 ETH",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "deny",
"chain_type": "ethereum",
"logic": "or",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "gt",
"value": "1000000000000000000"
}
]
},
{
"description": "Allow transfer up to 5 ETH",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"chain_type": "ethereum",
"logic": "or",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "5000000000000000000"
}
]
}
]
}

Solana

Below is an example policy where the first rule denies USDC transfers above 100, while the second rule allows USDC transfers up to 500.

  • A transaction with a transfer amount between 100 and 500 matches both rules.
  • Deny rule will implicitly override allow rule due to higher precedence.
{
"version": "1.0",
"description": "Conflicting allow and deny rules example (Solana SPL transfer)",
"rules": [
{
"description": "Deny USDC transfer above 100",
"issuer": [{ "type": "*", "id": "*" }],
"action": "deny",
"chain_type": "solana",
"logic": "or",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "gt",
"value": 100
}
]
}
]
},
{
"description": "Allow USDC transfer up to 500",
"issuer": [{ "type": "*", "id": "*" }],
"action": "allow",
"chain_type": "solana",
"logic": "or",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 500
}
]
}
]
}
]
}

Avoid adding rules that may override other rules

Ethereum

Below is an example policy where the second rule ("maximum 5 ETH") overrides the first rule ("maximum 1 ETH").

  • A transaction with a transfer amount greater than 1 ETH is rejected by the first rule, but still allowed by the second rule, so the overall policy evaluation passes.
{
"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"
}
]
},
{
"description": "Allow transfer up to 5 ETH",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"chain_type": "ethereum",
"logic": "or",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "5000000000000000000"
}
]
}
]
}

Solana

Below is an example policy where the second rule ("maximum 500 USDC") overrides the first rule ("maximum 100 USDC").

  • A transaction with a transfer amount greater than 100 USDC is rejected by the first rule, but still allowed by the second rule, so the overall policy evaluation passes.
{
"version": "1.0",
"description": "Conflicting rules example (Solana SPL transfer)",
"rules": [
{
"description": "Allow USDC transfer <= 100",
"issuer": [{ "type": "*", "id": "*" }],
"action": "allow",
"chain_type": "solana",
"logic": "or",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 100
}
]
}
]
},
{
"description": "Allow USDC transfer <= 500",
"issuer": [{ "type": "*", "id": "*" }],
"action": "allow",
"chain_type": "solana",
"logic": "or",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 500
}
]
}
]
}
]
}

Avoid adding wildcard issuer rules that may override specific issuer rules

Policies should not mix a broad wildcard issuer rule with a narrower issuer-specific rule when both can match the same transaction shape.

Ethereum

Below is an example policy where a broad wildcard issuer rule ("any issuer up to 5 ETH") overrides a narrower issuer-specific rule ("alice up to 1 ETH").

  • Any transaction from alice up to 5 ETH is still allowed by the wildcard rule.
  • The issuer-specific limit becomes ineffective.
{
"version": "1.0",
"description": "Wildcard issuer overrides specific issuer example",
"rules": [
{
"description": "Allow any issuer to transfer up to 5 ETH",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"chain_type": "ethereum",
"logic": "or",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "5000000000000000000"
}
]
},
{
"description": "Allow alice to transfer up to 1 ETH",
"issuer": [
{ "type": "user", "id": "alice" }
],
"action": "allow",
"chain_type": "ethereum",
"logic": "or",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "1000000000000000000"
}
]
}
]
}

Solana

Below is an example policy where a broad wildcard issuer rule ("any issuer up to 500 USDC") overrides a narrower issuer-specific rule ("alice up to 100 USDC").

  • Any USDC transfer from alice up to 500 is still allowed by the wildcard rule.
  • The issuer-specific limit becomes ineffective.
{
"version": "1.0",
"description": "Wildcard issuer overrides specific issuer example (Solana SPL transfer)",
"rules": [
{
"description": "Allow any issuer to transfer up to 500 USDC",
"issuer": [{ "type": "*", "id": "*" }],
"action": "allow",
"chain_type": "solana",
"logic": "or",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 500
}
]
}
]
},
{
"description": "Allow alice to transfer up to 100 USDC",
"issuer": [{ "type": "user", "id": "alice" }],
"action": "allow",
"chain_type": "solana",
"logic": "or",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 100
}
]
}
]
}
]
}

Avoid adding conditions that may override other conditions

Ethereum

Below is an example policy where the first condition ("maximum 1 ETH") effectively overrides the second condition ("maximum 5 ETH").

  • Any transaction with a transfer amount greater than 1 ETH will always be rejected by this policy.
  • This behavior also applies to ConditionGroup.
{
"version": "1.0",
"description": "Conflicting conditions in same rule example",
"rules": [
{
"description": "Allow transfer up to 1 ETH",
"issuer": [
{ "type": "*", "id": "*" }
],
"action": "allow",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "1000000000000000000"
},
{
"transaction_type": "nativeTransfer",
"transaction_attr": "nativeValue",
"operator": "lte",
"value": "5000000000000000000"
}
]
}
]
}

Solana

Below is an example policy where the first condition ("maximum 100 USDC") effectively overrides the second condition ("maximum 500 USDC").

  • Any transaction with a transfer amount greater than 100 USDC will always be rejected by this policy.
  • This behavior also applies to ConditionGroup.
{
"version": "1.0",
"description": "Conflicting conditions in same rule example (Solana SPL transfer)",
"rules": [
{
"description": "Allow USDC transfer up to 100 (but also includes a conflicting 500 limit)",
"issuer": [{ "type": "*", "id": "*" }],
"action": "allow",
"chain_type": "solana",
"conditions": [
{
"logic": "and",
"group": [
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTokenMint",
"operator": "eq",
"value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 100
},
{
"transaction_type": "solanaTransaction",
"transaction_attr": "splTransferAmount",
"operator": "lte",
"value": 500
}
]
}
]
}
]
}