๐ง Smart Contract Interaction โ
Quest Objective: Compile and interact with ErgoScript contracts Prerequisites: Completed previous tutorials Time Required: ~60 minutes Difficulty: โญโญโญโญ Hard
๐ฏ What You'll Learn โ
- โ ErgoScript basics
- โ Compiling contracts with Fleet SDK
- โ Creating contract boxes
- โ Spending from contracts
๐ ErgoScript Primer โ
ErgoScript is Ergo's smart contract language. It's:
- Declarative - Describes conditions, not procedures
- Sigma Protocol based - Cryptographic proofs
- UTXO-aware - Access box data directly
mermaid
graph LR
A[ErgoScript] -->|Compile| B[ErgoTree]
B -->|Hash| C[P2S Address]
C -->|Lock Funds| D[Contract Box]
D -->|Satisfy Conditions| E[Spend!]๐ป Example: Simple Time-Lock Contract โ
typescript
/**
* ๐ง QUEST: Time-Lock Contract
*
* Lock funds until a specific block height
*/
import { compile } from "@fleet-sdk/compiler";
import {
TransactionBuilder,
OutputBuilder,
SAFE_MIN_BOX_VALUE
} from "@fleet-sdk/core";
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// ๐ ERGOSCRIPT CONTRACT
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
const timeLockScript = `
{
// Funds can only be spent after block 1,500,000
val unlockHeight = 1500000L
// Owner's public key (replace with actual)
val ownerPk = PK("9f4QF8AD1nQ3nJahQVkMj8hFSVVzVom77b52JU7EW71Zexg6N8v")
// Spending condition: height reached AND owner signs
sigmaProp(HEIGHT >= unlockHeight && ownerPk)
}
`;
async function createTimeLock() {
console.log("๐ง Creating time-lock contract...\n");
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// Step 1: Compile the contract
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
console.log("๐ Step 1: Compiling ErgoScript...");
const compiled = compile(timeLockScript);
console.log(` โ
Compiled successfully!`);
console.log(` Contract Address: ${compiled.address}\n`);
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// Step 2: Lock funds in contract
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
console.log("๐ Step 2: Locking funds in contract...");
const inputBox = {
boxId: "input123...",
value: 5_000_000_000n, // 5 ERG to lock
ergoTree: "0008cd...",
creationHeight: 1_100_000,
assets: [],
additionalRegisters: {},
transactionId: "tx123...",
index: 0
};
// Create box at contract address
const contractOutput = new OutputBuilder(
1_000_000_000n, // Lock 1 ERG
compiled.address
);
const lockTx = new TransactionBuilder(1_200_000)
.from([inputBox])
.to(contractOutput)
.sendChangeTo("9f4QF8AD1nQ3nJahQVkMj8hFSVVzVom77b52JU7EW71Zexg6N8v")
.payMinFee()
.build();
console.log(" โ
Funds locked in contract!\n");
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// Step 3: Spend from contract (after unlock)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
console.log("๐ Step 3: Spending from contract...");
console.log(" (Only works after block 1,500,000)\n");
// The contract box that was created
const contractBox = {
boxId: "contract-box-id",
value: 1_000_000_000n,
ergoTree: compiled.ergoTree, // Contract's ergoTree
creationHeight: 1_200_001,
assets: [],
additionalRegisters: {},
transactionId: "lock-tx-id",
index: 0
};
// Spend at height >= 1,500,000
const spendTx = new TransactionBuilder(1_500_001) // After unlock!
.from([contractBox])
.to(
new OutputBuilder(
contractBox.value - 1_100_000n, // Minus fee
"9f4QF8AD1nQ3nJahQVkMj8hFSVVzVom77b52JU7EW71Zexg6N8v"
)
)
.payMinFee()
.build();
console.log(" โ
Spend transaction built!");
console.log(" (Requires owner signature + height check)\n");
return { lockTx, spendTx, contractAddress: compiled.address };
}
createTimeLock();๐ Contract Flow Diagram โ
mermaid
sequenceDiagram
participant U as ๐ค User
participant C as ๐ Compiler
participant B as โ๏ธ Blockchain
U->>C: 1. Write ErgoScript
C->>C: 2. Compile to ErgoTree
C->>U: 3. Return P2S address
U->>B: 4. Send ERG to contract
B->>B: 5. Create contract box
Note over B: Time passes...
U->>B: 6. Spend (if conditions met)
B->>U: 7. Funds released!๐ Common Contract Patterns โ
Pattern 1: Signature Required โ
typescript
const signatureRequired = `
{
val ownerPk = PK("9f4QF8AD...")
sigmaProp(ownerPk)
}
`;Pattern 2: Multi-Signature (2 of 3) โ
typescript
const multiSig = `
{
val pk1 = PK("9fAAA...")
val pk2 = PK("9fBBB...")
val pk3 = PK("9fCCC...")
sigmaProp(atLeast(2, Coll(pk1, pk2, pk3)))
}
`;Pattern 3: Anyone Can Spend (After Height) โ
typescript
const openAfterHeight = `
{
sigmaProp(HEIGHT > 2000000L)
}
`;๐ Common Issues โ
| Issue | Cause | Solution |
|---|---|---|
| Compilation error | Syntax issue | Check ErgoScript syntax |
| Cannot spend | Conditions not met | Verify HEIGHT, signatures |
| Invalid ErgoTree | Wrong encoding | Use compiler output directly |
๐ Congratulations! โ
You've completed the smart contracts tutorial! You now understand:
- ErgoScript fundamentals
- Contract compilation
- Locking and unlocking funds
- Multi-signature patterns