Introduction to
Smart Contracts
Slides and code partially from
Jason Weathersby, Algorand
With Examples on Algorand
Fabrice Benhamouda
Agenda
2
General Overview
of Smart Contracts
What is a Smart Contract
4
Smart Contract
In Development
Smart Contract
Blockchain State
Algorand
Blockchain
Deploy
Smart Contract
Smart Contract
Example of Use of Smart Contracts
5
What a Smart Contract Can Do?
6
What a Smart Contract Cannot Directly Do?
7
Smart Contract
Smart Contract
What a Smart Contract Cannot Directly Do?
8
Smart Contract
How to Interact with Smart Contracts?
9
Application Transaction
Deployment and Interaction
⇓
Transactions
Smart Contract
Blockchain State
Algorand
Blockchain
Smart Contract
Smart Contract
Algorand Smart Contracts
Overview: storage and transaction types
Accounts & Smart Contracts
11
Account address
=public key for basic accounts
PU3KOXQX5OGSUHEBWQTSVI47QZJSRX5RY3IJI3RNFDWCX5LJKBP5L43XAQ
Smart Contract
Application ID
=
68633014
≠
(on Algorand)
= 25-word mnemonic:�
attract tourist harbor warfare employ harbor unfair code coach nest zero tool game blur heavy stock novel giggle quiz grunt note endless day abandon cage
Account
12
Address of the account
Transaction of the account
Balances of the account
Application call transaction
Transfer of asset USDC
Transfer of Algos
Application
13
Application ID
Don’t Get Confused
14
≠
At the end of the presentation only
Smart Contract
=
Application
Full Blockchain vs State
15
State of the blockchain
can computed
from all the transactions
…
Transactions
Transaction 1
Transaction 2
Transaction 3
…
Effect of a Transaction
16
Alice sends
2 Algos to Bob
State
Full Blockchain
Alice
NX2J4…
Bob
GVD7Z…
2 Algos
Address | Algo Balance | … |
NX2J4… | 20 | … |
GVD7Z… | 7 | … |
… | … | … |
Address | Algo Balance | … |
NX2J4… | 18 | … |
GVD7Z… | 9 | … |
… | … | … |
Before
After
(ignoring transaction fees and many more details)
State size = the same*
Blockchain size increased
*some operations increase the state size
Global State
Application can store data in
17
Local State
State
Application ID | Key | Value |
68633014 | tally_vote_yes | 120 |
68633014 | tally_vote_no | 250 |
… | … | … |
Local and Global State
Application can store data in
18
Everything stored on chain in the state.
State
Application ID | Key | Value |
68633014 | tally_vote_yes | 120 |
68633014 | tally_vote_no | 250 |
… | … | … |
Account | Application ID | Key | Value |
NX2J4… | 68633014 | registered_voter | 1 |
NX2J4… | 68633014 | vote | yes |
GVD7Z… | 68633014 | registered_voter | 1 |
GVD7Z… | 68633014 | vote | no |
… | … | … | … |
Local and Global State: Access Restrictions
19
Even with secret key of U,
it is impossible to change the local storage of A for U,
without making an application call to A
| Application A | Application B |
Global state of A | Read/Write | Read only |
Local state of A for account U | Read/Write even if transaction sender is not U | Read only |
Some More Details
20
Application Transaction
Smart Contract
TEAL
Global State
Local State Account 1
Approval Program
Clear Program
TEAL
Generated, signed, sent using SDK
(Python, JS, Go, Java, …)
(Uses an algod endpoint)
Written in TEAL
Or generated by a PyTEAL
script (written in Python)
(No SDK, no algod endpoint)
Transaction Sub-Types for Application
21
Smart Contract
NoOp
TEAL
TEAL
Approval Program
Clear Program
OptIn
DeleteApplication
UpdateApplication
CloseOut
Clear
Used to Communicate With Smart Contract
Graceful clear
local storage
Force clear
local storage
Allocate
local storage
Default call
+ creation if AppID=0
Algorand Smart Contracts
Inner transactions / smart contracts as escrow
Application Account = Smart Contract Escrow
23
Application
Account
deploy/create
ASA
Smart Contract
control
transfer
creator
call
transaction
user/account
App ID
E.g, 68633014
Algorand Address
E.g, C6G2TUQWZ7VID…
Sending Tokens out of the Application Account
24
Application Transaction
Global State
Local State User 1
Local State User 1
Local State User 1
Local State User 1
Inner Transaction
Application
Account
Smart Contract
Summary of Smart Contracts / Applications
25
How does the smart
contract knows it
received the tokens?
Algorand Smart Contracts
Understanding ASA, Group Transactions / Atomic Transfer
Algorand Standard
Assets ASA
27
Create your token in one click on https://algodesk.io !
Atomic Transfers / Group Transactions
28
Alice
Bob
Atomic transfer:
Either all transactions succeed
Or all transactions fail
(work for up to 16 transactions)
ASA
1 Algo
20 USDC
Any transaction can be part of atomic transfer
Can include up to 16 transactions
Allow a Smart Contract to Receive Tokens
29
Alice
1 Algo
Application call
Application
Account
Smart Contract
Smart contract can inspect
the transactions in their atomic group.
(Note: smart contracts can only act when triggered by an application call transaction and cannot inspect transactions outside of their own group.)
Algorand Smart Contracts
Case Study: Crowdfunding
Crowdfunding
31
Crowdfunding — Creation and Funding
32
Global State
Fund Start Date
Fund End Date
Fund Goal�Current Funding Received
Receiver Address
App transaction create
Sets dates, Fund goal, fund receiver and creator
Payment Tx
From Donator to Smart Contract Escrow
App transaction optin
before Fund end date
Atomic group
Local State
of each User
Giving Amount
1
2
Application
Account
Smart Contract
Crowdfunding — Payout / Reimbursement (after fund end)
33
Global State
Fund Start Date
Fund End Date
Fund Goal�Current Funding Received
Receiver Address
App transaction noop
Pay the project
if fund goal reached
App transaction noop
Reimburse user funds
if fund goal not reached
Local State
of each User
Giving Amount
3
4
Application
Account
Smart Contract
Payouts and reimbursements
made via Inner Transactions from
Application Accounts
If Current Funding Received >= Fund Goal
If Current Funding Received < Fund Goal
(transaction to be sent by each user)
Algorand Smart Contracts
Runtime Architecture and TEAL
Smart Contract Runtime Architecture
35
Smart Contract Runtime
Global
Variables
Transaction(s)
Properties
Read Only
Stack
TEAL Program(s), Loaded on Create Update
Application Array
Arguments Array
Per Transaction
Transaction Submission
Accounts Array
Temporary Scratch
Read/Write
Global/LocalState
Assets Array
TEAL — Transaction Execution Approval Language
36
1000
5
…
hello
Stack
Push
= add on top
Pop
= remove the top
Simple Stack Example
37
…
int 5
int 1000
>=
1000
5
…
int 5
int 1000
>=
2
5
…
int 5
int 1000
>=
1
…
int 5
int 1000
>=
5
3
1000
0 (=false)
…
5 >= 1000
(true = 1)
https://developer.algorand.org/docs/get-details/dapps/avm/teal/opcodes/#_7
TEAL Basic Opcodes for State
38
“tally_vote_yes”
…
…
byte “tally_vote_yes”
app_global_get
…
120
…
State
Application ID | Key | Value |
68633014 | tally_vote_yes | 120 |
… | … | … |
TEAL Scratch Space
256 position of scratch space to store temporary values
39
State Demo
40
Every time called, increment a global counter
41
42
TEAL: Jumps and Loops
43
// loop 1 - 10
// init loop var
int 0
loop:
int 1
+
// implement loop code
// …
// check upper bound
int 10
<=
bnz loop
TEAL Opcodes and Pseudo-Opcodes (advanced)
44
>=
0x10
0x8105
pushint 5
int 5
intcblock 5
…
intc_0
0x200105…22
or
PyTeal — Python Library
45
def app():
handle_noop = Seq(
Assert(Txn.application_args[0] == Bytes("payme")),
InnerTxnBuilder.Begin(),
InnerTxnBuilder.SetFields({
TxnField.type_enum: TxnType.Payment,
TxnField.amount: Int(5000),
TxnField.receiver: Txn.sender()
}),
InnerTxnBuilder.Submit(),
Int(1)
)
return Cond(
[Txn.application_id() == Int(0), Approve()],
[Txn.on_completion() == OnComplete.NoOp, Return(handle_noop)]
)
if __name__ == '__main__':
print(compileTeal(app(), mode=Mode.Application, version=5))
#pragma version 5
txn ApplicationID
int 0
==
bnz main_l4
txn OnCompletion
int NoOp
==
bnz main_l3
err
main_l3:
txna ApplicationArgs 0
byte "payme"
==
assert
itxn_begin
int pay
itxn_field TypeEnum
int 5000
itxn_field Amount
txn Sender
itxn_field Receiver
itxn_submit
int 1
return
main_l4:
int 1
return
outputs
PyTeal Documentation
46
TEAL: Transaction Properties and Global Variables
47
Checking Type of Transaction
48
gtxn 0 TypeEnum
int pay
==
TEAL Program
Gtxn[0].type_enum() == TxnType.Payment
PyTEAL Program
Transaction 0 in the group
is a payment transaction
Application Transaction Sub-Types
49
txn OnCompletion
int NoOp
==
TEAL Program
Txn.on_completion() == OnComplete.NoOp
PyTEAL Program
Current application call is NoOp
Global Variables
50
50
global LatestTimestamp
int 1643691600
>=
TEAL Program
Global.latest_timestamp() >=
Int(1643691600)
PyTEAL Program
Previous round was after*
02/01/2022, 00:00 EST
Timestamp = 1643691600
* LatestTimestamp is best effort and may not be 100% accurate
TEAL: Checking Payment to Application Account
51
Payment of 2 Algos to
Application Account
Atomic
Application Call
**It is recommended not to enforce the atomic group size (as done in this simplified example) as it prevents “composition”. Instead look at previous transaction.
Seq([
Assert(Global.group_size() == Int(2)),
Assert(Gtxn[0].type_enum() == TxnType.Payment),
Assert(Gtxn[0].amount() == Int(2000000)),
Assert(Gtxn[0].receiver() == Global.current_application_address()),
…
])
PyTEAL Program
global GroupSize
int 2
==
assert
gtxn 0 TypeEnum
int pay
==
assert
TEAL Program
gtxn 0 Amount
int 2000000
==
assert
gtxn 0 Receiver
global CurrentApplicationAddress
==
assert
TEAL: Inner Transactions
52
52
Seq([
InnerTxnBuilder.Begin(),
InnerTxnBuilder.SetFields({
TxnField.type_enum: TxnType.Payment,
TxnField.amount: Int(1420000),
TxnField.receiver: Txn.sender(),
}),
InnerTxnBuilder.Submit(),
…
])
PyTEAL Program
itxn_begin
int pay
itxn_field TypeEnum
int 1420000
itxn_field Amount
txn Sender
itxn_field Receiver
itxn_submit
TEAL Program
TEAL: Subroutines
53
@Subroutine(TealType.uint64)
def isEvenSubRoutine(i):
return i % Int(2) == Int(0)
�Seq([
Assert(isEvenSubRoutine(Gtxn[0].amount())),
Assert(isEvenSubRoutine(Gtxn[1].amount())),
…
]
PyTEAL Program
gtxn 0 Amount
callsub sub0
assert
gtxn 1 Amount
callsub sub0
assert
…
…
TEAL Program
sub0: // isEvenSubRoutine
store 0
load 0
int 2
%
int 0
==
retsub
54
54
@Subroutine(TealType.uint64)
def isEvenSubRoutine(i):
return i % Int(2) == Int(0)
�Seq([
Assert(isEvenSubRoutine(Gtxn[0].amount())),
Assert(isEvenSubRoutine(Gtxn[1].amount())),
…
]
PyTEAL Program
gtxn 0 Amount
callsub sub0
assert
gtxn 1 Amount
callsub sub0
assert
…
…
TEAL Program
sub0: // isEvenSubRoutine
store 0
load 0
int 2
%
int 0
==
retsub
def isEvenPyFunc(i):
return i % Int(2) == Int(0)
�Seq([
Assert(isEvenPyFunc(Gtxn[0].amount())),
Assert(isEvenPyFunc(Gtxn[1].amount())),
…
]
PyTEAL Program
gtxn 0 Amount
int 2
%
int 0
==
assert
�
TEAL Program
gtxn 1 Amount
int 2
%
int 0
==
assert
…
Normal Python Function
Subroutine
The code is copy-pasted
for every invocation
TEAL: Application Arguments and “Methods”
55
How to specify which action/method to do in application call?
PyTEAL: Classic Skeleton for Smart Contract
56
def approval_program():
is_creator = Txn.sender() == Global.creator_address()
on_vote = Seq([...])� on_register …
� program = Cond(
[Txn.application_id() == Int(0), on_creation],
[Txn.on_completion() == OnComplete.DeleteApplication, Return(is_creator)],
[Txn.on_completion() == OnComplete.UpdateApplication, Return(is_creator)],
[Txn.on_completion() == OnComplete.CloseOut, on_closeout],
[Txn.on_completion() == OnComplete.OptIn, on_register],
[Txn.application_args[0] == Bytes("vote"), on_vote],
)
return program
if __name__ == "__main__":
with open("approval.teal", "w") as f:
compiled = compileTeal(approval_program(), mode=Mode.Application, version=5)
f.write(compiled)
Only the creator of the app can delete/update it
Logic for all the methods
When the ABI is finalized, the skeleton will change slightly.
Quick Summary
57
Application Transaction
(specifies Application Arguments)
Smart Contract
TEAL
Global State
Local State
“opted-in” Account 1
Approval Program
Clear Program
TEAL
Generated, signed, sent using SDK
(Python, JS, Go, Java, …)
(Uses an algod endpoint)
Written in TEAL
Or generated by a PyTeal
script (written in Python)
(No SDK, no algod endpoint)
Smart Contract = Application
= program living on the chain
Current Convention*
First argument = method called
* (pre-ABI)
Everything stored on chain in the state.
Application
Account
Control via inner transactions
PyTeal Simple
Escrow Demo
58
Every time method “payme” called (first argument),
send 2.1 Algo to the transaction sender
59
60
Algorand Smart Contracts
Fees, min balance, cost, and other constraints
Fee vs Minimum Balance
62
Use constants.min_txn_fee
Since Algorand currently support about 1,000 transactions per sec,
congestion is extremely rare
To empty an account, special “close remainder to” transaction.
TEAL: Cost and Constraints
63
Reach.sh — Alternative to PyTeal with guarantee safety properties
64
Same code targets �both Ethereum and Algorand
Comparison with Ethereum
Smart Contracts
Comparison with Ethereum (1/2)
66
| Algorand | Ethereum |
| Smart contracts ≠ accounts | Smart contract is an account |
Lang. | TEAL, PyTeal, Reach, … | Solidity, Reach, … |
Fees | Independent of complexity of smart contract�Almost no congestion on Algorand 0.001 Algo per tx (<$0.002 in Feb 2022) | Gas fee depends on smart contract complexity�Gas price depends on congestion� More than $10 for ERC-20 in early Feb 2022 |
Storage | 64 k/v global�16 k/v local per account�Deposit via min balance (reimbursable) | Unlimited global storage�Payment via gas fee (non-reimbursable) |
Computation | Very constrained but sufficient for most applications | Less constrained but expensive gas fee |
Comparison with Ethereum (2/2)
67
| Algorand | Ethereum |
Receive native token | Atomic transfer�1. Payment�2. Application call | Part of application call transaction�(no need for extra transaction) |
Custom�tokens | ASA �= similar to native token, same tx fee | ERC-20, ERC-721, ERC-1155 �= smart contracts, higher fee |
Receive custom tokens | Same as receiving native token | Two-step process: (not easily atomic)�1. Approval of transfer from sender�2. Application call |
Atomic transfer | Layer-1 feature | Requires writing a smart contract |
DApps and Wallets
68
Decentralized Applications = DApp
Usually, two parts:
69
Frontend cannot ask user’s secret key for security reasons
Wallets for DApps
70
User must check the transactions to be signed
(e.g., not moving all their tokens to a malicious party)
TinyMan Demo
71
72
73
74
75
76
77
78
Advanced Algorand Topics
79
Fee Pooling
80
Account Types
81
Smart Signatures (former Stateless Smart Contracts)
82
Alice
Bob
1 Algo
20 USDC
Albert
2 Algos
20 USDC
Alma
1 Algo
20 USDC
Signed by Albert
Signed by Alice
Signed by Alma
Signed by Bob
Signed by Bob
Signed by Bob
Smart signature!
1 Algo
Smart Signatures (former Stateless Smart Contracts)
Rekeying
84
Use New Accounts Local State to Extend Global State
85
2 solutions:
Resources
86
This presentation used resources from Flaticon.com