Cookbook
A working JSON example for every condition type the TACo SDK supports, plus several real-world combinations. Copy, paste, modify.
All addresses below are placeholders. Substitute your own. All chain IDs are real (Ethereum=1, Polygon=137, Base=8453, Arbitrum=42161).
Pair this page with the schema reference and the validator script. Together they are everything an LLM needs to author conditions for you.
Editor tip: add
"$schema": "https://raw.githubusercontent.com/nucypher/taco-web/signing-epic/packages/taco/schema-docs/condition-schema.json"to the top of anyconditions.jsonand your editor will validate every example below in-place. See Building Conditions with an LLM → JSON Schema integration.
Table of contents
Single conditions
SigningObjectAttributeCondition — UserOperation field check (TACo Action Control only)
SigningObjectAbiAttributeCondition — UserOperation calldata check (TACo Action Control only)
Logical / composed conditions
For a worked end-to-end example that combines many features at once, see the Discord tipping bot deep-dive.
1. TimeCondition — after a given time
TimeCondition — after a given timeDecryption is allowed only after the latest block on Polygon has a timestamp greater than 1735689600 (2025-01-01 UTC).
2. RpcCondition — minimum ETH balance
RpcCondition — minimum ETH balanceAllow if the requester holds at least 0.1 ETH on Ethereum mainnet.
:userAddress is automatically replaced with the requester's wallet address. The value 100000000000000000 is 0.1 ETH in wei.
3. ContractCondition — ERC-20 balance (standard shorthand)
ContractCondition — ERC-20 balance (standard shorthand)Require at least 1000 USDC (6 decimals) on Base.
When standardContractType is set to "ERC20" or "ERC721", the SDK uses the canonical ABI — you do not need to supply functionAbi.
4. ContractCondition — ERC-721 ownership
ContractCondition — ERC-721 ownershipHold at least one NFT from the specified collection on Polygon.
5. ContractCondition — custom view function
ContractCondition — custom view functionCall any view or pure function on any contract by supplying a functionAbi. Here we check that the user is a member of a DAO.
6. ContractCondition — allowlist mapping lookup
ContractCondition — allowlist mapping lookupA contract exposes mapping(address => uint8) public tier;. Allow only users in tier 2 or higher.
7. JsonApiCondition — public weather API
JsonApiCondition — public weather APIAllow if today's temperature in London is below 10°C.
8. JsonApiCondition — authenticated API with Bearer token
JsonApiCondition — authenticated API with Bearer tokenThe decrypter supplies an API token at decryption time via :apiToken.
authorizationType may be "Bearer", "Basic", or "X-API-Key".
9. JsonRpcCondition — arbitrary JSON-RPC
JsonRpcCondition — arbitrary JSON-RPCCall any JSON-RPC service. Here we hit a Solana RPC and require a non-zero SOL balance for a specific, hard-coded Solana account. Hard-coding the account address keeps the access policy fixed at encryption time, which is safer than letting the requester name an arbitrary account via a context variable.
If your access policy genuinely depends on the requester's Solana account, you would need to receive that value through an authenticated channel (e.g. a JWT claim validated by a sibling JwtCondition) rather than simply letting the requester supply it as a context variable.
10. JsonCondition — querying a context payload
JsonCondition — querying a context payloadUnlike JsonApiCondition (which fetches), JsonCondition evaluates JSON that the decrypter has already supplied. Useful for off-chain attestations.
11. JwtCondition — verify a JWT
JwtCondition — verify a JWTValidate a JWT signed by your IDP. The token is supplied at decryption time via the default :jwtToken variable.
expectedIssuer is optional but recommended.
:jwtToken is the default context-variable name. You can use any name you like by setting "jwtToken": ":myCustomToken" — this is useful when a single condition references more than one JWT (e.g. two sibling JwtConditions validating different issuers), since each needs to receive its own value.
12. EcdsaCondition — verify an ECDSA signature
EcdsaCondition — verify an ECDSA signatureVerify that a message was signed by a known public key. This is the same pattern the Discord tipping bot uses to prove a Discord interaction is genuine.
The "message" value here is a concatenation of two context variables, :timestamp and :discordPayload. At decryption time the SDK substitutes each :name token in sequence, so the string ":timestamp:discordPayload" becomes <timestamp_value><payload_value> — which is what the signer signed.
:message and :signature are the default context-variable names; like :jwtToken, they can be renamed ("message": ":myMessage", "signature": ":mySig") — useful when a single condition verifies multiple distinct signatures.
Supported curves: SECP256k1, NIST256p, NIST384p, NIST521p, Ed25519, BRAINPOOLP256r1.
13. SigningObjectAttributeCondition — UserOperation field check
SigningObjectAttributeCondition — UserOperation field checkUsed in TACo Action Control. Validate that an attribute on the object being signed (e.g. an ERC-4337 UserOperation) matches an expected value.
14. SigningObjectAbiAttributeCondition — validate calldata
SigningObjectAbiAttributeCondition — validate calldataUsed in TACo Action Control. Decode an attribute (typically call_data) using ABI definitions and assert constraints on the decoded parameters. Here: only allow transfer(recipient, amount) to a specific address.
For nested calldata validation (e.g. an ERC-4337 execute() that wraps a transfer()), see the Discord tipping bot deep-dive.
15. ContextVariableCondition — assert a custom variable
ContextVariableCondition — assert a custom variableApply a return-value test directly to a context variable. Most often used inside a SequentialCondition to validate an intermediate result.
16. CompoundCondition — AND, OR, NOT
CompoundCondition — AND, OR, NOTCombine up to 5 sub-conditions. Maximum nesting depth is 4. The nesting limit is counted across all MultiConditions — CompoundCondition, IfThenElseCondition, and SequentialCondition — not just compounds. A compound that contains an if-then-else that contains a sequential counts as three levels.
"operator": "or" and "operator": "not" work the same way (not takes a single operand).
17. SequentialCondition — derive then check
SequentialCondition — derive then checkTwo to twenty steps, each binding a varName that subsequent steps can reference. Use operations on a step to transform the obtained value before storing it.
18. IfThenElseCondition — branching
IfThenElseCondition — branchingifCondition and thenCondition must both be full conditions. Only elseCondition accepts a boolean shortcut (true means "admit", false means "deny").
Before reaching for IfThenElseCondition, check whether the rule is really a CompoundCondition:
if A then true else BisOR(A, B)if A then false else BisAND(NOT(A), B)
IfThenElseCondition earns its keep when thenCondition and elseCondition are themselves meaningful, distinct checks — i.e. holders of the branch-condition's subject face one requirement, and non-holders face another. The example below applies different rules to VIP-pass holders and the general public: holders only need the access window to be open, while everyone else must hold ≥10 USDC.
19. Pattern: NFT-or-allowlist gate
Hold the NFT or be on a hard-coded allowlist. The allowlist branch uses a ContextVariableCondition to check that :userAddress is one of the allowed values — no RPC call is needed for a pure allowlist check.
20. Pattern: time-windowed paid access
Allow decryption between two timestamps and require an active subscription on-chain.
21. Pattern: storm-condition open access
A backup safety plan for an outdoor event. If it is raining at the venue and the wind is high enough to be unsafe, anyone can decrypt the umbrella-pickup instructions; otherwise only umbrella-NFT holders can. Each branch is a meaningful check — there is no artificial thenCondition.
22. Pattern: balance fetched, normalised, then asserted
A SequentialCondition that fetches a wei balance, divides it down to whole ETH using operations, and then asserts a minimum.
Available operations
operationsOperations can be applied to obtained values inside returnValueTest.operations or ConditionVariable.operations. Up to five per array.
+=, -=, *=, /=, %=
Arithmetic with the supplied value
toTokenBaseUnits
Multiply by 10^value (decimals → base units)
weiToEth, ethToWei
Native unit conversions
int, float, bool, str
Type coercion
round, floor, ceil, abs
Numeric rounding
len, min, max, sum, avg
Aggregations on arrays
index
Pick an array element
keccak
Hash a string
create2
Compute a CREATE2 address locally given deployerAddress + bytecodeHash
For the full enum see VariableOperation in the schema reference.
Need something this cookbook does not cover? Read the schema reference, then ask an LLM with the building-with-llms workflow.
Last updated