Blockchain · How-to
How to Write Smart Signatures on Algorand With TEAL (2026)
Algorand smart signatures are stateless TEAL programs that can approve transactions on behalf of an account. This guide explains how they work, how to write and compile one, and how to test and review it before anyone relies on it with real funds.
By the DappsAtlas editorial team · Updated

What a smart signature is on Algorand
A smart signature on Algorand, also called a logic signature or LogicSig, is a small TEAL program that decides whether a transaction is allowed. When a transaction carries a logic signature, the network runs the program. If the program finishes with a non-zero value on top of the stack, the transaction is approved for the account it is authorized to act for. If it finishes with zero or fails, the transaction is rejected.
This is different from an Algorand smart contract, which is a stateful application that is called through application transactions and can store data in global or local state. A smart signature has no state of its own. It can read the transaction it is attached to, the group it belongs to, some global values such as the current round, and its arguments. It cannot write anything to the ledger.
Because of that, smart signatures suit rules that can be checked from the transaction alone. Examples include a payment that may only go to one fixed receiver, an escrow that releases funds after a round number, or an account that can only send to a list of approved addresses. If your rule needs memory of past actions, such as a one-time claim, a stateful application is usually the better fit.
Before you write any code, describe the rule in plain words and list every transaction type it should allow and every type it should refuse. This list will become your test plan later.
Know the limits of a stateless program
Stateless design is the main constraint. Because a logic signature cannot store anything, it cannot count how many times it has been used, remember a previous payment, or track a balance over time. Any program that approves a payment to a fixed address will approve every matching payment that anyone submits, until the account it protects runs out of funds or the program stops being valid.
For that reason, state the limits you need inside the program itself. Useful limits include a maximum amount per transaction, a maximum fee, a fixed receiver, and an expiry based on the last valid round. A round-based limit is especially useful for time-bound rules, because it does not depend on wall-clock time.
You also need to block transaction fields that let an account be taken over or emptied in unexpected ways. The two fields to check in almost every program are RekeyTo and CloseRemainderTo. Rekeying changes which key controls an account, and a close-to field can send the entire remaining balance to another address. If your program does not explicitly require both fields to be the zero address, a valid transaction may use them.
The program size and the execution cost of each run are also limited. Keep the logic short, avoid unnecessary loops, and check the current limits in the Algorand developer documentation before you build anything large.
Contract account or delegated signature
There are two common ways to use a smart signature, and they produce different kinds of account control.
In a contract account, the address of the account is derived from the compiled program itself. Nobody holds a private key for that address. Funds sent to it can only move when a transaction carrying the matching logic signature is accepted by the program. This is the typical choice for escrow, where the rule is the only authority over the funds.
In a delegated signature, a normal account owner signs the program bytes with its own key. The signed result authorizes that specific program to sign transactions on behalf of the owner's account. The owner still controls the account and can change its arrangements, while the delegated program can only approve the specific actions its logic allows. This is useful when an account holder wants a narrow permission, such as letting a service send small recurring payments.
Choose the model before you write the program, because the signing step and the risk profile differ. A contract account has no key to rotate if something goes wrong. A delegated signature depends on the owner's key staying safe. In both cases, a bug in the TEAL code can allow more than you intended, so the review steps later in this guide matter in either model.
Set up a local environment
You need a way to compile, sign, and test programs. The most direct route is the Algorand command-line tools, which include the goal command and its clerk subcommands. The official developer documentation describes how to install them for your operating system and how to run a local development network.
AlgoKit is the recommended toolkit for many developers. It helps create project templates, run a local network, and work with Algorand Python or Algorand Typescript projects that compile to TEAL. If you only need to write and compile TEAL, you can use the command-line tools alone.
A local network is important. It lets you create test accounts, fund them with test currency, and submit transactions without spending real assets. Make sure the local network is running the same protocol version your production code targets. Version differences can change which opcodes are available and how fees and limits are calculated.
Keep the workspace organized. Store the TEAL source, the compiled output, the test scripts, and the notes about which signer and receiver addresses you used in one project folder. Avoid keeping mnemonic phrases or private keys in the same folder as source files, and never commit them to a shared repository.
Write a first TEAL program
A TEAL program begins with a version directive, which tells the assembler which opcodes are allowed. Use the latest version your toolchain supports, and check the documentation for the opcodes you need. The example below is a deliberately narrow rule. It approves a payment only when the amount is at most one Algo, the fee is small, the receiver is one fixed address, and neither rekeying nor close-to is set.
#pragma version 8
txn TypeEnum
int pay
==
txn Fee
int 2000
<=
&&
txn RekeyTo
global ZeroAddress
==
&&
txn CloseRemainderTo
global ZeroAddress
==
&&
txn Receiver
addr YOUR_RECEIVER_ADDRESS
==
&&
txn Amount
int 1000000
<=
&&
Replace YOUR_RECEIVER_ADDRESS with a real, valid address before compiling. Amounts and fees are in microAlgos, so 1000000 equals one Algo. The fee cap is an example; choose a value that matches the transactions you expect, keeping in mind that fees on Algorand are generally small.
Notice the pattern. Each check leaves a true or false value on the stack, and the && operator combines them with the previous result. A program that forgets a check is approved more widely than intended, so write one line per rule and compare the list to your plan from the first section.
If you need to accept several receivers, do not write a long chain of equality checks by hand without a plan. Consider whether a different design, such as a single approved receiver per program, better matches the rule and is easier to audit.
Compile, fund, and sign the program
Compile the source file with the goal clerk compile command. The command produces compiled program bytes and prints the address that corresponds to that program. Check the help output for your installed version, because the flags for the output file and for signing can differ between releases.
Record the program address and the compiled file together. The address is what you fund if you are using a contract account. Funding the wrong address will lock funds in a place no transaction can release, so verify the address against the compiled output before sending anything to it, even on a local network where mistakes are cheap.
If you are using a delegated signature, the compile step includes signing with the owner's account. In the goal clerk compile help, look for the flags that name the signing account and request a signature. Run the command on a test account first. The signed output is what you will attach to transactions, so keep it in a file that is clearly named and separate from the source.
Keep the source, the compiled output, and any signed file under version control, but treat signed artifacts that represent authority as sensitive. Anyone who holds a delegated signature file can use the permission it grants until the owner stops relying on it.
Attach the logic signature to a transaction
To use a logic signature, you build the transaction you want to send, then attach the logic signature to it before submitting. You can do this with the goal command line where supported, or with an SDK such as algosdk, which includes a LogicSigAccount class for this purpose. The SDK route gives you more control over the transaction fields and makes tests easier to repeat.
For a contract account, the transaction sender is the program address. The attached logic signature is the compiled program, plus any arguments your rule expects. Arguments are byte strings that the transaction carries, and they are visible on chain once the transaction is submitted. Do not place secrets in arguments.
For a delegated signature, the transaction sender is the owner account, and the attached signature is the signed delegation. The network checks that the program was authorized for that account.
Whatever route you use, build the transaction with explicit values for the fee, the first and last valid rounds, and the note field if your application uses one. Setting the last valid round to a short window limits how long a signed transaction can be submitted. Test the exact transaction you plan to submit, not a simpler stand-in.
Test with dry runs and a local network
Testing should cover both the approved paths and the refused ones. Write a list of cases from your rule, such as a correct payment, a payment over the amount cap, a payment to another receiver, a payment with a rekey field set, a payment with a close-to field set, and a payment after the last valid round. Run each case and confirm the outcome matches the rule.
The goal clerk dryrun command evaluates a program against a transaction without submitting it to the network. This is useful for quick checks and for seeing why a program fails. Read the trace output for the failing cases to confirm that the failure comes from the rule you intended.
Run the full set on a local network after the dry runs. A local network also tests submission, fees, and the way your transactions are grouped, which dry runs may not fully reproduce. Repeat the tests after any change to the TEAL code, the compiler version, or the protocol version your tools target.
Add a test that tries to misuse the program, not only one that uses it correctly. Try to send a valid-looking payment with a different sender, try to reuse a transaction after its window has passed, and try to add extra transactions to a group. The aim is to find out what the program actually allows, rather than what you hoped it would allow.
Review the program for security before mainnet
Before real value depends on a program, review it with the same care you would give any code that controls funds. Start by reading the compiled output, not only the source, and confirm that the logic matches your plan line by line. Compilers and version choices can change details, so the bytecode is the final check.
Check the rekey and close-to fields in every program that controls an account. Missing these checks is one of the most common ways a program can approve more than its author intended. Also check the sender, receiver, amount, fee, and round window. If any of these is left open, the program may approve transactions that were never part of the rule.
Do not hardcode private keys, mnemonic phrases, or other secrets in TEAL source, scripts, or arguments. Keep signing keys in a dedicated wallet or secure storage, and separate the key used for testing from the key used for production.
Assume the program and its arguments become public after use. Anyone can read the bytecode on chain and reproduce the logic. Design the program so that knowing its rules gives an attacker nothing useful beyond what the rules already permit.
For programs that control significant value, arrange an independent review, and keep a written record of the version you approved. If you find a flaw after deployment, plan for how you will move or retire the funds, since a stateless contract account may not be easy to update.
Frequently asked questions
What is the difference between a smart signature and a smart contract on Algorand?
A smart contract on Algorand is a stateful application that stores data in global or local state and is called through application transactions. A smart signature, also called a logic signature, is a stateless program attached to a transaction. It can only approve or reject, and it cannot write state. Smart signatures are typically used for escrow-style rules, such as limiting who a payment can go to.
Do I have to write TEAL by hand, or can I use Python or TypeScript?
TEAL is the assembly-like language that the Algorand Virtual Machine executes. Algorand Python and Algorand Typescript, both supported through AlgoKit, can compile to TEAL. Writing TEAL directly gives you the most control over the bytecode and its cost, while higher-level languages can make larger programs easier to maintain. Either way, review the compiled TEAL, because that is what runs on chain.
Can a smart signature be used to protect real funds?
Yes, but only with careful design. Stateless programs cannot track whether something has already happened, so a rule like 'pay this address once' needs another mechanism, such as off-chain coordination or a stateful application. Without rekey and close-to checks, a program can also be misused. Limit what the program can approve, add expiry rounds, and test every path before any mainnet use.
Where can I check the current size and cost limits for a TEAL program?
Read the current limits in the Algorand developer documentation before writing, since program size and execution budgets are defined there and can change between protocol versions. Plan your logic to fit comfortably below those limits, and keep the program as short as the rule requires.
What should I check before moving a smart signature to mainnet?
Start with a local network, run dry-run evaluations against sample transactions, and read the compiled output. Check the program address against what your application expects. Get an independent review for anything that controls significant value, and assume that the program code and its arguments are public once it is used.
Mentioned in this guide
dApps in this guide
Envio is a blockchain indexing and data platform offering HyperIndex APIs and fast HyperSync raw data access for developers across 81+ chains.
DefiLlama is a data site that aggregates total value locked, trading volume and fees for DeFi protocols across many chains.
Keep reading
Related guides
Blockchain · How-to
Intro to Algorand PyTeal Smart Signatures: 2026 Guide
Algorand smart signatures are small, stateless programs that approve transactions, and PyTeal lets you write them in Python. This guide walks through the concepts, a starter program, compilation, testing, deployment and the security checks to run before mainnet use.
Blockchain · Explainer
Casper Network Odra Smart Contracts: A Developer's Guide 2026
Casper Network is a proof-of-stake Layer-1 chain that runs Rust-based smart contracts compiled to WebAssembly. This guide explains how Casper contracts work and how the Odra framework helps you build, test, deploy and upgrade them.
Blockchain · Explainer
Filecoin FVM Explained: Provable Storage Meets Smart Contracts
Filecoin's Virtual Machine adds programmable smart contracts to a network where storage is independently verified. This guide explains how the FVM works, how provable storage fits in, and what to check before building on or using it.
Blockchain · Explainer
Oasis Sapphire Explained: Confidential EVM Smart Contracts in 2026
Oasis Sapphire is an EVM-compatible chain that runs smart contracts inside trusted execution environments so that contract state and inputs can stay confidential. This guide explains how it works, what it protects, where it falls short, and how to evaluate it in 2026.
Blockchain · Explainer
Consensus-Agnostic Sidechains with Zendoo by Horizen: A 2026 Guide
Zendoo is Horizen's sidechain protocol, and its consensus-agnostic design lets each sidechain pick its own consensus while the mainchain verifies it with zero-knowledge proofs. This guide explains how that works, what it changes for developers and users, and what to check before relying on it.
Blockchain · Explainer
Why People Are Bullish on Ethereum in 2026: Key Arguments
The bullish case for Ethereum rests on its developer base, DeFi and stablecoin activity, staking economics, and layer-2 scaling, with institutional access adding to demand. This guide sets out each argument, the strongest counterpoints, and where to check the current data yourself.
Blockchain · Explainer
zkBTC Explained: How a Bitcoin EVM Layer 2 Scales with ZK Proofs
zkBTC belongs to a newer group of projects that try to run Ethereum-style smart contracts on top of Bitcoin, using zero-knowledge proofs to scale. This guide explains how these networks process transactions, move BTC in and out, and where the risks sit, so you can check zkBTC or a similar network against the same criteria.
Blockchain · Explainer
Why Ontology Is Different: Meanings, Uses and Context in 2026
Ontology means different things in philosophy, data science and crypto. This guide explains the data sense in detail, sets it apart from taxonomies and schemas, and separates it from the Ontology blockchain so readers know which meaning they are dealing with.