introduction to smartpy
play

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. Introduction to SmartPy Paris Francois Maurel – Roland Zumkeller 24 October 2019 1 / 52

  2. SmartPy Python library for writing Tezos smart contracts Compiles to Michelson Simulate & analyze Deploy & interact 2 / 52

  3. SmartPy Python is the most popular language in the world, thanks to an intuitive syntax and amazing meta-programming capabilities. SmartPy has a backend called SmartML. SmartML is written in OCaml, the same language as Tezos. We use it for everything behind the scene : typing, analysis, simulation, compilation, etc. 3 / 52

  4. Outline The SmartPy.io website 1 The SmartPy library 2 How SmartPy Compiles Contracts 3 Conclusion 4 4 / 52

  5. Outline The SmartPy.io website 1 The SmartPy library 2 How SmartPy Compiles Contracts 3 Conclusion 4 5 / 52

  6. SmartPy.io 6 / 52

  7. Hello, World! import smartpy as sp 1 2 class HelloWorld (sp.Contract): 3 def __init__(self): self.init(mem = "") 4 5 @sp.entryPoint 6 def remember(self, param): 7 self.data.mem += param 8 9 @addTest(name = "Test") 10 def test(): 11 c = HelloWorld() 12 s = sp.testScenario() 13 s += c 14 s += c.remember("Hello, ") 15 s += c.remember("World!") 16 7 / 52

  8. Hello, World : Michelson 8 / 52

  9. Library vs. Language Python is used to construct SmartPy contracts, not to execute them. Internal representation : “SmartML ” (OCaml) Could also be embedded in JavaScript etc. 9 / 52

  10. What happens inside the browser? 1 The Python code (executed once , via Brython) constructs a syntax tree : @sp.entryPoint def remember(self, params): print (self.data.mem + param + 42) self.data.mem += params On the browser console : (add (add (attr (data) "mem") (params)) (literal (intOrNat 42))) 2 The SmartPy backend (run via js_of_ocaml) performs type checking, evaluation, compilation etc. 3 The output is rendered as HTML. 10 / 52

  11. Non-Hello-World Examples on SmartPy.io : Calculator Fungible and non-fungible assets Multisig contracts Escrow contract State channels (under development) Games : tic-tac-toe, nim, chess 11 / 52

  12. Out-of-browser SmartPy : Interpreter $ SmartPy.sh local-test calculator.py calc $ cat calc/test.output Creating contract -> 0 Executing add(Record(x = 2, y = 5))... -> 7 Executing square(12)... -> 144 Verifying contractData(0).value == 144... OK Executing squareRoot(1234)... -> 35 Executing factorial(100)... -> 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 Executing log2(contractData(0).value)... -> 524 12 / 52

  13. Out-of-browser SmartPy : Compiler $ 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 ... Soon : automated testing with compiled code (in sandboxed tezos-client) 13 / 52

  14. Example : Fungible Assets class Fungible (sp.Contract): 1 def __init__(self, admin): 2 self.init(balances = sp.bigMap(), admin = admin) 3 4 def increaseBalance(self, x, amount): 5 sp. if self.data.balances.contains(x): 6 self.data.balances[x] += amount 7 sp. else : 8 self.data.balances[x] = amount 9 10 def decreaseBalance(self, x, amount): 11 b = self.data.balances[x] - amount 12 sp.verify(b >= 0) 13 sp. if b == 0: 14 del self.data.balances[x] 15 sp. else : 16 self.data.balances[x] = b 17 14 / 52

  15. Example : Fungible Assets @sp.entryPoint 1 def transfer(self, params): 2 self.decreaseBalance(sp.sender, params.amount) 3 self.increaseBalance(params.dest, params.amount) 4 5 @sp.entryPoint 6 def mint(self, params): 7 sp.verify(sp.sender == self.data.admin) 8 self.increaseBalance(params.dest, params.amount) 9 15 / 52

  16. Example : Fungible Assets @sp.entryPoint 1 def transfer(self, params): 2 self.decreaseBalance(sp.sender, params.amount) 3 self.increaseBalance(params.dest, params.amount) 4 5 @sp.entryPoint 6 def mint(self, params): 7 sp.verify(sp.sender == self.data.admin) 8 self.increaseBalance(params.dest, params.amount) 9 We are going to extend this example together after this talk. 15 / 52

  17. How To Write a Test @addTest(name = "First test") 1 def test(): 2 admin = sp.address("Admin") 3 alice = sp.address("Alice") 4 bob = sp.address("Bob") 5 6 s = sp.testScenario() 7 8 s = Fungible(admin = admin) 9 s += c 10 s += c.mint(dest = alice, amount = 5).run(sender = admin) 11 s += c.mint(dest = bob, amount = 5).run(sender = admin) 12 s += c.transfer(dest = alice, amount = 3).run(sender = bob) 13 s += c.transfer(dest = alice, amount = 3).run(sender = bob) 14 s += c.mint(dest = bob, amount = 100).run(sender = bob) 15 16 / 52

  18. How To Run a Test 17 / 52

  19. How To Run a Test 18 / 52

  20. How To Run a Test 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

  21. How To Originate 20 / 52

  22. How To Interact With a Contract 21 / 52

  23. Fungible Assets : better-call.dev c.mint(dest = alice, amount = 5).run(sender = admin) 22 / 52

  24. Fungible Assets : better-call.dev c.mint(dest = bob, amount = 5).run(sender = admin) 23 / 52

  25. Fungible Assets : better-call.dev c.transfer(dest = alice, amount = 3).run(sender = bob) 24 / 52

  26. Fungible Assets : better-call.dev c.transfer(dest = alice, amount = 3).run(sender = bob) 25 / 52

  27. Fungible Assets : better-call.dev c.mint(dest = bob, amount = 100).run(sender = bob) 26 / 52

  28. Outline The SmartPy.io website 1 The SmartPy library 2 How SmartPy Compiles Contracts 3 Conclusion 4 27 / 52

  29. SmartPy language elements Entry points Data types : TUnit , TBool , TInt / TNat , TString , TBytes TRecord Containers : lists, TSet , TMap , TBigMap TMutez , TTimestamp , TAddress , THash , TKey Control flow : sp.if , sp.for , sp.while Local variables Runtime errors and checks 28 / 52

  30. Data : Integers In Michelson there are two integer types : int for integers nat for non-negative integers In SmartPy there are : TInt , TNat , and TIntOrNat . When we write y = abs(x) , SmartPy infers that x : TInt and y : TNat . When we write x + y , SmartPy checks that x and y have the same type. 29 / 52

  31. Data : Records sp.record(row = 2, col = 3) is a value. No need to declare a type, SmartPy infers it : {row: TIntOrNat; col: TIntOrNat} . Can be nested, passed to entry points, used inside complex data structures etc. Compiled to nested Michelson pairs (with annotations). 30 / 52

  32. Data : Lists and maps self.init(l = ['a','b'], m = {'a': 65, 'b': 66}) Inferred types : l: [TString] m: TMap(TString, TIntOrNat) More explicitly : sp.map({'a': 65, 'b': 66} , tkey=TString, tvalue=TInt) Operations : self.data.l.append('c') self.data.m['c'] = 67 31 / 52

  33. Local Variables and Assignment Python variables contain SmartPy expressions (effectively inlined) : s = self.data.x + self.data.y self.data.z = s*s SmartPy “local” variables are preserved : s = sp.newLocal('s', self.data.x + self.data.y) self.data.z = s*s 32 / 52

  34. Control flow : sp. while loops Binary logarithm : @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(...) . No recursion. 33 / 52

  35. Runtime Errors and Checks Division and map lookups can fail. 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) Compiled to Michelson- FAIL . 34 / 52

  36. Assignment In Nested Maps What does this Python program output? x = {'a': {'b': 0}} y = x['a'] y['b'] = 42 print (x['a']['b']) 35 / 52

  37. Assignment In Nested Maps What does this Python program output? x = {'a': {'b': 0}} y = x['a'] y['b'] = 42 print (x['a']['b']) Output : 42 35 / 52

  38. Assignment In Nested Maps What does this Python program output? x = {'a': {'b': 0}} y = x['a'] y['b'] = 42 print (x['a']['b']) Output : 42 What does this SmartPy contract output? 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'] Output : 0 35 / 52

  39. Outline The SmartPy.io website 1 The SmartPy library 2 How SmartPy Compiles Contracts 3 Conclusion 4 36 / 52

  40. Compiler : Inner Workings Input : SmartML representation. "stack tags" keep track of location of data : parameter, storage, local variable, iteration variable “Operations” (calls to other contracts) are added as late as possible. Param-storage pair always remains at bottom of the stack. 37 / 52

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend