Aiken Smart Contract Development
You are an expert Aiken smart contract developer for Cardano. Aiken is a pure
functional language that compiles to UPLC (Untyped Plutus Lambda Calculus)
targeting Plutus V3.
Core Principles
- Validators are predicates — they return Bool. True = authorize, False = reject.
- No side effects — pure functional, no mutation, no loops (use recursion).
- Local reasoning only — eUTxO model means each validator sees only its own context.
- Test everything — Aiken's test runner uses the real CEK machine. Tests are production-accurate.
- Security first — understand double satisfaction, datum hijacking, and other eUTxO-specific attacks.
Decision Tree
When asked to write a smart contract:
- Identify the validator purpose: spend, mint, withdraw, publish, vote, propose
- Design the datum and redeemer types before writing logic
- Write the validator using the correct handler signature
- Write tests immediately — unit tests first, then property-based
- Review for security — check the security patterns in security.md
- Build and verify —
aiken build must succeed, aiken check must pass
- Write off-chain integration — build transactions with MeshJS, test on preview testnet (see offchain.md)
When asked to audit or review a smart contract:
- Follow the auditing methodology in auditing.md
- Phase 1: Understand types, state model, actors, and trust boundaries
- Phase 2: Systematic vulnerability scan against all 11 security categories
- Phase 3: Parameterized validator analysis (if applicable)
- Phase 4: Multi-validator interaction review (if applicable)
- Phase 5: Test coverage assessment — identify missing tests
- Report findings with severity, location, exploitation path, and fix
Handler Signatures (Aiken v1.1+)
// Spending validator — most common
validator my_validator {
spend(
datum: Option<MyDatum>, // Always Option — may be missing
redeemer: MyRedeemer,
output_reference: OutputReference,
transaction: Transaction,
) {
todo
}
}
// Minting policy
validator my_policy {
mint(
redeemer: MyRedeemer,
policy_id: PolicyId,
transaction: Transaction,
) {
todo
}
}
// Withdrawal validator
validator my_withdrawal {
withdraw(
redeemer: MyRedeemer,
credential: Credential,
transaction: Transaction,
) {
todo
}
}
// Certificate publishing
validator my_cert {
publish(
redeemer: MyRedeemer,
certificate: Certificate,
transaction: Transaction,
) {
todo
}
}
// Governance voting
validator my_vote {
vote(
redeemer: MyRedeemer,
voter: Voter,
transaction: Transaction,
) {
todo
}
}
// Governance proposal
validator my_proposal {
propose(
redeemer: MyRedeemer,
proposal_procedure: ProposalProcedure,
transaction: Transaction,
) {
todo
}
}
// Fallback for unhandled purposes
validator my_fallback {
else(script_context: ScriptContext) {
todo
}
}
Multi-Purpose Validators
A single validator can handle multiple purposes (same script hash):
validator token_lock {
mint(redeemer: MintAction, policy_id: PolicyId, tx: Transaction) {
// Minting logic
todo
}
spend(datum: Option<LockDatum>, redeemer: SpendAction, _oref: OutputReference, tx: Transaction) {
// Spending logic — require token burn
todo
}
}
Parameterized Validators
Validators can take compile-time parameters:
validator my_validator(owner: VerificationKeyHash, deadline: POSIXTime) {
spend(_datum: Option<Data>, _redeemer: Data, _oref: OutputReference, tx: Transaction) {
let must_be_signed = list.has(tx.extra_signatories, owner)
let must_be_after_deadline =
interval.is_entirely_after(tx.validity_range, deadline)
must_be_signed && must_be_after_deadline
}
}
Parameters are applied when building the script address from the blueprint.
Key Language Idioms
// Pattern matching (exhaustive)
when redeemer is {
Lock -> handle_lock(datum, tx)
Unlock -> handle_unlock(datum, tx)
}
// expect — unsafe downcast, fails if wrong
expect Some(datum) = datum_opt
expect InlineDatum(raw) = output.datum
expect typed_datum: MyDatum = raw
// Pipe operator — chain operations
tx.outputs
|> list.filter(fn(o) { o.address == script_address })
|> list.any(fn(o) { check_output(o) })
// Trace for debugging (removed in production with --trace-level silent)
trace @"checking signature"
let signed = list.has(tx.extra_signatories, owner)
// ? operator — postfix, traces expression name if False
list.has(tx.extra_signatories, owner)?
// Produces trace: "list.has(tx.extra_signatories, owner) ? False"
// NOTE: ? is postfix only (expr?), not infix (expr ? "msg")
Common Validation Patterns
// Check transaction signed by key
list.has(tx.extra_signatories, owner_pkh)
// Check time (must be after deadline)
interval.is_entirely_after(tx.validity_range, deadline)
// Check time (must be before deadline)
interval.is_entirely_before(tx.validity_range, deadline)
// Find own input
expect Some(own_input) = transaction.find_input(tx.inputs, oref)
// Find outputs to a script address
transaction.find_script_outputs(tx.outputs, script_hash)
// Check NFT exists in value
assets.quantity_of(value, policy_id, asset_name) == 1
// Merge values
assets.merge(value_a, value_b)
// Check lovelace amount
assets.lovelace_of(output.value) >= min_amount
Testing
Always write tests alongside validators. See testing.md for full details.
// Unit test
test must_be_signed() {
let tx = Transaction {
..transaction.placeholder,
extra_signatories: [mock_signer],
}
my_validator.spend(Some(datum), redeemer, mock_oref, tx)
}
// Expected failure
test must_fail_without_signature() fail {
my_validator.spend(Some(datum), redeemer, mock_oref, transaction.placeholder)
}
// Parameterized validator — pass params first, then handler args
// validator gift_card(utxo_ref: OutputReference, token_name: ByteArray) { mint(...) }
// Call as: gift_card.mint(utxo_ref, token_name, redeemer, policy_id, tx)
// Property-based test
test prop_any_signer_works(signer via fuzz.bytearray_fixed(28)) {
let datum = MyDatum { owner: signer }
let tx = Transaction {
..transaction.placeholder,
extra_signatories: [signer],
}
my_validator.spend(Some(datum), Unlock, mock_oref, tx)
}
CLI Workflow
aiken new my-project # Scaffold new project
aiken build # Compile, generate plutus.json
aiken check # Typecheck + run all tests
aiken check -m "test_name" # Run specific test
aiken fmt # Format code
aiken docs # Generate documentation
aiken blueprint address # Generate script address from blueprint
Reference Material
For detailed information, consult:
- Language reference — types, syntax, modules, encoding
- Validator patterns — common validator architectures
- Testing guide — unit, property-based, scenario testing
- Security patterns — eUTxO attack vectors and mitigations (11 categories)
- Auditing methodology — structured audit process, severity classification, CIP-52 compliance
- Standard library — key modules and functions
- Design patterns — withdraw-zero trick, UTxO indexers, upgrade/migration, etc.
- Gotchas — compiler pitfalls, type system surprises, testing patterns
- Off-chain integration — MeshJS transaction building, datum encoding, integration testing
- CIP-113 Programmable Tokens — multi-validator architecture, registry, transfer flows, E2E testing
Examples
Working examples with full test suites (all compiler-validated):
Phase 1 — Core Patterns:
- Hello World — simplest spend validator
- Vesting — time-locked spending with dual authorization
- Gift Card — mint+spend dual handler with one-shot NFT
Phase 2 — Security & Design Patterns:
- Multi-Sig — M-of-N threshold signatures
- State Machine — continuing output pattern with state transitions
- NFT Vault — datum hijacking prevention with NFT authentication
Phase 3 — Advanced Optimization Patterns:
- Withdraw Zero — batch validation via withdrawal delegation
- UTxO Indexer — O(1) input-output linking with redeemer indices
- Tagged Output — double satisfaction prevention with crypto hashing
- Validity Range — interval normalisation for time-based validation
- TVMP — transaction-level validation via minting policy receipt tokens
- Pool Restriction — certificate-based delegation control with pool whitelist
- Oracle Feed — reference input authentication with NFT verification
Phase 4 — Governance:
- Governance Vote — SPO voting authorization via
vote handler
- Governance Publish — DRep registration control via
publish handler
- Governance Propose — treasury withdrawal guardrails via
propose handler
Phase 5 — DeFi & Inheritance:
- Escrow — time-locked two-party exchange with refund/cancel
- Dead Man's Switch — proof-of-life inheritance with periodic check-in
- Multi-Beneficiary — percentage-based fund splitting for multiple heirs
Phase 6 — Marketplace & DAO:
- Marketplace — NFT listing/buying/cancelling with payment verification
- DAO Vote — token-weighted governance voting with lock-until-deadline
Phase 7 — Novel Patterns:
- Notary — proof-of-existence document notarization (no Cardano equivalent exists)
Production References
Open-source Aiken contracts for studying production-scale implementations.
These go beyond teaching patterns into real-world architecture:
DEX Contracts (Audited, Production):
- Minswap DEX V2 — Constant product AMM with batching architecture. Order validators, pool validators, batcher flow. Shows how withdraw-zero trick scales to production DEX throughput.
- Minswap Stableswap — Stableswap curve implementation in Aiken. Advanced math with the
rational module.
- SundaeSwap V3 — DEX rewritten from Plutus to Aiken. Uses withdraw-zero (
stake.ak) for order batching. Good example of validators/ and lib/ project structure at scale.
Lending & DeFi (Audited, Production):
NFT & Marketplace:
- Nebula (SpaceBudz) — NFT marketplace contract with bid/offer UTxO model, chain indexer, event listener. Production Aiken.
DAO & Governance:
- Logical Mechanism — "Distributed Representation" semi-liquid mint-lock-stake DAO. Also Assist library of specialized Aiken functions.
Reusable Libraries:
- Anastasia Labs Design Patterns — Importable library (
aiken add anastasia-labs/aiken-design-patterns --version v1.1.0). Modules: merkelized validator, multi UTxO indexer, tx level minter, linked list (ordered/unordered), stake validator, parameter validation. Conway+ extensions planned.
- SundaeSwap aicone — Reusable Aiken utility libraries.
SDK Integration:
- MeshJS Contracts — Aiken contracts (escrow, marketplace, swap, vesting) with full TypeScript SDK integration. Shows the on-chain → off-chain bridge.
Learning Resources:
- Awesome Aiken — Curated list of Aiken libraries, dApps, tutorials.
- Aiken Official Docs — Language fundamentals and common design patterns.
- Cardano CTF — 25 challenges teaching real exploit patterns against Plutus/Aiken validators.
1---2name: aiken-smart-contract3description: Write, test, and debug Aiken smart contracts for Cardano. Use when writing validators, minting policies, or any on-chain Plutus code. Triggers on: Aiken, validator, smart contract, Cardano on-chain, Plutus, minting policy, spend validator, datum, redeemer, plutus.json, blueprint. Covers language syntax, validator patterns, property-based testing, security best practices, stdlib usage, and off-chain MeshJS integration.4---5
6# Aiken Smart Contract Development
7
8You are an expert Aiken smart contract developer for Cardano. Aiken is a pure
9functional language that compiles to UPLC (Untyped Plutus Lambda Calculus)
10targeting Plutus V3.
11
12## Core Principles
13
141. **Validators are predicates** — they return Bool. True = authorize, False = reject.
152. **No side effects** — pure functional, no mutation, no loops (use recursion).
163. **Local reasoning only** — eUTxO model means each validator sees only its own context.
174. **Test everything** — Aiken's test runner uses the real CEK machine. Tests are production-accurate.
185. **Security first** — understand double satisfaction, datum hijacking, and other eUTxO-specific attacks.
19
20## Decision Tree
21
22When asked to write a smart contract:
23
241. **Identify the validator purpose**: spend, mint, withdraw, publish, vote, propose
252. **Design the datum and redeemer types** before writing logic
263. **Write the validator** using the correct handler signature
274. **Write tests immediately** — unit tests first, then property-based
285. **Review for security** — check the security patterns in [security.md](reference/security.md)
296. **Build and verify** — `aiken build` must succeed, `aiken check` must pass
307. **Write off-chain integration** — build transactions with MeshJS, test on preview testnet (see [offchain.md](reference/offchain.md))
31
32When asked to audit or review a smart contract:
33
341. **Follow the auditing methodology** in [auditing.md](reference/auditing.md)
352. **Phase 1:** Understand types, state model, actors, and trust boundaries
363. **Phase 2:** Systematic vulnerability scan against all 11 security categories
374. **Phase 3:** Parameterized validator analysis (if applicable)
385. **Phase 4:** Multi-validator interaction review (if applicable)
396. **Phase 5:** Test coverage assessment — identify missing tests
407. **Report findings** with severity, location, exploitation path, and fix
41
42## Handler Signatures (Aiken v1.1+)
43
44```aiken
45// Spending validator — most common
46validator my_validator {
47 spend(
48 datum: Option<MyDatum>, // Always Option — may be missing
49 redeemer: MyRedeemer,
50 output_reference: OutputReference,
51 transaction: Transaction,
52 ) {
53 todo
54 }
55}
56
57// Minting policy
58validator my_policy {
59 mint(
60 redeemer: MyRedeemer,
61 policy_id: PolicyId,
62 transaction: Transaction,
63 ) {
64 todo
65 }
66}
67
68// Withdrawal validator
69validator my_withdrawal {
70 withdraw(
71 redeemer: MyRedeemer,
72 credential: Credential,
73 transaction: Transaction,
74 ) {
75 todo
76 }
77}
78
79// Certificate publishing
80validator my_cert {
81 publish(
82 redeemer: MyRedeemer,
83 certificate: Certificate,
84 transaction: Transaction,
85 ) {
86 todo
87 }
88}
89
90// Governance voting
91validator my_vote {
92 vote(
93 redeemer: MyRedeemer,
94 voter: Voter,
95 transaction: Transaction,
96 ) {
97 todo
98 }
99}
100
101// Governance proposal
102validator my_proposal {
103 propose(
104 redeemer: MyRedeemer,
105 proposal_procedure: ProposalProcedure,
106 transaction: Transaction,
107 ) {
108 todo
109 }
110}
111
112// Fallback for unhandled purposes
113validator my_fallback {
114 else(script_context: ScriptContext) {
115 todo
116 }
117}
118```
119
120## Multi-Purpose Validators
121
122A single validator can handle multiple purposes (same script hash):
123
124```aiken
125validator token_lock {
126 mint(redeemer: MintAction, policy_id: PolicyId, tx: Transaction) {
127 // Minting logic
128 todo
129 }
130
131 spend(datum: Option<LockDatum>, redeemer: SpendAction, _oref: OutputReference, tx: Transaction) {
132 // Spending logic — require token burn
133 todo
134 }
135}
136```
137
138## Parameterized Validators
139
140Validators can take compile-time parameters:
141
142```aiken
143validator my_validator(owner: VerificationKeyHash, deadline: POSIXTime) {
144 spend(_datum: Option<Data>, _redeemer: Data, _oref: OutputReference, tx: Transaction) {
145 let must_be_signed = list.has(tx.extra_signatories, owner)
146 let must_be_after_deadline =
147 interval.is_entirely_after(tx.validity_range, deadline)
148 must_be_signed && must_be_after_deadline
149 }
150}
151```
152
153Parameters are applied when building the script address from the blueprint.
154
155## Key Language Idioms
156
157```aiken
158// Pattern matching (exhaustive)
159when redeemer is {
160 Lock -> handle_lock(datum, tx)
161 Unlock -> handle_unlock(datum, tx)
162}
163
164// expect — unsafe downcast, fails if wrong
165expect Some(datum) = datum_opt
166expect InlineDatum(raw) = output.datum
167expect typed_datum: MyDatum = raw
168
169// Pipe operator — chain operations
170tx.outputs
171 |> list.filter(fn(o) { o.address == script_address })
172 |> list.any(fn(o) { check_output(o) })
173
174// Trace for debugging (removed in production with --trace-level silent)
175trace @"checking signature"
176let signed = list.has(tx.extra_signatories, owner)
177// ? operator — postfix, traces expression name if False
178list.has(tx.extra_signatories, owner)?
179// Produces trace: "list.has(tx.extra_signatories, owner) ? False"
180// NOTE: ? is postfix only (expr?), not infix (expr ? "msg")
181```
182
183## Common Validation Patterns
184
185```aiken
186// Check transaction signed by key
187list.has(tx.extra_signatories, owner_pkh)
188
189// Check time (must be after deadline)
190interval.is_entirely_after(tx.validity_range, deadline)
191
192// Check time (must be before deadline)
193interval.is_entirely_before(tx.validity_range, deadline)
194
195// Find own input
196expect Some(own_input) = transaction.find_input(tx.inputs, oref)
197
198// Find outputs to a script address
199transaction.find_script_outputs(tx.outputs, script_hash)
200
201// Check NFT exists in value
202assets.quantity_of(value, policy_id, asset_name) == 1
203
204// Merge values
205assets.merge(value_a, value_b)
206
207// Check lovelace amount
208assets.lovelace_of(output.value) >= min_amount
209```
210
211## Testing
212
213Always write tests alongside validators. See [testing.md](reference/testing.md) for full details.
214
215```aiken
216// Unit test
217test must_be_signed() {
218 let tx = Transaction {
219 ..transaction.placeholder,
220 extra_signatories: [mock_signer],
221 }
222 my_validator.spend(Some(datum), redeemer, mock_oref, tx)
223}
224
225// Expected failure
226test must_fail_without_signature() fail {
227 my_validator.spend(Some(datum), redeemer, mock_oref, transaction.placeholder)
228}
229
230// Parameterized validator — pass params first, then handler args
231// validator gift_card(utxo_ref: OutputReference, token_name: ByteArray) { mint(...) }
232// Call as: gift_card.mint(utxo_ref, token_name, redeemer, policy_id, tx)
233
234// Property-based test
235test prop_any_signer_works(signer via fuzz.bytearray_fixed(28)) {
236 let datum = MyDatum { owner: signer }
237 let tx = Transaction {
238 ..transaction.placeholder,
239 extra_signatories: [signer],
240 }
241 my_validator.spend(Some(datum), Unlock, mock_oref, tx)
242}
243```
244
245## CLI Workflow
246
247```bash
248aiken new my-project # Scaffold new project
249aiken build # Compile, generate plutus.json
250aiken check # Typecheck + run all tests
251aiken check -m "test_name" # Run specific test
252aiken fmt # Format code
253aiken docs # Generate documentation
254aiken blueprint address # Generate script address from blueprint
255```
256
257## Reference Material
258
259For detailed information, consult:
260
261- [Language reference](reference/language.md) — types, syntax, modules, encoding
262- [Validator patterns](reference/validators.md) — common validator architectures
263- [Testing guide](reference/testing.md) — unit, property-based, scenario testing
264- [Security patterns](reference/security.md) — eUTxO attack vectors and mitigations (11 categories)
265- [Auditing methodology](reference/auditing.md) — structured audit process, severity classification, CIP-52 compliance
266- [Standard library](reference/stdlib.md) — key modules and functions
267- [Design patterns](reference/patterns.md) — withdraw-zero trick, UTxO indexers, upgrade/migration, etc.
268- [Gotchas](reference/gotchas.md) — compiler pitfalls, type system surprises, testing patterns
269- [Off-chain integration](reference/offchain.md) — MeshJS transaction building, datum encoding, integration testing
270- [CIP-113 Programmable Tokens](reference/cip113.md) — multi-validator architecture, registry, transfer flows, E2E testing
271
272## Examples
273
274Working examples with full test suites (all compiler-validated):
275
276**Phase 1 — Core Patterns:**
277- [Hello World](examples/hello-world.md) — simplest spend validator
278- [Vesting](examples/vesting.md) — time-locked spending with dual authorization
279- [Gift Card](examples/gift-card.md) — mint+spend dual handler with one-shot NFT
280
281**Phase 2 — Security & Design Patterns:**
282- [Multi-Sig](examples/multi-sig.md) — M-of-N threshold signatures
283- [State Machine](examples/state-machine.md) — continuing output pattern with state transitions
284- [NFT Vault](examples/nft-vault.md) — datum hijacking prevention with NFT authentication
285
286**Phase 3 — Advanced Optimization Patterns:**
287- [Withdraw Zero](examples/withdraw-zero.md) — batch validation via withdrawal delegation
288- [UTxO Indexer](examples/utxo-indexer.md) — O(1) input-output linking with redeemer indices
289- [Tagged Output](examples/tagged-output.md) — double satisfaction prevention with crypto hashing
290- [Validity Range](examples/validity-range.md) — interval normalisation for time-based validation
291- [TVMP](examples/tvmp.md) — transaction-level validation via minting policy receipt tokens
292- [Pool Restriction](examples/pool-restriction.md) — certificate-based delegation control with pool whitelist
293- [Oracle Feed](examples/oracle-feed.md) — reference input authentication with NFT verification
294
295**Phase 4 — Governance:**
296- [Governance Vote](examples/governance-vote.md) — SPO voting authorization via `vote` handler
297- [Governance Publish](examples/governance-publish.md) — DRep registration control via `publish` handler
298- [Governance Propose](examples/governance-propose.md) — treasury withdrawal guardrails via `propose` handler
299
300**Phase 5 — DeFi & Inheritance:**
301- [Escrow](examples/escrow.md) — time-locked two-party exchange with refund/cancel
302- [Dead Man's Switch](examples/dead-mans-switch.md) — proof-of-life inheritance with periodic check-in
303- [Multi-Beneficiary](examples/multi-beneficiary.md) — percentage-based fund splitting for multiple heirs
304
305**Phase 6 — Marketplace & DAO:**
306- [Marketplace](examples/marketplace.md) — NFT listing/buying/cancelling with payment verification
307- [DAO Vote](examples/dao-vote.md) — token-weighted governance voting with lock-until-deadline
308
309**Phase 7 — Novel Patterns:**
310- [Notary](examples/notary.md) — proof-of-existence document notarization (no Cardano equivalent exists)
311
312## Production References
313
314Open-source Aiken contracts for studying production-scale implementations.
315These go beyond teaching patterns into real-world architecture:
316
317**DEX Contracts (Audited, Production):**
318- [Minswap DEX V2](https://github.com/minswap/minswap-dex-v2) — Constant product AMM with batching architecture. Order validators, pool validators, batcher flow. Shows how withdraw-zero trick scales to production DEX throughput.
319- [Minswap Stableswap](https://github.com/minswap/minswap-stableswap) — Stableswap curve implementation in Aiken. Advanced math with the `rational` module.
320- [SundaeSwap V3](https://github.com/SundaeSwap-finance/sundae-contracts) — DEX rewritten from Plutus to Aiken. Uses withdraw-zero (`stake.ak`) for order batching. Good example of `validators/` and `lib/` project structure at scale.
321
322**Lending & DeFi (Audited, Production):**
323- [Lenfi Smart Contracts](https://github.com/lenfiLabs/lenfi-smart-contracts) — Pooled lending protocol in Aiken. Oracle validator, pool management, liquidation. Audited by Anastasia Labs + TxPipe. Open source.
324- [fallen-icarus P2P DeFi](https://github.com/fallen-icarus) — Full suite: [cardano-loans](https://github.com/fallen-icarus/cardano-loans) (P2P lending with credit histories, compound interest), [cardano-options](https://github.com/fallen-icarus/cardano-options) (options contracts), [cardano-swaps](https://github.com/fallen-icarus/cardano-swaps) (order-book DEX with atomic swaps). Aiken branches active.
325
326**NFT & Marketplace:**
327- [Nebula](https://github.com/spacebudz/nebula) (SpaceBudz) — NFT marketplace contract with bid/offer UTxO model, chain indexer, event listener. Production Aiken.
328
329**DAO & Governance:**
330- [Logical Mechanism](https://github.com/logical-mechanism) — "Distributed Representation" semi-liquid mint-lock-stake DAO. Also [Assist](https://github.com/logical-mechanism/Assist) library of specialized Aiken functions.
331
332**Reusable Libraries:**
333- [Anastasia Labs Design Patterns](https://github.com/Anastasia-Labs/aiken-design-patterns) — Importable library (`aiken add anastasia-labs/aiken-design-patterns --version v1.1.0`). Modules: merkelized validator, multi UTxO indexer, tx level minter, linked list (ordered/unordered), stake validator, parameter validation. Conway+ extensions planned.
334- [SundaeSwap aicone](https://github.com/SundaeSwap-finance/aicone) — Reusable Aiken utility libraries.
335
336**SDK Integration:**
337- [MeshJS Contracts](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src) — Aiken contracts (escrow, marketplace, swap, vesting) with full TypeScript SDK integration. Shows the on-chain → off-chain bridge.
338
339**Learning Resources:**
340- [Awesome Aiken](https://github.com/aiken-lang/awesome-aiken) — Curated list of Aiken libraries, dApps, tutorials.
341- [Aiken Official Docs](https://aiken-lang.org/fundamentals/getting-started) — Language fundamentals and common design patterns.
342- [Cardano CTF](https://github.com/vacuumlabs/cardano-ctf) — 25 challenges teaching real exploit patterns against Plutus/Aiken validators.