Introduction to SmartPy
Paris Francois Maurel – Roland Zumkeller 24 October 2019
1 / 52
Introduction to SmartPy Paris Francois Maurel Roland Zumkeller 24 - - PowerPoint PPT Presentation
Introduction to SmartPy Paris Francois Maurel Roland Zumkeller 24 October 2019 1 / 52 SmartPy Python library for writing Tezos smart contracts Compiles to Michelson Simulate & analyze Deploy & interact 2 / 52 SmartPy Python
1 / 52
2 / 52
3 / 52
4 / 52
5 / 52
6 / 52
1
import smartpy as sp
2 3
class HelloWorld(sp.Contract):
4
def __init__(self): self.init(mem = "")
5 6
@sp.entryPoint
7
def remember(self, param):
8
self.data.mem += param
9 10
@addTest(name = "Test")
11
def test():
12
c = HelloWorld()
13
s = sp.testScenario()
14
s += c
15
s += c.remember("Hello, ")
16
s += c.remember("World!")
7 / 52
8 / 52
9 / 52
1 The Python code (executed once, via
@sp.entryPoint def remember(self, params): print(self.data.mem + param + 42) self.data.mem += params
(add (add (attr (data) "mem") (params)) (literal (intOrNat 42))) 2 The SmartPy backend (run via
3 The output is rendered as HTML.
10 / 52
11 / 52
$ SmartPy.sh local-test calculator.py calc $ cat calc/test.output Creating contract
Executing add(Record(x = 2, y = 5))...
Executing square(12)...
Verifying contractData(0).value == 144... OK Executing squareRoot(1234)...
Executing factorial(100)...
Executing log2(contractData(0).value)...
12 / 52
$ SmartPy.sh local-compile calculator.py 'Calculator()' calc $ cat calc/contractCode.tz parameter (or (or (or (or (or (pair %add (nat %x) (nat %y)) storage nat; code { DUP; # pair(params, storage).pair(params, storage) CDR; # storage.pair(params, storage) SWAP; # pair(params, storage).storage CAR; # params.storage IF_LEFT ...
13 / 52
1
class Fungible(sp.Contract):
2
def __init__(self, admin):
3
self.init(balances = sp.bigMap(), admin = admin)
4 5
def increaseBalance(self, x, amount):
6
sp.if self.data.balances.contains(x):
7
self.data.balances[x] += amount
8
sp.else:
9
self.data.balances[x] = amount
10 11
def decreaseBalance(self, x, amount):
12
b = self.data.balances[x] - amount
13
sp.verify(b >= 0)
14
sp.if b == 0:
15
del self.data.balances[x]
16
sp.else:
17
self.data.balances[x] = b
14 / 52
1
@sp.entryPoint
2
def transfer(self, params):
3
self.decreaseBalance(sp.sender, params.amount)
4
self.increaseBalance(params.dest, params.amount)
5 6
@sp.entryPoint
7
def mint(self, params):
8
sp.verify(sp.sender == self.data.admin)
9
self.increaseBalance(params.dest, params.amount)
15 / 52
1
@sp.entryPoint
2
def transfer(self, params):
3
self.decreaseBalance(sp.sender, params.amount)
4
self.increaseBalance(params.dest, params.amount)
5 6
@sp.entryPoint
7
def mint(self, params):
8
sp.verify(sp.sender == self.data.admin)
9
self.increaseBalance(params.dest, params.amount)
15 / 52
1
@addTest(name = "First test")
2
def test():
3
admin = sp.address("Admin")
4
alice = sp.address("Alice")
5
bob = sp.address("Bob")
6 7
s = sp.testScenario()
8 9
s = Fungible(admin = admin)
10
s += c
11
s += c.mint(dest = alice, amount = 5).run(sender = admin)
12
s += c.mint(dest = bob, amount = 5).run(sender = admin)
13
s += c.transfer(dest = alice, amount = 3).run(sender = bob)
14
s += c.transfer(dest = alice, amount = 3).run(sender = bob)
15
s += c.mint(dest = bob, amount = 100).run(sender = bob)
16 / 52
17 / 52
18 / 52
c.mint(dest = alice, amount = 5).run(sender = admin) c.mint(dest = bob, amount = 5).run(sender = admin) c.transfer(dest = alice, amount = 3).run(sender = bob) c.transfer(dest = alice, amount = 3).run(sender = bob) c.mint(dest = bob, amount = 100).run(sender = bob)
19 / 52
20 / 52
21 / 52
c.mint(dest = alice, amount = 5).run(sender = admin)
22 / 52
c.mint(dest = bob, amount = 5).run(sender = admin)
23 / 52
c.transfer(dest = alice, amount = 3).run(sender = bob)
24 / 52
c.transfer(dest = alice, amount = 3).run(sender = bob)
25 / 52
c.mint(dest = bob, amount = 100).run(sender = bob)
26 / 52
27 / 52
28 / 52
29 / 52
sp.record(row = 2, col = 3) is a value.
30 / 52
self.init(l = ['a','b'], m = {'a': 65, 'b': 66})
l: [TString] m: TMap(TString, TIntOrNat)
sp.map({'a': 65, 'b': 66} , tkey=TString, tvalue=TInt)
self.data.l.append('c') self.data.m['c'] = 67
31 / 52
s = self.data.x + self.data.y self.data.z = s*s
s = sp.newLocal('s', self.data.x + self.data.y) self.data.z = s*s
32 / 52
@sp.entryPoint def log2(self, x): self.data.result = 0 y = sp.newLocal('y', x) sp.while 1 < y: self.data.result += 1 y.set(y // 2) sp.while ... is syntactic sugar for with sp.whileBlock(...).
33 / 52
sp.verify checks a condition at runtime : def log2(self, x): sp.verify(x > 0) # <<< self.data.result = 0 y = sp.newLocal('y', x) sp.while 1 < y: self.data.result += 1 y.set(y // 2)
34 / 52
x = {'a': {'b': 0}} y = x['a'] y['b'] = 42 print(x['a']['b'])
35 / 52
x = {'a': {'b': 0}} y = x['a'] y['b'] = 42 print(x['a']['b'])
35 / 52
x = {'a': {'b': 0}} y = x['a'] y['b'] = 42 print(x['a']['b'])
def __init__(self): self.init(x = {'a': {'b': 0}}, out = -1) @sp.entryPoint def ep(self, params): y = sp.newLocal('y', self.data.x['a']) y['b'] = 42 self.data.out = self.data.x['a']['b']
35 / 52
36 / 52
37 / 52
for-loops over ranges, while-loops : LOOP
38 / 52
39 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) CDR; # storage.pair(params, storage) DROP; # pair(params, storage) DUP; # pair(params, storage).pair(params, storage) CAR; # params.pair(params, storage) DIP { DUP }; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string CAR; # params.string PAIR; # pair(params, _) CDR; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string
40 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) CDR; # storage.pair(params, storage) DROP; # pair(params, storage) DUP; # pair(params, storage).pair(params, storage) CAR; # params.pair(params, storage) DIP { DUP }; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string CAR; # params.string PAIR; # pair(params, _) CDR; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string # CDR; DROP
DROP # DUP; DROP
41 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) CAR; # params.pair(params, storage) DIP { DUP }; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string CAR; # params.string PAIR; # pair(params, _) CDR; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string # CDR; DROP
DROP # DUP; DROP
DROP
42 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) CAR; # params.pair(params, storage) DIP { DUP }; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string CAR; # params.string PAIR; # pair(params, _) CDR; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string # CAR; DIP { ... }
DIP { ... }; CAR # DUP; DIP { DUP }
DUP; DUP
43 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) DUP; # pair(params, storage).pair(params, storage).pair(params, CAR; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string CAR; # params.string PAIR; # pair(params, _) CDR; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string # CAR; DIP { ... }
DIP { ... }; CAR # DUP; DIP { DUP }
DUP; DUP
44 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) DUP; # pair(params, storage).pair(params, storage).pair(params, CAR; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string CAR; # params.string PAIR; # pair(params, _) CDR; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string # PAIR; CDR
DROP # CAR; DROP
DROP
45 / 52
# self.data.mem += params DUP; # pair(params, storage).pair(params, storage) DUP; # pair(params, storage).pair(params, storage).pair(params, CAR; # params.pair(params, storage).pair(params, storage) SWAP; # pair(params, storage).params.pair(params, storage) CDR; # storage.params.pair(params, storage) CONCAT; # string.pair(params, storage) SWAP; # pair(params, storage).string DROP; # string NIL operation; # list (operation).string PAIR; # pair (list (operation)) string # PAIR; CDR
DROP # CAR; DROP
DROP
46 / 52
47 / 52
48 / 52
48 / 52
49 / 52
1
2
3
4
49 / 52
50 / 52
51 / 52
52 / 52