-
Notifications
You must be signed in to change notification settings - Fork 0
/
Smart-contracts-Cardano-slides.html
626 lines (603 loc) · 149 KB
/
Smart-contracts-Cardano-slides.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
<!DOCTYPE html><html lang="en-CA"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0"><meta name="apple-mobile-web-app-capable" content="yes"><meta http-equiv="X-UA-Compatible" content="ie=edge"><meta property="og:type" content="website"><meta name="twitter:card" content="summary"><style>@media screen{body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button{-webkit-tap-highlight-color:transparent;-webkit-appearance:none;appearance:none;background-color:transparent;border:0;color:inherit;cursor:pointer;font-size:inherit;opacity:.8;outline:none;padding:0;transition:opacity .2s linear}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:disabled,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:disabled,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:disabled,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:disabled{cursor:not-allowed;opacity:.15!important}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover{opacity:1}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:active,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:active,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover:active,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover:active{opacity:.6}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:not(:disabled),body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:not(:disabled),body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover:not(:disabled),body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover:not(:disabled){transition:none}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button.bespoke-marp-presenter-info-page-prev{background:transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNNjggOTAgMjggNTBsNDAtNDAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button.bespoke-marp-presenter-info-page-next{background:transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJtMzIgOTAgNDAtNDAtNDAtNDAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen]{background:transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZmZmO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4fTwvc3R5bGU+PC9kZWZzPjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI2MCIgeD0iMTAiIHk9IjIwIiBjbGFzcz0iYSIgcng9IjUuNjciLz48cGF0aCBkPSJNNDAgNzBIMjBWNTBtMjAgMEwyMCA3MG00MC00MGgyMHYyMG0tMjAgMCAyMC0yMCIgY2xhc3M9ImEiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button.exit[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button.exit[data-bespoke-marp-osc=fullscreen]{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZmZmO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4fTwvc3R5bGU+PC9kZWZzPjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI2MCIgeD0iMTAiIHk9IjIwIiBjbGFzcz0iYSIgcng9IjUuNjciLz48cGF0aCBkPSJNMjAgNTBoMjB2MjBtLTIwIDAgMjAtMjBtNDAgMEg2MFYzMG0yMCAwTDYwIDUwIiBjbGFzcz0iYSIvPjwvc3ZnPg==")}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter]{background:transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNODcuOCA0Ny41Qzg5IDUwIDg3LjcgNTIgODUgNTJIMzVhOC43IDguNyAwIDAgMS03LjItNC41bC0xNS42LTMxQzExIDE0IDEyLjIgMTIgMTUgMTJoNTBhOC44IDguOCAwIDAgMSA3LjIgNC41ek02MCA1MnYzNm0tMTAgMGgyME00NSA0MmgyMCIvPjwvc3ZnPg==") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button.bespoke-marp-presenter-note-bigger{background:transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNMTIgNTBoODBNNTIgOTBWMTAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button.bespoke-marp-presenter-note-smaller{background:transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNMTIgNTBoODAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}}@keyframes __bespoke_marp_transition_reduced_outgoing__{0%{opacity:1}to{opacity:0}}@keyframes __bespoke_marp_transition_reduced_incoming__{0%{mix-blend-mode:plus-lighter;opacity:0}to{mix-blend-mode:plus-lighter;opacity:1}}.bespoke-marp-note,.bespoke-marp-osc,.bespoke-progress-parent{display:none;transition:none}@media screen{::view-transition-group(*){animation-duration:var(--marp-bespoke-transition-animation-duration,.5s);animation-timing-function:ease}::view-transition-new(*),::view-transition-old(*){animation-delay:0s;animation-direction:var(--marp-bespoke-transition-animation-direction,normal);animation-duration:var(--marp-bespoke-transition-animation-duration,.5s);animation-fill-mode:both;animation-name:var(--marp-bespoke-transition-animation-name,var(--marp-bespoke-transition-animation-name-fallback,__bespoke_marp_transition_no_animation__));mix-blend-mode:normal}::view-transition-old(*){--marp-bespoke-transition-animation-name-fallback:__bespoke_marp_transition_reduced_outgoing__;animation-timing-function:ease}::view-transition-new(*){--marp-bespoke-transition-animation-name-fallback:__bespoke_marp_transition_reduced_incoming__;animation-timing-function:ease}::view-transition-new(root),::view-transition-old(root){animation-timing-function:linear}::view-transition-new(__bespoke_marp_transition_osc__),::view-transition-old(__bespoke_marp_transition_osc__){animation-duration:0s!important;animation-name:__bespoke_marp_transition_osc__!important}::view-transition-new(__bespoke_marp_transition_osc__){opacity:0!important}.bespoke-marp-transition-warming-up::view-transition-group(*),.bespoke-marp-transition-warming-up::view-transition-new(*),.bespoke-marp-transition-warming-up::view-transition-old(*){animation-play-state:paused!important}body,html{height:100%;margin:0}body{background:#000;overflow:hidden}svg.bespoke-marp-slide{content-visibility:hidden;opacity:0;pointer-events:none;z-index:-1}svg.bespoke-marp-slide:not(.bespoke-marp-active) *{view-transition-name:none!important}svg.bespoke-marp-slide.bespoke-marp-active{content-visibility:visible;opacity:1;pointer-events:auto;z-index:0}svg.bespoke-marp-slide.bespoke-marp-active.bespoke-marp-active-ready *{animation-name:__bespoke_marp__!important}@supports not (content-visibility:hidden){svg.bespoke-marp-slide[data-bespoke-marp-load=hideable]{display:none}svg.bespoke-marp-slide[data-bespoke-marp-load=hideable].bespoke-marp-active{display:block}}}@media screen and (prefers-reduced-motion:reduce){svg.bespoke-marp-slide *{view-transition-name:none!important}}@media screen{[data-bespoke-marp-fragment=inactive]{visibility:hidden}body[data-bespoke-view=""] .bespoke-marp-parent,body[data-bespoke-view=next] .bespoke-marp-parent{inset:0;position:absolute}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc{view-transition-name:__bespoke_marp_transition_osc__;background:rgba(0,0,0,.65);border-radius:7px;bottom:50px;color:#fff;contain:paint;display:block;font-family:Helvetica,Arial,sans-serif;font-size:16px;left:50%;line-height:0;opacity:1;padding:12px;position:absolute;touch-action:manipulation;transform:translateX(-50%);transition:opacity .2s linear;-webkit-user-select:none;user-select:none;white-space:nowrap;will-change:transform;z-index:1}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>*,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>*{margin-left:6px}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>:first-child,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>:first-child{margin-left:0}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>span,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>span{opacity:.8}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>span[data-bespoke-marp-osc=page],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>span[data-bespoke-marp-osc=page]{display:inline-block;min-width:140px;text-align:center}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev]{height:32px;line-height:32px;width:32px}body[data-bespoke-view=""] .bespoke-marp-parent.bespoke-marp-inactive,body[data-bespoke-view=next] .bespoke-marp-parent.bespoke-marp-inactive{cursor:none}body[data-bespoke-view=""] .bespoke-marp-parent.bespoke-marp-inactive>.bespoke-marp-osc,body[data-bespoke-view=next] .bespoke-marp-parent.bespoke-marp-inactive>.bespoke-marp-osc{opacity:0;pointer-events:none}body[data-bespoke-view=""] svg.bespoke-marp-slide,body[data-bespoke-view=next] svg.bespoke-marp-slide{height:100%;left:0;position:absolute;top:0;width:100%}body[data-bespoke-view=""] .bespoke-progress-parent{background:#222;display:flex;height:5px;width:100%}body[data-bespoke-view=""] .bespoke-progress-parent+.bespoke-marp-parent{top:5px}body[data-bespoke-view=""] .bespoke-progress-parent .bespoke-progress-bar{background:#0288d1;flex:0 0 0;transition:flex-basis .2s cubic-bezier(0,1,1,1)}body[data-bespoke-view=next]{background:transparent}body[data-bespoke-view=presenter]{background:#161616}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container{display:grid;font-family:Helvetica,Arial,sans-serif;grid-template:"current dragbar next" minmax(140px,1fr) "current dragbar note" 2fr "info dragbar note" 3em;grid-template-columns:minmax(3px,var(--bespoke-marp-presenter-split-ratio,66%)) 0 minmax(3px,1fr);height:100%;left:0;position:absolute;top:0;width:100%}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent{grid-area:current;overflow:hidden;position:relative}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent svg.bespoke-marp-slide{height:calc(100% - 40px);left:20px;pointer-events:none;position:absolute;top:20px;-webkit-user-select:none;user-select:none;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent svg.bespoke-marp-slide.bespoke-marp-active{filter:drop-shadow(0 3px 10px rgba(0,0,0,.5))}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container{background:#0288d1;cursor:col-resize;grid-area:dragbar;margin-left:-3px;opacity:0;position:relative;transition:opacity .4s linear .1s;width:6px;z-index:10}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container:hover{opacity:1}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container.active{opacity:1;transition-delay:0s}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container{background:#222;cursor:pointer;display:none;grid-area:next;overflow:hidden;position:relative}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container.active{display:block}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container iframe.bespoke-marp-presenter-next{background:transparent;border:0;display:block;filter:drop-shadow(0 3px 10px rgba(0,0,0,.5));height:calc(100% - 40px);left:20px;pointer-events:none;position:absolute;top:20px;-webkit-user-select:none;user-select:none;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container{background:#222;color:#eee;grid-area:note;position:relative;z-index:1}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button{height:1.5em;line-height:1.5em;width:1.5em}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-wrapper{display:block;inset:0;position:absolute}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-buttons{background:rgba(0,0,0,.65);border-radius:4px;bottom:0;display:flex;gap:4px;margin:12px;opacity:0;padding:6px;pointer-events:none;position:absolute;right:0;transition:opacity .2s linear}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-buttons:focus-within,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-wrapper:focus-within+.bespoke-marp-presenter-note-buttons,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container:hover .bespoke-marp-presenter-note-buttons{opacity:1;pointer-events:auto}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note{word-wrap:break-word;box-sizing:border-box;font-size:calc(1.1em*var(--bespoke-marp-note-font-scale, 1));height:calc(100% - 40px);margin:20px;overflow:auto;padding-right:3px;scrollbar-color:hsla(0,0%,93%,.5) transparent;scrollbar-width:thin;white-space:pre-wrap;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar{width:6px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar-track{background:transparent}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar-thumb{background:hsla(0,0%,93%,.5);border-radius:6px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note:empty{pointer-events:none}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note.active{display:block}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note p:first-child{margin-top:0}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note p:last-child{margin-bottom:0}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container{align-items:center;box-sizing:border-box;color:#eee;display:flex;flex-wrap:nowrap;grid-area:info;justify-content:center;overflow:hidden;padding:0 10px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-time,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer{box-sizing:border-box;display:block;padding:0 10px;white-space:nowrap;width:100%}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button{height:1.5em;line-height:1.5em;width:1.5em}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page{order:2;text-align:center}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page .bespoke-marp-presenter-info-page-text{display:inline-block;min-width:120px;text-align:center}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-time{color:#999;order:1;text-align:left}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer{color:#999;order:3;text-align:right}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer:hover{cursor:pointer}}@media print{.bespoke-marp-presenter-info-container,.bespoke-marp-presenter-next-container,.bespoke-marp-presenter-note-container{display:none}}</style><style>@charset "UTF-8";@import "https://fonts.bunny.net/css?family=Lato:400,900|Roboto+Mono:400,700&display=swap";div#\:\$p>svg>foreignObject>section{width:1280px;height:720px;box-sizing:border-box;overflow:hidden;position:relative;scroll-snap-align:center center}div#\:\$p>svg>foreignObject>section:after{bottom:0;content:attr(data-marpit-pagination);padding:inherit;pointer-events:none;position:absolute;right:0}div#\:\$p>svg>foreignObject>section:not([data-marpit-pagination]):after{display:none}/* Normalization */div#\:\$p>svg>foreignObject>section :is(h1,marp-h1){font-size:2em;margin:0.67em 0}div#\:\$p>svg>foreignObject>section video::-webkit-media-controls{will-change:transform}@page{size:1280px 720px;margin:0}@media print{body,html{background-color:#fff;margin:0;page-break-inside:avoid;break-inside:avoid-page}div#\:\$p>svg>foreignObject>section{page-break-before:always;break-before:page}div#\:\$p>svg>foreignObject>section,div#\:\$p>svg>foreignObject>section *{-webkit-print-color-adjust:exact!important;animation-delay:0s!important;animation-duration:0s!important;color-adjust:exact!important;transition:none!important}div#\:\$p>svg[data-marpit-svg]{display:block;height:100vh;width:100vw}}div#\:\$p>svg>foreignObject>:where(section){container-type:size}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG]{direction:ltr}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG]>svg{overflow:visible;min-height:1px;min-width:1px}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG]>svg a{fill:blue;stroke:blue}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG][display=true]{display:block;text-align:center;margin:1em 0}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG][display=true][width=full]{display:flex}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG][justify=left]{text-align:left}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG][justify=right]{text-align:right}div#\:\$p>svg>foreignObject>section g[data-mml-node=merror]>g{fill:red;stroke:red}div#\:\$p>svg>foreignObject>section g[data-mml-node=merror]>rect[data-background]{fill:yellow;stroke:none}div#\:\$p>svg>foreignObject>section g[data-mml-node=mtable]>line[data-line],div#\:\$p>svg>foreignObject>section svg[data-table]>g>line[data-line]{stroke-width:70px;fill:none}div#\:\$p>svg>foreignObject>section g[data-mml-node=mtable]>rect[data-frame],div#\:\$p>svg>foreignObject>section svg[data-table]>g>rect[data-frame]{stroke-width:70px;fill:none}div#\:\$p>svg>foreignObject>section g[data-mml-node=mtable]>.mjx-dashed,div#\:\$p>svg>foreignObject>section svg[data-table]>g>.mjx-dashed{stroke-dasharray:140}div#\:\$p>svg>foreignObject>section g[data-mml-node=mtable]>.mjx-dotted,div#\:\$p>svg>foreignObject>section svg[data-table]>g>.mjx-dotted{stroke-linecap:round;stroke-dasharray:0,140}div#\:\$p>svg>foreignObject>section g[data-mml-node=mtable]>g>svg{overflow:visible}div#\:\$p>svg>foreignObject>section [jax=SVG] mjx-tool{display:inline-block;position:relative;width:0;height:0}div#\:\$p>svg>foreignObject>section [jax=SVG] mjx-tool>mjx-tip{position:absolute;top:0;left:0}div#\:\$p>svg>foreignObject>section mjx-tool>mjx-tip{display:inline-block;padding:.2em;border:1px solid #888;font-size:70%;background-color:#F8F8F8;color:black;box-shadow:2px 2px 5px #AAAAAA}div#\:\$p>svg>foreignObject>section g[data-mml-node=maction][data-toggle]{cursor:pointer}div#\:\$p>svg>foreignObject>section mjx-status{display:block;position:fixed;left:1em;bottom:1em;min-width:25%;padding:.2em .4em;border:1px solid #888;font-size:90%;background-color:#F8F8F8;color:black}div#\:\$p>svg>foreignObject>section foreignObject[data-mjx-xml]{font-family:initial;line-height:normal;overflow:visible}div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG] path[data-c],div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG] use[data-c]{stroke-width:3}@media print{div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG] path[data-c],div#\:\$p>svg>foreignObject>section mjx-container[jax=SVG] use[data-c]{stroke-width:0}}div#\:\$p>svg>foreignObject>section img[data-marp-twemoji]{background:transparent;height:1em;margin:0 .05em 0 .1em;vertical-align:-.1em;width:1em}
/*!
* Marp / Marpit Gaia theme.
*
* @theme gaia
* @author Yuki Hattori
*
* @auto-scaling true
* @size 16:9 1280px 720px
* @size 4:3 960px 720px
*/div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) code.hljs{display:block;overflow-x:auto;padding:1em}div#\:\$p>svg>foreignObject>section code.hljs{padding:3px 5px}div#\:\$p>svg>foreignObject>section .hljs{background:#000;color:#f8f8f8}div#\:\$p>svg>foreignObject>section .hljs-comment,div#\:\$p>svg>foreignObject>section .hljs-quote{color:#aeaeae;font-style:italic}div#\:\$p>svg>foreignObject>section .hljs-keyword,div#\:\$p>svg>foreignObject>section .hljs-selector-tag,div#\:\$p>svg>foreignObject>section .hljs-type{color:#e28964}div#\:\$p>svg>foreignObject>section .hljs-string{color:#65b042}div#\:\$p>svg>foreignObject>section .hljs-subst{color:#daefa3}div#\:\$p>svg>foreignObject>section .hljs-link,div#\:\$p>svg>foreignObject>section .hljs-regexp{color:#e9c062}div#\:\$p>svg>foreignObject>section .hljs-name,div#\:\$p>svg>foreignObject>section .hljs-section,div#\:\$p>svg>foreignObject>section .hljs-tag,div#\:\$p>svg>foreignObject>section .hljs-title{color:#89bdff}div#\:\$p>svg>foreignObject>section .hljs-class .hljs-title,div#\:\$p>svg>foreignObject>section .hljs-doctag,div#\:\$p>svg>foreignObject>section .hljs-title.class_{text-decoration:underline}div#\:\$p>svg>foreignObject>section .hljs-bullet,div#\:\$p>svg>foreignObject>section .hljs-number,div#\:\$p>svg>foreignObject>section .hljs-symbol{color:#3387cc}div#\:\$p>svg>foreignObject>section .hljs-params,div#\:\$p>svg>foreignObject>section .hljs-template-variable,div#\:\$p>svg>foreignObject>section .hljs-variable{color:#3e87e3}div#\:\$p>svg>foreignObject>section .hljs-attribute{color:#cda869}div#\:\$p>svg>foreignObject>section .hljs-meta{color:#8996a8}div#\:\$p>svg>foreignObject>section .hljs-formula{background-color:#0e2231;color:#f8f8f8;font-style:italic}div#\:\$p>svg>foreignObject>section .hljs-addition{background-color:#253b22;color:#f8f8f8}div#\:\$p>svg>foreignObject>section .hljs-deletion{background-color:#420e09;color:#f8f8f8}div#\:\$p>svg>foreignObject>section .hljs-selector-class{color:#9b703f}div#\:\$p>svg>foreignObject>section .hljs-selector-id{color:#8b98ab}div#\:\$p>svg>foreignObject>section .hljs-emphasis{font-style:italic}div#\:\$p>svg>foreignObject>section .hljs-strong{font-weight:700}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1),div#\:\$p>svg>foreignObject>section :is(h2,marp-h2),div#\:\$p>svg>foreignObject>section :is(h3,marp-h3),div#\:\$p>svg>foreignObject>section :is(h4,marp-h4),div#\:\$p>svg>foreignObject>section :is(h5,marp-h5),div#\:\$p>svg>foreignObject>section :is(h6,marp-h6){margin:.5em 0 0}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1) strong,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2) strong,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3) strong,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4) strong,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5) strong,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6) strong{font-weight:inherit}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h2,marp-h2)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h3,marp-h3)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h4,marp-h4)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h5,marp-h5)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h6,marp-h6)::part(auto-scaling){max-height:580px}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1){font-size:1.8em}div#\:\$p>svg>foreignObject>section :is(h2,marp-h2){font-size:1.5em}div#\:\$p>svg>foreignObject>section :is(h3,marp-h3){font-size:1.3em}div#\:\$p>svg>foreignObject>section :is(h4,marp-h4){font-size:1.1em}div#\:\$p>svg>foreignObject>section :is(h5,marp-h5){font-size:1em}div#\:\$p>svg>foreignObject>section :is(h6,marp-h6){font-size:.9em}div#\:\$p>svg>foreignObject>section blockquote,div#\:\$p>svg>foreignObject>section p{margin:1em 0 0}div#\:\$p>svg>foreignObject>section ol>li,div#\:\$p>svg>foreignObject>section ul>li{margin:.3em 0 0}div#\:\$p>svg>foreignObject>section ol>li>p,div#\:\$p>svg>foreignObject>section ul>li>p{margin:.6em 0 0}div#\:\$p>svg>foreignObject>section code{display:inline-block;font-family:Roboto Mono,monospace;font-size:.8em;letter-spacing:0;margin:-.1em .15em;padding:.1em .2em;vertical-align:baseline}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre){display:block;margin:1em 0 0;overflow:visible}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) code{box-sizing:border-box;font-size:.7em;margin:0;min-width:100%;padding:.5em}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre)::part(auto-scaling){max-height:calc(580px - 1em)}div#\:\$p>svg>foreignObject>section blockquote{margin:1em 0 0;padding:0 1em;position:relative}div#\:\$p>svg>foreignObject>section blockquote:after,div#\:\$p>svg>foreignObject>section blockquote:before{content:"“";display:block;font-family:Times New Roman,serif;font-weight:700;position:absolute}div#\:\$p>svg>foreignObject>section blockquote:before{left:0;top:0}div#\:\$p>svg>foreignObject>section blockquote:after{bottom:0;right:0;transform:rotate(180deg)}div#\:\$p>svg>foreignObject>section blockquote>:first-child{margin-top:0}div#\:\$p>svg>foreignObject>section mark{background:transparent}div#\:\$p>svg>foreignObject>section table{border-collapse:collapse;border-spacing:0;margin:1em 0 0}div#\:\$p>svg>foreignObject>section table td,div#\:\$p>svg>foreignObject>section table th{border-style:solid;border-width:1px;padding:.2em .4em}div#\:\$p>svg>foreignObject>section footer,div#\:\$p>svg>foreignObject>section header,div#\:\$p>svg>foreignObject>section:after{box-sizing:border-box;font-size:66%;height:70px;line-height:50px;overflow:hidden;padding:10px 25px;position:absolute}div#\:\$p>svg>foreignObject>section:after{--marpit-root-font-size:66%}div#\:\$p>svg>foreignObject>section header{top:0}div#\:\$p>svg>foreignObject>section footer,div#\:\$p>svg>foreignObject>section header{left:0;right:0}div#\:\$p>svg>foreignObject>section footer{bottom:0}div#\:\$p>svg>foreignObject>section{word-wrap:break-word;--color-background:#fff8e1;--color-background-stripe:rgba(69,90,100,.1);--color-foreground:#455a64;--color-dimmed:#6a7a7d;--color-highlight:#0288d1;background-color:var(--color-background);background-image:linear-gradient(135deg,hsla(0,0%,53%,0),hsla(0,0%,53%,.02) 50%,hsla(0,0%,100%,0) 0,hsla(0,0%,100%,.05));color:var(--color-foreground);font-family:Lato,Avenir Next,Avenir,Trebuchet MS,Segoe UI,sans-serif;font-size:35px;height:720px;letter-spacing:1.25px;line-height:1.35;padding:70px;width:1280px}div#\:\$p>svg>foreignObject>section{--marpit-root-font-size:35px}div#\:\$p>svg>foreignObject>section:after{bottom:0;font-size:80%;right:0}div#\:\$p>svg>foreignObject>section:after{--marpit-root-font-size:80%}div#\:\$p>svg>foreignObject>section a,div#\:\$p>svg>foreignObject>section mark{color:var(--color-highlight)}div#\:\$p>svg>foreignObject>section code{background:var(--color-dimmed);color:var(--color-background)}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1) strong,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2) strong,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3) strong,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4) strong,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5) strong,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6) strong{color:var(--color-highlight)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre){background:var(--color-foreground)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre)>code{background:transparent}div#\:\$p>svg>foreignObject>section blockquote:after,div#\:\$p>svg>foreignObject>section blockquote:before,div#\:\$p>svg>foreignObject>section footer,div#\:\$p>svg>foreignObject>section header,div#\:\$p>svg>foreignObject>section section:after{color:var(--color-dimmed)}div#\:\$p>svg>foreignObject>section table td,div#\:\$p>svg>foreignObject>section table th{border-color:var(--color-foreground)}div#\:\$p>svg>foreignObject>section table thead th{background:var(--color-foreground);color:var(--color-background)}div#\:\$p>svg>foreignObject>section table tbody>tr:nth-child(odd) td,div#\:\$p>svg>foreignObject>section table tbody>tr:nth-child(odd) th{background:var(--color-background-stripe,transparent)}div#\:\$p>svg>foreignObject>section>:first-child,div#\:\$p>svg>foreignObject>section>header:first-child+*{margin-top:0}div#\:\$p>svg>foreignObject>section:where(.invert){--color-background:#455a64;--color-background-stripe:rgba(255,248,225,.1);--color-foreground:#fff8e1;--color-dimmed:#dad8c8;--color-highlight:#81d4fa}div#\:\$p>svg>foreignObject>section:where(.gaia){--color-background:#0288d1;--color-background-stripe:rgba(255,248,225,.1);--color-foreground:#fff8e1;--color-dimmed:#cce2de;--color-highlight:#81d4fa}div#\:\$p>svg>foreignObject>section:where(.lead){display:flex;flex-flow:column nowrap;justify-content:center}div#\:\$p>svg>foreignObject>section:where(.lead) :is(h1,marp-h1),div#\:\$p>svg>foreignObject>section:where(.lead) :is(h2,marp-h2),div#\:\$p>svg>foreignObject>section:where(.lead) :is(h3,marp-h3),div#\:\$p>svg>foreignObject>section:where(.lead) :is(h4,marp-h4),div#\:\$p>svg>foreignObject>section:where(.lead) :is(h5,marp-h5),div#\:\$p>svg>foreignObject>section:where(.lead) :is(h6,marp-h6){text-align:center}div#\:\$p>svg>foreignObject>section:where(.lead) p{text-align:center}div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>:is(h1,marp-h1),div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>:is(h2,marp-h2),div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>:is(h3,marp-h3),div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>:is(h4,marp-h4),div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>:is(h5,marp-h5),div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>:is(h6,marp-h6),div#\:\$p>svg>foreignObject>section:where(.lead) blockquote>p{text-align:left}div#\:\$p>svg>foreignObject>section:where(.lead) ol>li>p,div#\:\$p>svg>foreignObject>section:where(.lead) ul>li>p{text-align:left}div#\:\$p>svg>foreignObject>section:where(.lead) table{margin-left:auto;margin-right:auto}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}</style></head><body><div class="bespoke-marp-osc"><button data-bespoke-marp-osc="prev" tabindex="-1" title="Previous slide">Previous slide</button><span data-bespoke-marp-osc="page"></span><button data-bespoke-marp-osc="next" tabindex="-1" title="Next slide">Next slide</button><button data-bespoke-marp-osc="fullscreen" tabindex="-1" title="Toggle fullscreen (f)">Toggle fullscreen</button><button data-bespoke-marp-osc="presenter" tabindex="-1" title="Open presenter view (p)">Open presenter view</button></div><div id=":$p"><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-class="lead" data-theme="gaia" lang="en-CA" class="lead" data-marpit-pagination="1" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--class:lead;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;--marpit-advanced-background-split:40%;" data-marpit-pagination-total="48" data-marpit-advanced-background="background" data-marpit-advanced-background-split="left"><div data-marpit-advanced-background-container="true" data-marpit-advanced-background-direction="horizontal"><figure style="background-image:url("images/Cardano-RGB_Logo-Stack-Blue.png");background-size:80%;"></figure></div></section></foreignObject><foreignObject width="60%" height="720" x="40%"><section id="1" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-class="lead" data-theme="gaia" lang="en-CA" class="lead" data-marpit-pagination="1" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--class:lead;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;--marpit-advanced-background-split:40%;" data-marpit-pagination-total="48" data-marpit-advanced-background="content" data-marpit-advanced-background-split="left">
<h1 id="smart-contracts-in-cardano"><strong>Smart Contracts in Cardano</strong></h1>
<p>Claudio Hermida<br />
<a href="mailto:[email protected]">[email protected]</a><br />
<a href="https://www.linkedin.com/in/claudiohermida/">https://www.linkedin.com/in/claudiohermida/</a></p>
</section>
</foreignObject><foreignObject width="1280" height="720" data-marpit-advanced-background="pseudo"><section data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-class="lead" data-theme="gaia" lang="en-CA" class="lead" data-marpit-pagination="1" style="" data-marpit-pagination-total="48" data-marpit-advanced-background="pseudo" data-marpit-advanced-background-split="left"></section></foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="2" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="2" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h1 id="synopsis">Synopsis</h1>
<ul>
<li>State in functional programming ~~~> eUTXO model</li>
<li>Specification of contract methods ~~~~> Validator</li>
<li>What is a smart contract in Cardano?</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="3" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="3" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-java"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
pragma solidity ^<span class="hljs-number">0.8</span><span class="hljs-number">.0</span>;
contract VestingContract {
address <span class="hljs-keyword">public</span> beneficiary;
address <span class="hljs-keyword">public</span> benefactor;
uint <span class="hljs-keyword">public</span> amount;
uint <span class="hljs-keyword">public</span> deadline;
bool <span class="hljs-keyword">public</span> consumed;
constructor(
address _beneficiary,
uint _deadline
) payable {
beneficiary = _beneficiary;
benefactor = msg.sender;
amount = msg.value;
deadline = _deadline;
consumed = <span class="hljs-literal">false</span>;
}
function <span class="hljs-title function_">claim</span><span class="hljs-params">()</span> <span class="hljs-keyword">public</span> {
require(msg.sender == beneficiary, <span class="hljs-string">"Only the beneficiary can call this function."</span>);
require(block.timestamp >= deadline, <span class="hljs-string">"Deadline has not passed yet."</span>);
require(!consumed, <span class="hljs-string">"Funds have already been released."</span>);
consumed = <span class="hljs-literal">true</span>;
payable(beneficiary).transfer(amount);
}
function <span class="hljs-title function_">cancel</span><span class="hljs-params">()</span> <span class="hljs-keyword">public</span> {
require(msg.sender == benefactor, <span class="hljs-string">"Only the benefactor can call this function."</span>);
require(block.timestamp < deadline, <span class="hljs-string">"Deadline has already passed."</span>);
require(!consumed, <span class="hljs-string">"Funds have already been released."</span>);
consumed = <span class="hljs-literal">true</span>;
payable(benefactor).transfer(amount);
}
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="4" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="4" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="account-based-blockchain-model">Account-based blockchain model</h2>
<div style="text-align: center;">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>Account-Ledger = Map Address (Value,State)
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>smart contract = object ~~~> (state{balance, ...}, methods)
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>tx-method : Account-Ledger -> Account-Ledger
</code></pre>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="5" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="5" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="functional-programming">Functional Programming</h2>
<ul>
<li>
<p><strong>Stateless</strong>: functions are evaluated, reading inputs and producing outputs without manipulating any state or storage variables.</p>
</li>
<li>
<p><strong>Referentially transparent</strong>: statalessness enables <em>equational reasoning</em>, allowing to replace equals by equals anywhere.</p>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="6" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="6" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="handling-state">Handling state</h3>
<p>Imperative programming: a <strong>variable</strong> is an <em>object</em> with two methods: <code>read</code> and <code>update</code></p>
<p>To emulate such (storage) variable in a stateless fashion, we must emulate these two operations.</p>
<ul>
<li><code>read</code>: we must provide the contents of the variable as an additional <em>input</em></li>
<li><code>update</code>: we must produce the updated content as an additional <em>output</em> so that it can be used in later computation.</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="7" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="7" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"> reverse :: <span class="hljs-type">List</span> <span class="hljs-type">A</span> -> <span class="hljs-type">List</span> <span class="hljs-type">A</span>
reverse l =
<span class="hljs-keyword">let</span>
var accumulator:: <span class="hljs-type">List</span> <span class="hljs-type">A</span>
reverseWithAccumulator :: <span class="hljs-type">List</span> <span class="hljs-type">A</span> -> <span class="hljs-type">List</span> <span class="hljs-type">A</span>
reverseWithAccumulator <span class="hljs-type">EmptyList</span> = accumulator <span class="hljs-comment">-- read state</span>
reverseWithAccumulator a:l =
accumulator := a: accumulator; <span class="hljs-comment">-- update state</span>
reverseWithAccumulator l
<span class="hljs-keyword">in</span>
accumulator := <span class="hljs-type">EmptyList</span>; <span class="hljs-comment">-- initialize state</span>
reverseWithAccumulator l
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="8" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="8" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"> newType <span class="hljs-type">State</span> = <span class="hljs-type">List</span> <span class="hljs-type">A</span>
reverse l =
<span class="hljs-keyword">let</span>
reverseWithAccumulator' :: (<span class="hljs-type">List</span> <span class="hljs-type">A</span>,<span class="hljs-type">State</span>) -> (<span class="hljs-type">List</span> <span class="hljs-type">A</span>, <span class="hljs-type">State</span>)
reverseWithAccumulator'(<span class="hljs-type">EmptyList</span>,acc) = (acc,acc)
<span class="hljs-comment">-- read state => no change on second component</span>
reverseWithAccumulator' (a:l, acc) =
reverseWithAccumulator' (l, a:acc)
<span class="hljs-comment">-- update state => modify second component </span>
<span class="hljs-keyword">in</span>
fst $ reverseWithAccumulator (l,<span class="hljs-type">EmptyList</span>)
<span class="hljs-comment">-- supply initial state, </span>
<span class="hljs-comment">-- select first component to get result </span>
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="9" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="9" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<ul>
<li><strong>functional transactions</strong> should have additional input/output to account for state</li>
<li>state is associated to an <strong>address</strong></li>
<li>state split <strong>(value, storage)</strong></li>
</ul>
<div style="text-align: center; font-size: 30px; margin-top: 20px;">
∎ the additional input/output representing state is an <em>eutxo</em>
</div>
<table>
<thead>
<tr>
<th style="text-align:left"><strong>eutxo =</strong></th>
<th style="text-align:left"></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><strong>address</strong></td>
<td style="text-align:left">target address where the utxo is held/locked</td>
</tr>
<tr>
<td style="text-align:left"><strong>value</strong></td>
<td style="text-align:left">value locked in this utxo</td>
</tr>
<tr>
<td style="text-align:left"><strong>datum</strong></td>
<td style="text-align:left">local state</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="10" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="10" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="eutxo-blockchain-model">EUTXO blockchain model</h2>
<div style="text-align: center;">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>eUTXO-Ledger = {eutxo}
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>tx: inputs |-> outputs
tx-effect : eUTXO-Ledger -> eUTXO-Ledger
tx-effect (ledger) = (legder \ inputs) + outputs
</code></pre>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="11" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="11" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="sharded-state">Sharded state</h2>
<p>eutxos in Cardano are <em><strong>resources</strong></em>: once <em>produced</em> by a transaction can be <em>consumed</em> or <em>spent</em> once, <em>and only once</em>, by another transaction (as inputs).</p>
<p>Cardano allows multiple etuxos to be held at a single address, thereby effectively splitting or <em>sharding</em> the local state at an address.</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="12" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="12" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>Immediate consequences of the resource nature of eutxos and sharding:</p>
<ul>
<li>efficiency: a transaction can select very precisely those utxos which hold the piece of state to consume, and transactions consuming different utxos can be computed/validated in parallel.</li>
<li><em>non-interference</em>: an eutxo can only be used by a single transaction, so different transactions cannot operate over the same piece of state<br />
==> <em>predictability</em> of the outcome of transactions</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="13" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="13" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="transactions">Transactions</h2>
<p>Most <em><strong>radical difference</strong></em> between the two models</p>
<p>In account-based model : transactions <strong>excuted on-chain</strong></p>
<p>In Cardano</p>
<br />
<div style="border: 1px solid #999; padding: 10px; background-color: lightblue;"><strong>a transaction is computed off-chain and validated on-chain</strong>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="14" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="14" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="validators">Validators</h2>
<p>For on-chain validation, Cardano introduces</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"><span class="hljs-title">validator</span> :: <span class="hljs-type">Datum</span> -> <span class="hljs-type">Redeemer</span> -> <span class="hljs-type">ScriptContext</span> -> <span class="hljs-type">Bool</span>
</code></pre>
<p>to validate/allow the consumption of an <em>input</em> in a transaction.</p>
<ul>
<li><strong>Datum</strong>: is the datum of the input eutxo</li>
<li><strong>Redeemer</strong>: is the action/method whose execution is validated</li>
<li><strong>ScriptContext</strong>: indicates <em>purpose</em> of the script being executed (spending an eutxo, minting, staking, etc) and the <em>transaction context</em> (inputs, outputs, signatures).</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="15" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="15" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="input-eutxo">Input eutxo</h3>
<ul>
<li>eutxo held at a <em><strong>PublicKeyHash address</strong></em>: unlocks with <em>private key signature</em></li>
<li>eutxo held at a <em><strong>script address</strong></em>: unlocks by evaluating successfully the validator associated with the address:<br />
<code>script address ~ hash(validator code)</code></li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="16" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="16" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="separation-of-building-and-execution-of-tx">Separation of building and execution of tx:</h3>
<ul>
<li><strong>tx build</strong>: specify its inputs (eutxos) and its would-be outputs (eutxos). Here, eutxos are treated as mere <em>data</em>, not resources, since we are off chain. We also indicate the signer of the transaction, which pays for the <em>transaction fees</em> (supplied as one of the inputs eutxo). In order to specify outputs, some computation might take place from the given inputs (method execution); this is the <em>off-chain (pre)computation</em> of a transaction. We produce a so-called <em>transaction body</em>,</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="17" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="17" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<ul>
<li><strong>tx execute</strong>
<ul>
<li>
<p>we <em>sign and submit</em> the transaction body for <em>validation</em>: each input held at a script triggers the execution of the corresponding validator and each input held at a pkh is signature-verified (<em>on-chain</em>)</p>
</li>
<li>
<p>if all inputs validate and the transaction satisfies preservation-of-values (that is, inputs and outputs are balanced), the transaction submission is <em>successful</em> and the ledger gets updated: inputs are spent (eliminated) and outputs are created (added) (<em><strong>data ~~> resources</strong></em>) Otherwise, the transaction <em>fails</em> and has no effect on the ledger.</p>
</li>
</ul>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="18" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="18" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<table>
<thead>
<tr>
<th style="text-align:left"><strong>Account based</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">- Transaction signed and submitted to a node</td>
</tr>
<tr>
<td style="text-align:left">- Changes to the ledger effected <strong>on-chain</strong> by means of state updates of the accounts involved in the transaction</td>
</tr>
<tr>
<td style="text-align:left">- Protected execution <strong>on-chain</strong>: if anything fails, it <em>reverts</em> to initial state of the ledger before transaction execution started, using a snapshot of the state taken at the start of execution</td>
</tr>
<tr>
<td style="text-align:left">- <strong>Validation</strong> mixed with <strong>execution</strong>, by means of <strong>require</strong> statements</td>
</tr>
<tr>
<td style="text-align:left">- Access to accounts during execution could be unrestricted (Ethereum) or restricted to pre-specified ones at transaction-build time (Algorand)</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="19" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="19" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<table>
<thead>
<tr>
<th style="text-align:left"><strong>eUTXO based</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">- Transaction signed and submitted to a node</td>
</tr>
<tr>
<td style="text-align:left">- Outputs of a transaction <strong>precomputed off-chain;</strong></td>
</tr>
<tr>
<td style="text-align:left">- (Inputs, Outputs) fed as transaction context to cardano-node at transaction-build time</td>
</tr>
<tr>
<td style="text-align:left">- (Inputs, outputs) are subject to <strong>validation</strong> in the node (<strong>on-chain</strong>) before effecting a change on the distributed ledger</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="20" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="20" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h1 id="part-ii">Part II</h1>
<h2 id="specification-in-the-small-pre--and-postconditions">Specification in the small: pre- and postconditions</h2>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="21" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="21" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>How do we specify a sorting function?<br />
<code>sortIncOrder: List(Int) -> List(Int)</code></p>
<ul>
<li>Output must be increasingly ordered:<pre is="marp-pre" data-auto-scaling="downscale-only"><code> Ordered:: List(Int) -> Bool
Ordered [] = True
Ordered [n] = True
Ordered n:(m:l) = n \leq m && Ordered(m:l)
forall l:List(Int). Ordered(sortIncOrder(l))
</code></pre>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="22" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="22" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>How do we specify a sorting function?<br />
<code>sortIncOrder: List(Int) -> List(Int)</code></p>
<ul>
<li>
<p>Output must be increasingly ordered:</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>
forall l:List(Int). Ordered(sortIncOrder(l))
</code></pre>
</li>
<li>
<p>output should be a permutation or rearrangement of input</p>
</li>
</ul>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code> isPermutation:: List(Int) -> List(Int) -> Bool
isPermutation [] [] = True
isPermutation (h:t) l = (h `elem` l) && isPermutation t (l \ h)
forall l: List(Int). isPermutation(l,sortIncOrder(l))
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="23" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="23" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>How do we specify a sorting function?<br />
<code>sortIncOrder: List(Int) -> List(Int)</code></p>
<ul>
<li>Output must be increasingly ordered:</li>
</ul>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>
forall l:List(Int). Ordered(sortIncOrder(l))
</code></pre>
<ul>
<li>output should be a permutation or rearrangement of input</li>
</ul>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>
forall l: List(Int). isPermutation(l,sortIncOrder(l))
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>Spec(sortIncOrder)= forall l: List(Int).Ordered(sortIncOrder(l)) && isPermutation(l,sortIncOrder(l))
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="24" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="24" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>In general, for a function <code>f: I -> O</code>, we want to specify its <em><strong>extensional behaviour</strong></em>: given input <code>i:I</code> satisfying a <em><strong>precondition</strong></em> <code>Pre(i)</code> its output <code>fi:O</code> should satisfy the <em><strong>postcondition</strong></em> <code>Post(i,fi)</code>:</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>forall i:I. Pre(i) => Post(i,fi)
</code></pre>
<p>What happens when <code>Pre(i)</code> does not hold? In the context of blockchains, we want that if the precondition for a method is not satisfied, its specification fails: <code>!Pre(i) => false</code></p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>Spec(f) = forall i:I. (Pre(i) => Post(i,fi)) && (!Pre(i) => false)
= forall i:I. Pre(i) && Post(i,fi)
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="25" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="25" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="example-from-aiken-library">Example (from Aiken library)</h3>
<p><code>from_asset_list(xs: List<(PolicyId, List<(AssetName, Int)>)> -> Value</code></p>
<p>Promote an arbitrary list of assets into a Value. This function fails if</p>
<ul>
<li>there’s any duplicate amongst PolicyId; <code>nodup $ map fst xs</code></li>
<li>there’s any duplicate amongst AssetName; <code>all $ map (nodup $ map fst) xs</code></li>
<li>the AssetName aren’t sorted in ascending lexicographic order; <code>all (Ordered map fst)</code></li>
<li>or any asset quantity is null. <code>none $ concat (map (map (\(assetName,qty) -> qty == 0)))</code></li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="26" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="26" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>This function is meant to turn arbitrary user-defined Data into safe Value, while checking for internal invariants. The result should be the addition of the values represented by each individual entry <code>(PolicyId,AssetName,Int)</code>, which we write as <code>SingletonValue</code>. So, the <em><strong>Postcondition</strong></em> is:</p>
<p><code>from_asset_list (xs) == foldr <> mempty $ concat (map (\pid -> map (\(an,qty) -> SingletonValue(pid,an,qty))) xs</code></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="27" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="27" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="validators-and-contract-methods">Validators and contract methods</h3>
<p>How are we to use validators in the context of implementing smart contracts? The answer is:</p>
<h2 id="a-validator-specifies-the-pre--and-post-condition-of-a-contract-method"><em><strong>A validator specifies the pre- and post-condition of a contract method</strong></em></h2>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="28" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="28" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-javascript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">claim</span>(<span class="hljs-params"></span>) public {
<span class="hljs-built_in">require</span>(msg.<span class="hljs-property">sender</span> == beneficiary, <span class="hljs-string">"Only the beneficiary can call this function."</span>);
<span class="hljs-built_in">require</span>(block.<span class="hljs-property">timestamp</span> >= deadline, <span class="hljs-string">"Deadline has not passed yet."</span>);
<span class="hljs-built_in">require</span>(!consumed, <span class="hljs-string">"Funds have already been released."</span>);
consumed = <span class="hljs-literal">true</span>;
<span class="hljs-title function_">payable</span>(beneficiary).<span class="hljs-title function_">transfer</span>(amount);
}
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-javascript"><span class="hljs-title class_">Pre</span> = (msg.<span class="hljs-property">sender</span> == beneficiary) -- signed by beneficiary
&& (block.<span class="hljs-property">timestamp</span> >= deadline) -- deadline reached
&& [!consumed] -- amount not withdrawn yet
&& (<span class="hljs-title function_">address</span>(<span class="hljs-variable language_">this</span>).<span class="hljs-property">balance</span> >= amount) -- enough funds to transfer
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-javascript"><span class="hljs-title class_">Post</span> =
(<span class="hljs-title function_">address</span>(<span class="hljs-variable language_">this</span>).<span class="hljs-title function_">balance</span>()_after == <span class="hljs-title function_">address</span>(<span class="hljs-variable language_">this</span>).<span class="hljs-title function_">balance</span>()_before - amount ) &&
(beneficiary.<span class="hljs-title function_">balance</span>()_after == beneficiary.<span class="hljs-title function_">balance</span>()_before + amount)
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="29" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="29" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">VestingDatum</span> = <span class="hljs-type">VestingDatum</span></span>
{ beneficiary :: <span class="hljs-type">PubKeyHash</span>
, benefactor: <span class="hljs-type">PubKeyHash</span>
, deadline :: <span class="hljs-type">POSIXTime</span>
, amount: <span class="hljs-type">Integer</span>
}
<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">VestingRedeemer</span> = <span class="hljs-type">Claim</span> | <span class="hljs-type">Cancel</span></span>
<span class="hljs-title">mkVestingValidator</span> :: <span class="hljs-type">VestingDatum</span> -> <span class="hljs-type">VestingRedeemer</span> -> <span class="hljs-type">ScriptContext</span> -> <span class="hljs-type">Bool</span>
<span class="hljs-title">mkVestingValidator</span> dat <span class="hljs-type">Claim</span> ctx =
<span class="hljs-keyword">let</span>
<span class="hljs-comment">-- PRECONDITIONS</span>
signedByBeneficiary = txSignedBy info $ beneficiary dat
deadlineReached = contains (from $ deadline dat) $ txInfoValidRange info
<span class="hljs-comment">-- POSTCONDITION</span>
amountPaidToBeneficiary = ( (getSignerAdaAmount info beneficiary) == amount dat)
<span class="hljs-keyword">in</span>
traceIfFalse <span class="hljs-string">"beneficiary's signature missing"</span> signedByBeneficiary &&
traceIfFalse <span class="hljs-string">"deadline not reached"</span> deadlineReached &&
traceIfFalse <span class="hljs-string">"wrong amount paid"</span> amountPaidToBeneficiary
<span class="hljs-keyword">where</span>
info :: <span class="hljs-type">TxInfo</span>
info = scriptContextTxInfo ctx
<span class="hljs-comment">-- extract the integer denominator (lovelace) of the Ada value of the outputs sent to a given address:</span>
getSignerAdaAmount :: <span class="hljs-type">TxInfo</span> -> <span class="hljs-type">PubKeyHash</span> -><span class="hljs-type">Integer</span>
getSignerAdaAmount info addr = valueOf (valuePaidTo info addr) adaSymbol adaToken
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="30" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="30" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<ul>
<li>In the account-based model, since the contract methods operate on the whole state of the contract, we must use a boolean flag <code>consumed</code> to indicate whether the portion of the contract balance which is vested has already been consumed or not. This effectively turns that portion of the balance (state) into a <em>resource managed by the flag</em>: it is turned off when created and turned on when consumed or spent. In the validators, the resource-nature of eutxos makes this flag unnecessary: an input eutxo is either available or not, the node validating a transaction checks that for us.</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="31" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="31" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<ul>
<li>Conversely, we might notice that in the account-based model, the transfer of <code>amount</code> to <code>beneficiary/benefactor</code> is achieved by invoking a system-defined method <code>payable(beneficiary).transfer(amount)</code> which has its own (prespecified) pre and postconditions.</li>
<li>The validator, on the other hand, cannot know whether the funds unlocked will satisfy the transfer postcondition; we only know that the value in the input will be consumed, but we must ensure that it reaches the beneficiary/benefactor, hence the additional check <code>amountPaidToBeneficiary</code></li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="32" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="32" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="transaction-specification">Transaction specification</h2>
<img src="images/tx.png" alt="Claim diagram" style="width: 20%; height: auto;" />
<p><em><strong>SPEC(tx) = validator<sub>1</sub> (datum(in<sub>1</sub>), redeemer<sub>1</sub>, sc<sub>1</sub>) ∧ … ∧ validator<sub>n</sub>(datum(in<sub>n</sub>),redeemer<sub>n</sub>, sc<sub>n</sub>) ∧ Preservation-of-Value(sc)</strong></em></p>
<p><em><strong>Preservation-of-Value(scriptContext)</strong></em> = “sum of values of inputs + value minted = sum of values of outpus + tx fee”</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="33" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="33" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="transaction-schema">Transaction Schema</h2>
<p>We call <strong>transaction schema</strong> any function that produces a transaction body <code>TxBody</code> as output, that is</p>
<h2 id="transaction-schema--parameterized-transaction-body"><em><strong>Transaction Schema = parameterized Transaction Body</strong></em></h2>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="34" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="34" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<img src="images/Claim-diagram.png" alt="Claim diagram" style="width: 70%; height: auto;" />
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="35" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="35" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="building-transaction-schema">Building Transaction schema</h3>
<p>We use Atlas (<a href="https://atlas-app.io/">https://atlas-app.io/</a>) to maintain the functional programming theme, but there are several alternative frameworks for transaction building.</p>
<ul>
<li>
<p>modular building of transactions via <em>skeletons</em>: add an input, an output, a validity range, a signatory, etc. ~~><code>GYTxSkeleton</code> monad with a monoid structure.</p>
</li>
<li>
<p>skeleton passed to a <em>transaction builder</em> (<code>gyTxBuilder</code> in <code>GYTxMonadNode</code>), along with relevant parameters for interacting with a node: <em>network id</em>, <em>data providers</em>, etc.</p>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="36" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="36" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<ul>
<li>transaction builder will attempt to complete the transaction body using a coin selection algorithm to select relevant fee and collateral input eutxos, and well as balancing the transaction by sending unspent input value to a change address.</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="37" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="37" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"><span class="hljs-comment">-- implement business logic of Claim method</span>
<span class="hljs-title">claimVestingBeneficiary</span> :: <span class="hljs-type">GYTxQueryMonad</span> m => <span class="hljs-type">GYTxInTxOutRef</span> -> m (<span class="hljs-type">GYTxSkeleton</span> '<span class="hljs-type">PlutusV2</span>)
<span class="hljs-title">claimVestingBeneficiary</span> oref = <span class="hljs-keyword">do</span>
slot <- currentSlot
beneficiary <- extractBeneficiary oref <span class="hljs-comment">-- gets beneficiary from inline datum</span>
return $ isInvalidBefore slot <> <span class="hljs-comment">-- sets up the validity interval</span>
mustBeSignedBy beneficiary <> <span class="hljs-comment">-- adds a required signatory</span>
mustHaveInput <span class="hljs-type">GYTxIn</span> <span class="hljs-comment">-- adds input</span>
{ gyTxInTxOutRef = oref
, gyTxInWitness = <span class="hljs-type">GYTxInWitnessScript</span> <span class="hljs-comment">-- specify parameters to consume input eutxo: </span>
(<span class="hljs-type">GYInScript</span> $ vestingValidatorScript) <span class="hljs-comment">-- script</span>
<span class="hljs-type">Nothing</span> <span class="hljs-comment">-- inline datum</span>
<span class="hljs-type">Claim</span> <span class="hljs-comment">-- redeemer</span>
} <>
mustHaveOutput $ <span class="hljs-type">GYTxOut</span> <span class="hljs-comment">-- adds output</span>
{ gyTxOutAddress = beneficiary <span class="hljs-comment">-- target address</span>
, gyTxOutValue = getValueFromTxOutRef oref <span class="hljs-comment">-- amount to transfer</span>
, gyTxOutDatum = <span class="hljs-type">Nothing</span> <span class="hljs-comment">-- no datum</span>
, gyTxOutRefS = <span class="hljs-type">Nothing</span> <span class="hljs-comment">-- no reference script</span>
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="38" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="38" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"><span class="hljs-comment">-- build transaction to Claim vested amount:</span>
beneficiary <- extractBeneficiary oref
txBody <- runGYTxMonadNode networkId providers beneficiary collateral $
claimVestingBeneficiary oref
tid <- gySubmitTx providers $ signTx txBody [skey]
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="39" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="39" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="smart-contracts-in-cardano-1">Smart Contracts in Cardano</h2>
<p><em><strong>Cardano smart contract =<br />
set of transaction schemas and associated validators</strong></em></p>
<ul>
<li>schemas and validators must ‘share’ <code>Datum</code> and <code>Redeemer</code></li>
<li><code>Datum</code>: <em>product</em> of components of local state of the contract (besides its <code>Value</code>):</li>
</ul>
<div style="border: 1px solid #999; padding: 10px;
font-size: 1.5rem; background-color: lightgray;">
data Datum = Datum { var<sub>1</sub> :: Type<sub>1</sub> , var<sub>2</sub> :: Type<sub>2</sub> , … , var<sub>n</sub> :: Type<sub>n</sub> }
</div>
<ul>
<li><code>Redeemer</code>: <em>sum</em> type; alternatives <~~> methods signatures:</li>
</ul>
<div style="border: 1px solid #999; padding: 10px;
font-size: 1.5rem; background-color: lightgray;">
data Redeemer = method<sub>1</sub> Type<sub>11</sub> … Type<sub>1p</sub> | … | method<sub>m</sub> Type<sub>m1</sub> … Type<sub>mq</sub>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="40" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="40" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<p>The correspondence of “methods” to redeemer cases need not be 1-1: some methods interact with various ‘pieces of state’ which will be represented by several inputs, each to be consumed by a possibly different redeemer. And conversely, a complex transaction involving several inputs implements a business logic that may correspond to a combination of several “methods” in the OOP sense.</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="41" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="41" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="deploying-contracts">Deploying contracts</h2>
<p>In account-based models, a smart contract is an <em><strong>object</strong></em> or <em><strong>instance</strong></em> of a class.</p>
<ul>
<li><em><strong>Deploying</strong></em> a contract amounts to <em>creating</em> a new instance of the class and assigning it to an account address, which will hold the <em>local state</em> of that object/instance.</li>
<li>The initial state is set upon deployment invoking the <em>constructor</em> method in the contract.</li>
<li>one may deploy <em>several</em> instances of the same contract class, each residing at a different account address.</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="42" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="42" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="deploying-cardano-smart-contracts">Deploying Cardano smart contracts</h3>
<ol>
<li>Generate a <em><strong>script address</strong></em> that is going to hold the local state of the contract via eutxos. It is generated by hashing the Plutus validator script.</li>
<li>Build and submit a transaction with an output (eutxo) trageted at the script address, encoding the <em>intial state</em> of the instance in its <em>Value</em> and <em>Datum</em>. This is analogous to executing the <em>constructor</em> method of the contract.</li>
</ol>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="43" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="43" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"><span class="hljs-comment">-- set up initial state to deploy Vesting contract</span>
<span class="hljs-title">placeVesting</span> :: <span class="hljs-type">GYTxQueryMonad</span> m => <span class="hljs-type">GYPubKeyHash</span> -> <span class="hljs-type">GYPubKeyHash</span> -> <span class="hljs-type">GYTime</span> -> <span class="hljs-type">GYValue</span> -> m (<span class="hljs-type">GYTxSkeleton</span> '<span class="hljs-type">PlutusV2</span>)
<span class="hljs-title">placeVesting</span> benefactor beneficiary deadline valueAmount =
return $ mustHaveOutput $ <span class="hljs-type">GYTxOut</span> <span class="hljs-comment">--specify an eutxo with inline datum</span>
{ gyTxOutAddress = vestingAddress
, gyTxOutValue = valueAmount
, gyTxOutDatum = <span class="hljs-type">Just</span> (datumFromPlutusData $
<span class="hljs-type">VestingDatum</span> benefactor beneficiary
{timeToPlutus deadline) (toLovelace $ fromValue valueAmount)
, <span class="hljs-type">GYTxOutUseInlineDatum</span>)
, gyTxOutRefS = <span class="hljs-type">Nothing</span>
}
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"><span class="hljs-comment">-- build initial transaction to deploy contract:</span>
txBody <- runGYTxMonadNode networkId providers sender collateral $
placeVesting
benefactor beneficiary (timeFromPlutus deadline)
(valueFromLovelace $ toInteger amount)
tid <- gySubmitTx providers $ signTx txBody [skey]
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="44" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="44" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="declaration-of-a-contract">Declaration of a contract</h3>
<p>In the acccount-based model <em>declaring</em> a contract amounts to storing its code <em>on-chain</em> so it can be referred to by other contracts as a library, as well as avoiding storing the contract code in each instance.</p>
<p>In Cardano, we build an eutxo with the validator <em><strong>reference script</strong></em> (CIP-33), so that the ‘contract class’ is on-chain and we can refer to it for execution.</p>
<p>The reason for putting the code in an eutxo is that the very simple model of ledger in Cardano implies that if we want to associate any information to an address, we must build an eutxo targetted at that address, containing that info.</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="45" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="45" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h3 id="contract-instances">Contract instances</h3>
<p>In order to accommodate the possibility of several instances of the same contract coexising in the blockchain, we <em>mint an NFT</em> which is incorporated in the value of the initializing eutxo and passed along as we update contract state via new eutxos.</p>
<p>Such NFT uniquely identifies the instance; it is the actual counterpart of the <em>account address</em> of the contract object:</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="46" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="46" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<table>
<thead>
<tr>
<th>Account based</th>
<th>eUTXO Based</th>
</tr>
</thead>
<tbody>
<tr>
<td>contract (class)</td>
<td>validator script + transaction schema</td>
</tr>
<tr>
<td>contract (object)</td>
<td>initial-state-eutxo @ script address</td>
</tr>
<tr>
<td>contract account address</td>
<td>contract token (NFT)</td>
</tr>
<tr>
<td>declaration</td>
<td>reference script eutxo</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="47" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="47" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<h2 id="the-state-monad">The State Monad</h2>
<p><mjx-container class="MathJax" jax="SVG" display="true" style="margin: 0;"><svg style="vertical-align: -0.791ex; display: block; width: 100%; height: auto; max-height: 2.713ex;" xmlns="http://www.w3.org/2000/svg" width="39.336ex" height="2.713ex" role="img" focusable="false" viewBox="0 -849.5 17386.7 1199"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M202 -349V850H394V810H242V-309H394V-349H202Z"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(417,0)"><g data-mml-node="mo"><path data-c="28" d="M74 250Q74 564 240 733L257 750H333L323 739Q167 573 167 250T323 -239L333 -250H257L240 -233Q74 -63 74 250Z"></path></g><g data-mml-node="mi" transform="translate(389,0)"><path data-c="1D5A0" d="M183 181Q183 179 152 91T118 0H28L154 346L280 693Q281 694 333 694H385L511 349Q636 4 638 2Q638 0 584 0H530L464 183H184L183 181ZM324 606Q319 578 292 492T238 332T210 256Q210 254 324 254T438 255L429 281L419 308Q409 336 395 378T365 465T339 551T324 611V606Z"></path></g><g data-mml-node="mo" transform="translate(1278.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z"></path></g><g data-mml-node="mi" transform="translate(2278.4,0)"><path data-c="1D5A1" d="M425 363Q438 363 465 353T526 324T585 270T610 192Q610 132 561 78T426 7Q404 2 387 2T240 0H90V694H227Q373 693 396 689Q484 673 533 623T583 517Q583 494 574 473T551 437T520 409T487 388T456 374T433 366L425 363ZM490 516Q490 527 485 539T467 568T423 599T347 621Q340 622 262 623H188V399H261H286Q432 399 478 475Q490 496 490 516ZM514 190Q514 245 462 280T343 322Q336 323 259 323H188V71H274Q365 72 388 77Q445 88 479 121T514 190Z"></path></g><g data-mml-node="mo" transform="translate(2945.4,0)"><path data-c="29" d="M221 -73T221 250T65 739L55 750H131L148 733Q314 567 314 250T148 -233L131 -250H55L65 -239Q221 -73 221 250Z"></path></g><g data-mml-node="mo" transform="translate(3612.2,0)"><path data-c="27F6" d="M84 237T84 250T98 270H1444Q1328 357 1301 493Q1301 494 1301 496T1300 499Q1300 511 1317 511H1320Q1329 511 1332 510T1338 506T1341 497T1344 481T1352 456Q1374 389 1425 336T1544 261Q1553 258 1553 250Q1553 244 1548 241T1524 231T1486 212Q1445 186 1415 152T1370 85T1349 35T1341 4Q1339 -6 1336 -8T1320 -11Q1300 -11 1300 0Q1300 7 1305 25Q1337 151 1444 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(5528,0)"><path data-c="1D5A2" d="M59 347Q59 440 100 521T218 654T392 705Q473 705 550 680Q577 670 577 667Q576 666 572 642T564 595T559 571Q515 601 479 613T392 626Q300 626 232 549T164 347Q164 231 229 150T397 68Q453 68 489 80T568 120L581 129L582 110Q584 91 585 71T587 46Q580 40 566 31T502 5T396 -11Q296 -11 218 41T99 174T59 347Z"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(6584,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5D" d="M22 810V850H214V-349H22V-309H174V810H22Z"></path></g></g><g data-mml-node="mo" transform="translate(7278.8,0)"><path data-c="27FA" d="M1438 514Q1438 525 1454 525Q1459 525 1462 525T1467 525T1471 524T1473 523T1475 520T1477 517T1480 512Q1517 438 1578 381T1689 300T1785 263Q1802 258 1802 250T1793 239T1756 228T1698 204Q1554 134 1480 -12Q1476 -21 1473 -22T1458 -24Q1438 -24 1438 -17Q1438 -13 1443 0Q1478 69 1529 123L1539 133H318L328 123Q379 69 414 0Q419 -13 419 -17Q419 -24 399 -24Q388 -24 385 -23T377 -12Q332 77 253 144T72 237Q62 240 59 242T56 250T59 257T70 262T89 268T119 278T160 296Q303 366 377 512Q382 522 385 523T401 525Q419 524 419 515Q419 510 414 500Q379 431 328 377L318 367H1539L1529 377Q1496 412 1467 458T1438 514ZM274 173H1583L1593 181Q1632 211 1710 250Q1709 251 1692 259T1647 283T1593 319L1583 327H930L927 328L602 327H274L264 319Q225 289 147 250Q148 249 165 241T210 217T264 181L274 173Z"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(9414.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M202 -349V850H394V810H242V-309H394V-349H202Z"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(9831.6,0)"><g data-mml-node="mi"><path data-c="1D5A0" d="M183 181Q183 179 152 91T118 0H28L154 346L280 693Q281 694 333 694H385L511 349Q636 4 638 2Q638 0 584 0H530L464 183H184L183 181ZM324 606Q319 578 292 492T238 332T210 256Q210 254 324 254T438 255L429 281L419 308Q409 336 395 378T365 465T339 551T324 611V606Z"></path></g><g data-mml-node="mo" transform="translate(944.8,0)"><path data-c="27F6" d="M84 237T84 250T98 270H1444Q1328 357 1301 493Q1301 494 1301 496T1300 499Q1300 511 1317 511H1320Q1329 511 1332 510T1338 506T1341 497T1344 481T1352 456Q1374 389 1425 336T1544 261Q1553 258 1553 250Q1553 244 1548 241T1524 231T1486 212Q1445 186 1415 152T1370 85T1349 35T1341 4Q1339 -6 1336 -8T1320 -11Q1300 -11 1300 0Q1300 7 1305 25Q1337 151 1444 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mo" transform="translate(2860.6,0)"><path data-c="28" d="M74 250Q74 564 240 733L257 750H333L323 739Q167 573 167 250T323 -239L333 -250H257L240 -233Q74 -63 74 250Z"></path></g><g data-mml-node="mi" transform="translate(3249.6,0)"><path data-c="1D5A1" d="M425 363Q438 363 465 353T526 324T585 270T610 192Q610 132 561 78T426 7Q404 2 387 2T240 0H90V694H227Q373 693 396 689Q484 673 533 623T583 517Q583 494 574 473T551 437T520 409T487 388T456 374T433 366L425 363ZM490 516Q490 527 485 539T467 568T423 599T347 621Q340 622 262 623H188V399H261H286Q432 399 478 475Q490 496 490 516ZM514 190Q514 245 462 280T343 322Q336 323 259 323H188V71H274Q365 72 388 77Q445 88 479 121T514 190Z"></path></g><g data-mml-node="mo" transform="translate(4194.3,0)"><path data-c="27F6" d="M84 237T84 250T98 270H1444Q1328 357 1301 493Q1301 494 1301 496T1300 499Q1300 511 1317 511H1320Q1329 511 1332 510T1338 506T1341 497T1344 481T1352 456Q1374 389 1425 336T1544 261Q1553 258 1553 250Q1553 244 1548 241T1524 231T1486 212Q1445 186 1415 152T1370 85T1349 35T1341 4Q1339 -6 1336 -8T1320 -11Q1300 -11 1300 0Q1300 7 1305 25Q1337 151 1444 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(6110.1,0)"><path data-c="1D5A2" d="M59 347Q59 440 100 521T218 654T392 705Q473 705 550 680Q577 670 577 667Q576 666 572 642T564 595T559 571Q515 601 479 613T392 626Q300 626 232 549T164 347Q164 231 229 150T397 68Q453 68 489 80T568 120L581 129L582 110Q584 91 585 71T587 46Q580 40 566 31T502 5T396 -11Q296 -11 218 41T99 174T59 347Z"></path></g><g data-mml-node="mo" transform="translate(6749.1,0)"><path data-c="29" d="M221 -73T221 250T65 739L55 750H131L148 733Q314 567 314 250T148 -233L131 -250H55L65 -239Q221 -73 221 250Z"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(16969.7,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5D" d="M22 810V850H214V-349H22V-309H174V810H22Z"></path></g></g></g></g></svg></mjx-container></p><pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"> curry :: ((<span class="hljs-type">A</span>,<span class="hljs-type">B</span>) -> <span class="hljs-type">C</span>) -> (<span class="hljs-type">A</span> -> (<span class="hljs-type">B</span> -> <span class="hljs-type">C</span>))
curry f = \a -> (\b -> f (a,b))
uncurry:: (<span class="hljs-type">A</span> -> (<span class="hljs-type">B</span> -> <span class="hljs-type">C</span>)) -> ((<span class="hljs-type">A</span>,<span class="hljs-type">B</span>) -> <span class="hljs-type">C</span>)
uncurry g = \(a,b) -> g a b
</code></pre>
<p>which set up an <em>isomorphism</em></p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>curry $ uncurry g == g uncurry $ curry f == f
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="48" data-paginate="true" data-background-color="#fff" data-background-image="images/Cardano-RGB_Logo-Stack-Blue.png" data-theme="gaia" lang="en-CA" data-marpit-pagination="48" style="--paginate:true;--background-color:#fff;--background-image:images/Cardano-RGB_Logo-Stack-Blue.png;--theme:gaia;background-color:#fff;background-image:images/Cardano-RGB_Logo-Stack-Blue.png;background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="48">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code> f:: (I,S) -> (O,S) ~~~~~> curry(f):: I -> (S -> (O,S))
</code></pre>
<p><em>State monad</em> at the type <code>O</code>:</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-haskell"> <span class="hljs-type">State</span>:: * -> *
<span class="hljs-type">State</span> <span class="hljs-type">O</span> :: <span class="hljs-type">S</span> -> (<span class="hljs-type">O</span>,<span class="hljs-type">S</span>)
</code></pre>
<p><strong><em>A function</em></strong> <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="9.928ex" height="1.667ex" role="img" focusable="false" viewBox="0 -715 4388.1 737"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D5BF" d="M262 705H267Q300 705 347 694V612L336 616Q303 628 274 628H266Q224 628 199 605Q187 590 184 579T181 541V507V444H287V371H184V0H94V371H27V444H94V492Q94 544 95 550Q102 617 151 661T262 705Z"></path></g><g data-mml-node="mo" transform="translate(624.8,0)"><path data-c="3A" d="M78 370Q78 394 95 412T138 430Q162 430 180 414T199 371Q199 346 182 328T139 310T96 327T78 370ZM78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z"></path></g><g data-mml-node="mi" transform="translate(1180.6,0)"><path data-c="1D5A8" d="M87 0V694H191V0H87Z"></path></g><g data-mml-node="mo" transform="translate(1736.3,0)"><path data-c="27F6" d="M84 237T84 250T98 270H1444Q1328 357 1301 493Q1301 494 1301 496T1300 499Q1300 511 1317 511H1320Q1329 511 1332 510T1338 506T1341 497T1344 481T1352 456Q1374 389 1425 336T1544 261Q1553 258 1553 250Q1553 244 1548 241T1524 231T1486 212Q1445 186 1415 152T1370 85T1349 35T1341 4Q1339 -6 1336 -8T1320 -11Q1300 -11 1300 0Q1300 7 1305 25Q1337 151 1444 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(3652.1,0)"><path data-c="1D5AE" d="M55 345Q55 504 149 609T361 715Q386 715 406 713Q521 696 600 592T680 344Q680 193 590 86T368 -22Q239 -22 147 84T55 345ZM276 59T368 59T518 146T576 360Q576 473 525 545T401 634Q371 637 362 637Q284 637 222 562T159 360T217 147Z"></path></g></g></g></g></svg></mjx-container> <strong><em>with state</em></strong> <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="1.258ex" height="1.67ex" role="img" focusable="false" viewBox="0 -716 556 738"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D5B2" d="M55 514Q55 589 115 652T283 716Q315 716 345 711T396 699T432 685T457 672T467 667Q467 666 459 618T449 568Q383 634 282 634Q214 634 182 600T150 525Q150 507 155 492T172 465T194 446T222 432T247 423T272 416T289 412Q353 396 378 384Q432 358 466 307T500 194Q500 110 438 44T272 -22Q215 -22 159 -5T73 28T44 50Q45 51 49 75T57 122T62 146L65 143Q68 140 74 136T88 125T107 111T131 98T160 85T194 74T232 66T274 63H286Q327 63 366 96T406 182Q406 245 352 280Q329 296 265 310T173 339Q124 363 90 409T55 514Z"></path></g></g></g></g></svg></mjx-container> <strong><em>corresponds to a monadic computation</em></strong> <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="22.003ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 9725.1 1000"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D5BC" d="M34 223Q34 327 99 393T245 460Q290 460 301 459Q328 455 354 445T395 427T410 415L396 338L386 344Q377 349 362 357T335 370Q305 381 258 381H252Q182 381 146 315Q126 275 126 224Q126 158 159 113T255 68Q329 68 394 106L408 114L410 93Q411 72 412 52L414 32Q407 27 394 20T338 2T252 -10Q156 -10 95 58T34 223Z"></path><path data-c="1D5CE" d="M353 39Q352 38 344 34T331 27T315 19T295 11T270 3T241 -3T207 -8T168 -10H162Q148 -10 137 -8T111 2T87 30T74 81Q73 89 73 268V444H166V268L167 92Q171 79 174 74T192 64T238 59Q317 59 344 116Q349 128 349 148T350 291V444H443V0H353V39Z" transform="translate(444,0)"></path><path data-c="1D5CB" d="M171 389Q237 455 320 455H327V373H317Q262 369 220 336T167 248Q165 239 164 119V0H74V450H159V377L171 389Z" transform="translate(961,0)"></path><path data-c="1D5CB" d="M171 389Q237 455 320 455H327V373H317Q262 369 220 336T167 248Q165 239 164 119V0H74V450H159V377L171 389Z" transform="translate(1303,0)"></path><path data-c="1D5D2" d="M113 -204Q83 -204 63 -200L43 -197Q43 -196 40 -157T36 -117L48 -121Q79 -133 114 -133Q124 -133 130 -132T145 -121T163 -94Q169 -82 184 -42T200 1L188 29Q176 57 152 115T107 223T62 330T26 416L14 443Q14 444 61 444H109L122 411Q230 155 236 75L237 65V74Q245 161 348 424L356 444H401Q446 444 446 443L396 313Q345 183 293 49T236 -93Q191 -204 123 -204H113Z" transform="translate(1645,0)"></path></g><g data-mml-node="mo" transform="translate(2106,0)"><path data-c="28" d="M74 250Q74 564 240 733L257 750H333L323 739Q167 573 167 250T323 -239L333 -250H257L240 -233Q74 -63 74 250Z"></path></g><g data-mml-node="mi" transform="translate(2495,0)"><path data-c="1D5BF" d="M262 705H267Q300 705 347 694V612L336 616Q303 628 274 628H266Q224 628 199 605Q187 590 184 579T181 541V507V444H287V371H184V0H94V371H27V444H94V492Q94 544 95 550Q102 617 151 661T262 705Z"></path></g><g data-mml-node="mo" transform="translate(2842,0)"><path data-c="29" d="M221 -73T221 250T65 739L55 750H131L148 733Q314 567 314 250T148 -233L131 -250H55L65 -239Q221 -73 221 250Z"></path></g><g data-mml-node="mo" transform="translate(3508.8,0)"><path data-c="3A" d="M78 370Q78 394 95 412T138 430Q162 430 180 414T199 371Q199 346 182 328T139 310T96 327T78 370ZM78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z"></path></g><g data-mml-node="mi" transform="translate(4064.6,0)"><path data-c="1D5A8" d="M87 0V694H191V0H87Z"></path></g><g data-mml-node="mo" transform="translate(4620.3,0)"><path data-c="27F6" d="M84 237T84 250T98 270H1444Q1328 357 1301 493Q1301 494 1301 496T1300 499Q1300 511 1317 511H1320Q1329 511 1332 510T1338 506T1341 497T1344 481T1352 456Q1374 389 1425 336T1544 261Q1553 258 1553 250Q1553 244 1548 241T1524 231T1486 212Q1445 186 1415 152T1370 85T1349 35T1341 4Q1339 -6 1336 -8T1320 -11Q1300 -11 1300 0Q1300 7 1305 25Q1337 151 1444 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(6536.1,0)"><path data-c="1D5B2" d="M55 514Q55 589 115 652T283 716Q315 716 345 711T396 699T432 685T457 672T467 667Q467 666 459 618T449 568Q383 634 282 634Q214 634 182 600T150 525Q150 507 155 492T172 465T194 446T222 432T247 423T272 416T289 412Q353 396 378 384Q432 358 466 307T500 194Q500 110 438 44T272 -22Q215 -22 159 -5T73 28T44 50Q45 51 49 75T57 122T62 146L65 143Q68 140 74 136T88 125T107 111T131 98T160 85T194 74T232 66T274 63H286Q327 63 366 96T406 182Q406 245 352 280Q329 296 265 310T173 339Q124 363 90 409T55 514Z"></path><path data-c="1D5CD" d="M333 27Q333 24 314 16T257 -1T184 -10H172Q146 -10 128 14T105 58T99 91Q95 113 95 251V371H18V444H98V571H182V444H316V371H182V253Q183 128 189 104Q199 68 234 68Q277 72 314 98Q315 93 323 61T333 27Z" transform="translate(556,0)"></path><path data-c="1D5BA" d="M236 387Q209 387 184 382T141 370T111 355T91 342T83 337L82 355Q80 373 79 393T77 417Q77 419 81 421Q86 423 91 426Q155 460 227 460H238Q319 460 368 400Q393 371 400 341T408 252Q408 240 408 207T407 152V0H317V39L306 32Q244 -10 159 -10H152Q109 -10 77 22Q38 61 38 126Q38 142 39 146Q55 199 130 223T295 252H314V277Q314 305 313 310Q308 342 287 364T236 387ZM303 186Q124 180 124 126Q124 105 144 86T208 66Q284 66 309 124Q314 137 314 166V186H303Z" transform="translate(917,0)"></path><path data-c="1D5CD" d="M333 27Q333 24 314 16T257 -1T184 -10H172Q146 -10 128 14T105 58T99 91Q95 113 95 251V371H18V444H98V571H182V444H316V371H182V253Q183 128 189 104Q199 68 234 68Q277 72 314 98Q315 93 323 61T333 27Z" transform="translate(1398,0)"></path><path data-c="1D5BE" d="M28 226Q28 329 91 395T235 461Q258 461 279 456T325 436T368 397T399 332T415 238V219H113V215Q113 163 151 114T248 65Q273 65 298 70T341 82T373 96T396 108L403 113Q403 106 406 76T409 38Q409 34 408 33T393 24Q325 -10 252 -10Q155 -10 92 59T28 226ZM340 289L338 297Q335 305 333 310T327 326T317 343T304 358T286 372T263 381T233 385Q212 385 193 376T162 353T140 325T127 301T123 289H340Z" transform="translate(1759,0)"></path></g><g data-mml-node="mtext" transform="translate(8739.1,0)"><path data-c="A0" d=""></path></g><g data-mml-node="mi" transform="translate(8989.1,0)"><path data-c="1D5AE" d="M55 345Q55 504 149 609T361 715Q386 715 406 713Q521 696 600 592T680 344Q680 193 590 86T368 -22Q239 -22 147 84T55 345ZM276 59T368 59T518 146T576 360Q576 473 525 545T401 634Q371 637 362 637Q284 637 222 562T159 360T217 147Z"></path></g></g></g></g></svg></mjx-container></em></strong></p>
</section>
<script>!function(){"use strict";const t={h1:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"1"},style:"display: block; font-size: 2em; margin-block-start: 0.67em; margin-block-end: 0.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h2:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"2"},style:"display: block; font-size: 1.5em; margin-block-start: 0.83em; margin-block-end: 0.83em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h3:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"3"},style:"display: block; font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h4:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"4"},style:"display: block; margin-block-start: 1.33em; margin-block-end: 1.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h5:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"5"},style:"display: block; font-size: 0.83em; margin-block-start: 1.67em; margin-block-end: 1.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h6:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"6"},style:"display: block; font-size: 0.67em; margin-block-start: 2.33em; margin-block-end: 2.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},span:{proto:()=>HTMLSpanElement},pre:{proto:()=>HTMLElement,style:"display: block; font-family: monospace; white-space: pre; margin: 1em 0; --marp-auto-scaling-white-space: pre;"}},e="data-marp-auto-scaling-wrapper",i="data-marp-auto-scaling-svg",n="data-marp-auto-scaling-container";class s extends HTMLElement{constructor(){super(),this.svgPreserveAspectRatio="xMinYMid meet";const t=t=>([e])=>{const{width:i,height:n}=e.contentRect;this[t]={width:i,height:n},this.updateSVGRect()};this.attachShadow({mode:"open"}),this.containerObserver=new ResizeObserver(t("containerSize")),this.wrapperObserver=new ResizeObserver(((...e)=>{t("wrapperSize")(...e),this.flushSvgDisplay()}))}static get observedAttributes(){return["data-downscale-only"]}connectedCallback(){var t,s,o,r,a;this.shadowRoot.innerHTML=`\n<style>\n svg[${i}] { display: block; width: 100%; height: auto; vertical-align: top; }\n span[${n}] { display: table; white-space: var(--marp-auto-scaling-white-space, nowrap); width: max-content; }\n</style>\n<div ${e}>\n <svg part="svg" ${i}>\n <foreignObject><span ${n}><slot></slot></span></foreignObject>\n </svg>\n</div>\n `.split(/\n\s*/).join(""),this.wrapper=null!==(t=this.shadowRoot.querySelector(`div[${e}]`))&&void 0!==t?t:void 0;const l=this.svg;this.svg=null!==(o=null===(s=this.wrapper)||void 0===s?void 0:s.querySelector(`svg[${i}]`))&&void 0!==o?o:void 0,this.svg!==l&&(this.svgComputedStyle=this.svg?window.getComputedStyle(this.svg):void 0),this.container=null!==(a=null===(r=this.svg)||void 0===r?void 0:r.querySelector(`span[${n}]`))&&void 0!==a?a:void 0,this.observe()}disconnectedCallback(){this.svg=void 0,this.svgComputedStyle=void 0,this.wrapper=void 0,this.container=void 0,this.observe()}attributeChangedCallback(){this.observe()}flushSvgDisplay(){const{svg:t}=this;t&&(t.style.display="inline",requestAnimationFrame((()=>{t.style.display=""})))}observe(){this.containerObserver.disconnect(),this.wrapperObserver.disconnect(),this.wrapper&&this.wrapperObserver.observe(this.wrapper),this.container&&this.containerObserver.observe(this.container),this.svgComputedStyle&&this.observeSVGStyle(this.svgComputedStyle)}observeSVGStyle(t){const e=()=>{const i=(()=>{const e=t.getPropertyValue("--preserve-aspect-ratio");if(e)return e.trim();return`x${(({textAlign:t,direction:e})=>{if(t.endsWith("left"))return"Min";if(t.endsWith("right"))return"Max";if("start"===t||"end"===t){let i="rtl"===e;return"end"===t&&(i=!i),i?"Max":"Min"}return"Mid"})(t)}YMid meet`})();i!==this.svgPreserveAspectRatio&&(this.svgPreserveAspectRatio=i,this.updateSVGRect()),t===this.svgComputedStyle&&requestAnimationFrame(e)};e()}updateSVGRect(){var t,e,i,n,s,o,r;let a=Math.ceil(null!==(e=null===(t=this.containerSize)||void 0===t?void 0:t.width)&&void 0!==e?e:0);const l=Math.ceil(null!==(n=null===(i=this.containerSize)||void 0===i?void 0:i.height)&&void 0!==n?n:0);void 0!==this.dataset.downscaleOnly&&(a=Math.max(a,null!==(o=null===(s=this.wrapperSize)||void 0===s?void 0:s.width)&&void 0!==o?o:0));const c=null===(r=this.svg)||void 0===r?void 0:r.querySelector(":scope > foreignObject");if(null==c||c.setAttribute("width",`${a}`),null==c||c.setAttribute("height",`${l}`),this.svg&&(this.svg.setAttribute("viewBox",`0 0 ${a} ${l}`),this.svg.setAttribute("preserveAspectRatio",this.svgPreserveAspectRatio),this.svg.style.height=a<=0||l<=0?"0":""),this.container){const t=this.svgPreserveAspectRatio.toLowerCase();this.container.style.marginLeft=t.startsWith("xmid")||t.startsWith("xmax")?"auto":"0",this.container.style.marginRight=t.startsWith("xmi")?"auto":"0"}}}const o=(t,{attrs:e={},style:i})=>class extends t{constructor(...t){super(...t);for(const[t,i]of Object.entries(e))this.hasAttribute(t)||this.setAttribute(t,i);this.attachShadow({mode:"open"})}static get observedAttributes(){return["data-auto-scaling"]}connectedCallback(){this._update()}attributeChangedCallback(){this._update()}_update(){const t=i?`<style>:host { ${i} }</style>`:"";let e="<slot></slot>";const{autoScaling:n}=this.dataset;if(void 0!==n){e=`<marp-auto-scaling exportparts="svg:auto-scaling" ${"downscale-only"===n?"data-downscale-only":""}>${e}</marp-auto-scaling>`}this.shadowRoot.innerHTML=t+e}};let r;const a=Symbol();let l;const c="marpitSVGPolyfill:setZoomFactor,",d=Symbol(),g=Symbol();const h=()=>{const t="Apple Computer, Inc."===navigator.vendor,e=t?[u]:[],i={then:e=>(t?(async()=>{if(void 0===l){const t=document.createElement("canvas");t.width=10,t.height=10;const e=t.getContext("2d"),i=new Image(10,10),n=new Promise((t=>{i.addEventListener("load",(()=>t()))}));i.crossOrigin="anonymous",i.src="data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2210%22%20viewBox%3D%220%200%201%201%22%3E%3CforeignObject%20width%3D%221%22%20height%3D%221%22%20requiredExtensions%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cdiv%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%20style%3D%22width%3A%201px%3B%20height%3A%201px%3B%20background%3A%20red%3B%20position%3A%20relative%22%3E%3C%2Fdiv%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E",await n,e.drawImage(i,0,0),l=e.getImageData(5,5,1,1).data[3]<128}return l})().then((t=>{null==e||e(t?[u]:[])})):null==e||e([]),i)};return Object.assign(e,i)};let p,m;function u(t){const e="object"==typeof t&&t.target||document,i="object"==typeof t?t.zoom:t;window[g]||(Object.defineProperty(window,g,{configurable:!0,value:!0}),document.body.style.zoom=1.0001,document.body.offsetHeight,document.body.style.zoom=1,window.addEventListener("message",(({data:t,origin:e})=>{if(e===window.origin)try{if(t&&"string"==typeof t&&t.startsWith(c)){const[,e]=t.split(","),i=Number.parseFloat(e);Number.isNaN(i)||(m=i)}}catch(t){console.error(t)}})));let n=!1;Array.from(e.querySelectorAll("svg[data-marpit-svg]"),(t=>{var e,s,o,r;t.style.transform||(t.style.transform="translateZ(0)");const a=i||m||t.currentScale||1;p!==a&&(p=a,n=a);const l=t.getBoundingClientRect(),{length:c}=t.children;for(let i=0;i<c;i+=1){const n=t.children[i];if(n.getScreenCTM){const t=n.getScreenCTM();if(t){const i=null!==(s=null===(e=n.x)||void 0===e?void 0:e.baseVal.value)&&void 0!==s?s:0,c=null!==(r=null===(o=n.y)||void 0===o?void 0:o.baseVal.value)&&void 0!==r?r:0,d=n.children.length;for(let e=0;e<d;e+=1){const s=n.children[e];if("SECTION"===s.tagName){const{style:e}=s;e.transformOrigin||(e.transformOrigin=`${-i}px ${-c}px`),e.transform=`scale(${a}) matrix(${t.a}, ${t.b}, ${t.c}, ${t.d}, ${t.e-l.left}, ${t.f-l.top}) translateZ(0.0001px)`;break}}}}}})),!1!==n&&Array.from(e.querySelectorAll("iframe"),(({contentWindow:t})=>{null==t||t.postMessage(`${c}${n}`,"null"===window.origin?"*":window.origin)}))}function v({once:t=!1,target:e=document}={}){const i=function(t=document){if(t[d])return t[d];let e=!0;const i=()=>{e=!1,delete t[d]};Object.defineProperty(t,d,{configurable:!0,value:i});let n=[],s=!1;(async()=>{try{n=await h()}finally{s=!0}})();const o=()=>{for(const e of n)e({target:t});s&&0===n.length||e&&window.requestAnimationFrame(o)};return o(),i}(e);return t?(i(),()=>{}):i}p=1,m=void 0;const b=Symbol(),w=(e=document)=>{if("undefined"==typeof window)throw new Error("Marp Core's browser script is valid only in browser context.");if(((e=document)=>{const i=window[a];i||customElements.define("marp-auto-scaling",s);for(const n of Object.keys(t)){const s=`marp-${n}`,a=t[n].proto();null!=r||(r=!!document.createElement("div",{is:"marp-auto-scaling"}).outerHTML.startsWith("<div is")),r&&a!==HTMLElement?i||customElements.define(s,o(a,{style:t[n].style}),{extends:n}):(i||customElements.define(s,o(HTMLElement,t[n])),e.querySelectorAll(`${n}[is="${s}"]`).forEach((t=>{t.outerHTML=t.outerHTML.replace(new RegExp(`^<${n}`,"i"),`<${s}`).replace(new RegExp(`</${n}>$`,"i"),`</${s}>`)})))}window[a]=!0})(e),e[b])return e[b];const i=v({target:e}),n=()=>{i(),delete e[b]},l=Object.assign(n,{cleanup:n,update:()=>w(e)});return Object.defineProperty(e,b,{configurable:!0,value:l}),l},y=document.currentScript;w(y?y.getRootNode():document)}();
</script></foreignObject></svg></div><script>/*!! License: https://unpkg.com/@marp-team/[email protected]/lib/bespoke.js.LICENSE.txt */
!function(){"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var t={from:function(e,t){var n,r=1===(e.parent||e).nodeType?e.parent||e:document.querySelector(e.parent||e),o=[].filter.call("string"==typeof e.slides?r.querySelectorAll(e.slides):e.slides||r.children,(function(e){return"SCRIPT"!==e.nodeName})),i={},a=function(e,t){return(t=t||{}).index=o.indexOf(e),t.slide=e,t},s=function(e,t){i[e]=(i[e]||[]).filter((function(e){return e!==t}))},l=function(e,t){return(i[e]||[]).reduce((function(e,n){return e&&!1!==n(t)}),!0)},c=function(e,t){o[e]&&(n&&l("deactivate",a(n,t)),n=o[e],l("activate",a(n,t)))},d=function(e,t){var r=o.indexOf(n)+e;l(e>0?"next":"prev",a(n,t))&&c(r,t)},u={off:s,on:function(e,t){return(i[e]||(i[e]=[])).push(t),s.bind(null,e,t)},fire:l,slide:function(e,t){if(!arguments.length)return o.indexOf(n);l("slide",a(o[e],t))&&c(e,t)},next:d.bind(null,1),prev:d.bind(null,-1),parent:r,slides:o,destroy:function(e){l("destroy",a(n,e)),i={}}};return(t||[]).forEach((function(e){e(u)})),n||c(0),u}},n=e(t);const r=document.body,o=(...e)=>history.replaceState(...e),i="presenter",a="next",s=["",i,a],l="bespoke-marp-",c=`data-${l}`,d=(e,{protocol:t,host:n,pathname:r,hash:o}=location)=>{const i=e.toString();return`${t}//${n}${r}${i?"?":""}${i}${o}`},u=()=>r.dataset.bespokeView,f=e=>new URLSearchParams(location.search).get(e),m=(e,t={})=>{var n;const r={location,setter:o,...t},i=new URLSearchParams(r.location.search);for(const t of Object.keys(e)){const n=e[t];"string"==typeof n?i.set(t,n):i.delete(t)}try{r.setter({...null!==(n=window.history.state)&&void 0!==n?n:{}},"",d(i,r.location))}catch(e){console.error(e)}},g=(()=>{const e="bespoke-marp";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(e){return!1}})(),p=e=>{try{return localStorage.getItem(e)}catch(e){return null}},v=(e,t)=>{try{return localStorage.setItem(e,t),!0}catch(e){return!1}},h=e=>{try{return localStorage.removeItem(e),!0}catch(e){return!1}},y=(e,t)=>{const n="aria-hidden";t?e.setAttribute(n,"true"):e.removeAttribute(n)},b=e=>{e.parent.classList.add(`${l}parent`),e.slides.forEach((e=>e.classList.add(`${l}slide`))),e.on("activate",(t=>{const n=`${l}active`,r=t.slide,o=r.classList,i=!o.contains(n);if(e.slides.forEach((e=>{e.classList.remove(n),y(e,!0)})),o.add(n),y(r,!1),i){const e=`${n}-ready`;o.add(e),document.body.clientHeight,o.remove(e)}}))},w=e=>{let t=0,n=0;Object.defineProperty(e,"fragments",{enumerable:!0,value:e.slides.map((e=>[null,...e.querySelectorAll("[data-marpit-fragment]")]))});const r=r=>void 0!==e.fragments[t][n+r],o=(r,o)=>{t=r,n=o,e.fragments.forEach(((e,t)=>{e.forEach(((e,n)=>{if(null==e)return;const i=t<r||t===r&&n<=o;e.setAttribute(`${c}fragment`,(i?"":"in")+"active");const a=`${c}current-fragment`;t===r&&n===o?e.setAttribute(a,"current"):e.removeAttribute(a)}))})),e.fragmentIndex=o;const i={slide:e.slides[r],index:r,fragments:e.fragments[r],fragmentIndex:o};e.fire("fragment",i)};e.on("next",(({fragment:i=!0})=>{if(i){if(r(1))return o(t,n+1),!1;const i=t+1;e.fragments[i]&&o(i,0)}else{const r=e.fragments[t].length;if(n+1<r)return o(t,r-1),!1;const i=e.fragments[t+1];i&&o(t+1,i.length-1)}})),e.on("prev",(({fragment:i=!0})=>{if(r(-1)&&i)return o(t,n-1),!1;const a=t-1;e.fragments[a]&&o(a,e.fragments[a].length-1)})),e.on("slide",(({index:t,fragment:n})=>{let r=0;if(void 0!==n){const o=e.fragments[t];if(o){const{length:e}=o;r=-1===n?e-1:Math.min(Math.max(n,0),e-1)}}o(t,r)})),o(0,0)},x=document,k=()=>!(!x.fullscreenEnabled&&!x.webkitFullscreenEnabled),$=()=>!(!x.fullscreenElement&&!x.webkitFullscreenElement),E=e=>{e.fullscreen=()=>{k()&&(async()=>{return $()?null===(e=x.exitFullscreen||x.webkitExitFullscreen)||void 0===e?void 0:e.call(x):((e=x.body)=>{var t;return null===(t=e.requestFullscreen||e.webkitRequestFullscreen)||void 0===t?void 0:t.call(e)})();var e})()},document.addEventListener("keydown",(t=>{"f"!==t.key&&"F11"!==t.key||t.altKey||t.ctrlKey||t.metaKey||!k()||(e.fullscreen(),t.preventDefault())}))},L=`${l}inactive`,S=(e=2e3)=>({parent:t,fire:n})=>{const r=t.classList,o=e=>n(`marp-${e?"":"in"}active`);let i;const a=()=>{i&&clearTimeout(i),i=setTimeout((()=>{r.add(L),o()}),e),r.contains(L)&&(r.remove(L),o(!0))};for(const e of["mousedown","mousemove","touchend"])document.addEventListener(e,a);setTimeout(a,0)},P=["AUDIO","BUTTON","INPUT","SELECT","TEXTAREA","VIDEO"],_=e=>{e.parent.addEventListener("keydown",(e=>{if(!e.target)return;const t=e.target;(P.includes(t.nodeName)||"true"===t.contentEditable)&&e.stopPropagation()}))},T=e=>{window.addEventListener("load",(()=>{for(const t of e.slides){const e=t.querySelector("marp-auto-scaling, [data-auto-scaling], [data-marp-fitting]");t.setAttribute(`${c}load`,e?"":"hideable")}}))},I=({interval:e=250}={})=>t=>{document.addEventListener("keydown",(e=>{if(" "===e.key&&e.shiftKey)t.prev();else if("ArrowLeft"===e.key||"ArrowUp"===e.key||"PageUp"===e.key)t.prev({fragment:!e.shiftKey});else if(" "!==e.key||e.shiftKey)if("ArrowRight"===e.key||"ArrowDown"===e.key||"PageDown"===e.key)t.next({fragment:!e.shiftKey});else if("End"===e.key)t.slide(t.slides.length-1,{fragment:-1});else{if("Home"!==e.key)return;t.slide(0)}else t.next();e.preventDefault()}));let n,r,o=0;t.parent.addEventListener("wheel",(i=>{let a=!1;const s=(e,t)=>{e&&(a=a||((e,t)=>((e,t)=>{const n="X"===t?"Width":"Height";return e[`client${n}`]<e[`scroll${n}`]})(e,t)&&((e,t)=>{const{overflow:n}=e,r=e[`overflow${t}`];return"auto"===n||"scroll"===n||"auto"===r||"scroll"===r})(getComputedStyle(e),t))(e,t)),(null==e?void 0:e.parentElement)&&s(e.parentElement,t)};if(0!==i.deltaX&&s(i.target,"X"),0!==i.deltaY&&s(i.target,"Y"),a)return;i.preventDefault();const l=Math.sqrt(i.deltaX**2+i.deltaY**2);if(void 0!==i.wheelDelta){if(void 0===i.webkitForce&&Math.abs(i.wheelDelta)<40)return;if(i.deltaMode===i.DOM_DELTA_PIXEL&&l<4)return}else if(i.deltaMode===i.DOM_DELTA_PIXEL&&l<12)return;r&&clearTimeout(r),r=setTimeout((()=>{n=0}),e);const c=Date.now()-o<e,d=l<=n;if(n=l,c||d)return;let u;(i.deltaX>0||i.deltaY>0)&&(u="next"),(i.deltaX<0||i.deltaY<0)&&(u="prev"),u&&(t[u](),o=Date.now())}))},M=(e=`.${l}osc`)=>{const t=document.querySelector(e);if(!t)return()=>{};const n=(e,n)=>{t.querySelectorAll(`[${c}osc=${JSON.stringify(e)}]`).forEach(n)};return k()||n("fullscreen",(e=>e.style.display="none")),g||n("presenter",(e=>{e.disabled=!0,e.title="Presenter view is disabled due to restricted localStorage."})),e=>{t.addEventListener("click",(t=>{if(t.target instanceof HTMLElement){const{bespokeMarpOsc:n}=t.target.dataset;n&&t.target.blur();const r={fragment:!t.shiftKey};"next"===n?e.next(r):"prev"===n?e.prev(r):"fullscreen"===n?null==e||e.fullscreen():"presenter"===n&&e.openPresenterView()}})),e.parent.appendChild(t),e.on("activate",(({index:t})=>{n("page",(n=>n.textContent=`Page ${t+1} of ${e.slides.length}`))})),e.on("fragment",(({index:t,fragments:r,fragmentIndex:o})=>{n("prev",(e=>e.disabled=0===t&&0===o)),n("next",(n=>n.disabled=t===e.slides.length-1&&o===r.length-1))})),e.on("marp-active",(()=>y(t,!1))),e.on("marp-inactive",(()=>y(t,!0))),k()&&(e=>{for(const t of["","webkit"])x.addEventListener(t+"fullscreenchange",e)})((()=>n("fullscreen",(e=>e.classList.toggle("exit",k()&&$())))))}},O=e=>{window.addEventListener("message",(t=>{if(t.origin!==window.origin)return;const[n,r]=t.data.split(":");if("navigate"===n){const[t,n]=r.split(",");let o=Number.parseInt(t,10),i=Number.parseInt(n,10)+1;i>=e.fragments[o].length&&(o+=1,i=0),e.slide(o,{fragment:i})}}))};var A=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"];let C=e=>String(e).replace(/[&<>"']/g,(e=>`&${D[e]};`)),D={"&":"amp","<":"lt",">":"gt",'"':"quot","'":"apos"},N="dangerouslySetInnerHTML",B={className:"class",htmlFor:"for"},q={};function K(e,t){let n=[],r="";t=t||{};for(let e=arguments.length;e-- >2;)n.push(arguments[e]);if("function"==typeof e)return t.children=n.reverse(),e(t);if(e){if(r+="<"+e,t)for(let e in t)!1!==t[e]&&null!=t[e]&&e!==N&&(r+=` ${B[e]?B[e]:C(e)}="${C(t[e])}"`);r+=">"}if(-1===A.indexOf(e)){if(t[N])r+=t[N].__html;else for(;n.length;){let e=n.pop();if(e)if(e.pop)for(let t=e.length;t--;)n.push(e[t]);else r+=!0===q[e]?e:C(e)}r+=e?`</${e}>`:""}return q[r]=!0,r}const j=({children:e})=>K(null,null,...e),F=`${l}presenter-`,V={container:`${F}container`,dragbar:`${F}dragbar-container`,next:`${F}next`,nextContainer:`${F}next-container`,noteContainer:`${F}note-container`,noteWrapper:`${F}note-wrapper`,noteButtons:`${F}note-buttons`,infoContainer:`${F}info-container`,infoPage:`${F}info-page`,infoPageText:`${F}info-page-text`,infoPagePrev:`${F}info-page-prev`,infoPageNext:`${F}info-page-next`,noteButtonsBigger:`${F}note-bigger`,noteButtonsSmaller:`${F}note-smaller`,infoTime:`${F}info-time`,infoTimer:`${F}info-timer`},U=e=>{const{title:t}=document;document.title="[Presenter view]"+(t?` - ${t}`:"");const n={},r=e=>(n[e]=n[e]||document.querySelector(`.${e}`),n[e]);document.body.appendChild((e=>{const t=document.createElement("div");return t.className=V.container,t.appendChild(e),t.insertAdjacentHTML("beforeend",K(j,null,K("div",{class:V.nextContainer},K("iframe",{class:V.next,src:"?view=next"})),K("div",{class:V.dragbar}),K("div",{class:V.noteContainer},K("div",{class:V.noteWrapper}),K("div",{class:V.noteButtons},K("button",{class:V.noteButtonsSmaller,tabindex:"-1",title:"Smaller notes font size"},"Smaller notes font size"),K("button",{class:V.noteButtonsBigger,tabindex:"-1",title:"Bigger notes font size"},"Bigger notes font size"))),K("div",{class:V.infoContainer},K("div",{class:V.infoPage},K("button",{class:V.infoPagePrev,tabindex:"-1",title:"Previous"},"Previous"),K("span",{class:V.infoPageText}),K("button",{class:V.infoPageNext,tabindex:"-1",title:"Next"},"Next")),K("time",{class:V.infoTime,title:"Current time"}),K("time",{class:V.infoTimer,title:"Timer"})))),t})(e.parent)),(e=>{let t=!1;r(V.dragbar).addEventListener("mousedown",(()=>{t=!0,r(V.dragbar).classList.add("active")})),window.addEventListener("mouseup",(()=>{t=!1,r(V.dragbar).classList.remove("active")})),window.addEventListener("mousemove",(e=>{if(!t)return;const n=e.clientX/document.documentElement.clientWidth*100;r(V.container).style.setProperty("--bespoke-marp-presenter-split-ratio",`${Math.max(0,Math.min(100,n))}%`)})),r(V.nextContainer).addEventListener("click",(()=>e.next()));const n=r(V.next),o=(i=n,(e,t)=>{var n;return null===(n=i.contentWindow)||void 0===n?void 0:n.postMessage(`navigate:${e},${t}`,"null"===window.origin?"*":window.origin)});var i;n.addEventListener("load",(()=>{r(V.nextContainer).classList.add("active"),o(e.slide(),e.fragmentIndex),e.on("fragment",(({index:e,fragmentIndex:t})=>o(e,t)))}));const a=document.querySelectorAll(".bespoke-marp-note");a.forEach((e=>{e.addEventListener("keydown",(e=>e.stopPropagation())),r(V.noteWrapper).appendChild(e)})),e.on("activate",(()=>a.forEach((t=>t.classList.toggle("active",t.dataset.index==e.slide())))));let s=0;const l=e=>{s=Math.max(-5,s+e),r(V.noteContainer).style.setProperty("--bespoke-marp-note-font-scale",(1.2**s).toFixed(4))},c=()=>l(1),d=()=>l(-1),u=r(V.noteButtonsBigger),f=r(V.noteButtonsSmaller);u.addEventListener("click",(()=>{u.blur(),c()})),f.addEventListener("click",(()=>{f.blur(),d()})),document.addEventListener("keydown",(e=>{"+"===e.key&&c(),"-"===e.key&&d()}),!0),e.on("activate",(({index:t})=>{r(V.infoPageText).textContent=`${t+1} / ${e.slides.length}`}));const m=r(V.infoPagePrev),g=r(V.infoPageNext);m.addEventListener("click",(t=>{m.blur(),e.prev({fragment:!t.shiftKey})})),g.addEventListener("click",(t=>{g.blur(),e.next({fragment:!t.shiftKey})})),e.on("fragment",(({index:t,fragments:n,fragmentIndex:r})=>{m.disabled=0===t&&0===r,g.disabled=t===e.slides.length-1&&r===n.length-1}));let p=new Date;const v=()=>{const e=new Date,t=e=>`${Math.floor(e)}`.padStart(2,"0"),n=e.getTime()-p.getTime(),o=t(n/1e3%60),i=t(n/1e3/60%60),a=t(n/36e5%24);r(V.infoTime).textContent=e.toLocaleTimeString(),r(V.infoTimer).textContent=`${a}:${i}:${o}`};v(),setInterval(v,250),r(V.infoTimer).addEventListener("click",(()=>{p=new Date}))})(e)},X=e=>{if(!(e=>e.syncKey&&"string"==typeof e.syncKey)(e))throw new Error("The current instance of Bespoke.js is invalid for Marp bespoke presenter plugin.");Object.defineProperties(e,{openPresenterView:{enumerable:!0,value:H},presenterUrl:{enumerable:!0,get:R}}),g&&document.addEventListener("keydown",(t=>{"p"!==t.key||t.altKey||t.ctrlKey||t.metaKey||(t.preventDefault(),e.openPresenterView())}))};function H(){const{max:e,floor:t}=Math,n=e(t(.85*window.innerWidth),640),r=e(t(.85*window.innerHeight),360);return window.open(this.presenterUrl,F+this.syncKey,`width=${n},height=${r},menubar=no,toolbar=no`)}function R(){const e=new URLSearchParams(location.search);return e.set("view","presenter"),e.set("sync",this.syncKey),d(e)}const W=e=>{const t=u();return t===a&&e.appendChild(document.createElement("span")),{"":X,[i]:U,[a]:O}[t]},J=e=>{e.on("activate",(t=>{document.querySelectorAll(".bespoke-progress-parent > .bespoke-progress-bar").forEach((n=>{n.style.flexBasis=100*t.index/(e.slides.length-1)+"%"}))}))},Y=e=>{const t=Number.parseInt(e,10);return Number.isNaN(t)?null:t},z=(e={})=>{const t={history:!0,...e};return e=>{let n=!0;const r=e=>{const t=n;try{return n=!0,e()}finally{n=t}},o=(t={fragment:!0})=>{let n=t.fragment?Y(f("f")||""):null;((t,n)=>{const{min:r,max:o}=Math,{fragments:i,slides:a}=e,s=o(0,r(t,a.length-1)),l=o(0,r(n||0,i[s].length-1));s===e.slide()&&l===e.fragmentIndex||e.slide(s,{fragment:l})})((()=>{var t,r;if(location.hash){const[o]=location.hash.slice(1).split(":~:");if(/^\d+$/.test(o))return(null!==(t=Y(o))&&void 0!==t?t:1)-1;const i=document.getElementById(o)||document.querySelector(`a[name="${CSS.escape(o)}"]`);if(i){const{length:t}=e.slides;for(let o=0;o<t;o+=1)if(e.slides[o].contains(i)){const t=null===(r=e.fragments)||void 0===r?void 0:r[o],a=i.closest("[data-marpit-fragment]");if(t&&a){const e=t.indexOf(a);e>=0&&(n=e)}return o}}}return 0})(),n)};e.on("fragment",(({index:e,fragmentIndex:r})=>{n||m({f:0===r||r.toString()},{location:{...location,hash:`#${e+1}`},setter:(...e)=>t.history?history.pushState(...e):history.replaceState(...e)})})),setTimeout((()=>{o(),window.addEventListener("hashchange",(()=>r((()=>{o({fragment:!1}),m({f:void 0})})))),window.addEventListener("popstate",(()=>{n||r((()=>o()))})),n=!1}),0)}},G=(e={})=>{var t;const n=e.key||(null===(t=window.history.state)||void 0===t?void 0:t.marpBespokeSyncKey)||Math.random().toString(36).slice(2),r=`bespoke-marp-sync-${n}`;var i;i={marpBespokeSyncKey:n},m({},{setter:(e,...t)=>o({...e,...i},...t)});const a=()=>{const e=p(r);return e?JSON.parse(e):Object.create(null)},s=e=>{const t=a(),n={...t,...e(t)};return v(r,JSON.stringify(n)),n},l=()=>{window.removeEventListener("pageshow",l),s((e=>({reference:(e.reference||0)+1})))};return e=>{l(),Object.defineProperty(e,"syncKey",{value:n,enumerable:!0});let t=!0;setTimeout((()=>{e.on("fragment",(e=>{t&&s((()=>({index:e.index,fragmentIndex:e.fragmentIndex})))}))}),0),window.addEventListener("storage",(n=>{if(n.key===r&&n.oldValue&&n.newValue){const r=JSON.parse(n.oldValue),o=JSON.parse(n.newValue);if(r.index!==o.index||r.fragmentIndex!==o.fragmentIndex)try{t=!1,e.slide(o.index,{fragment:o.fragmentIndex,forSync:!0})}finally{t=!0}}}));const o=()=>{const{reference:e}=a();void 0===e||e<=1?h(r):s((()=>({reference:e-1})))};window.addEventListener("pagehide",(e=>{e.persisted&&window.addEventListener("pageshow",l),o()})),e.on("destroy",o)}},{PI:Q,abs:Z,sqrt:ee,atan2:te}=Math,ne={passive:!0},re=({slope:e=-.7,swipeThreshold:t=30}={})=>n=>{let r;const o=n.parent,i=e=>{const t=o.getBoundingClientRect();return{x:e.pageX-(t.left+t.right)/2,y:e.pageY-(t.top+t.bottom)/2}};o.addEventListener("touchstart",(({touches:e})=>{r=1===e.length?i(e[0]):void 0}),ne),o.addEventListener("touchmove",(e=>{if(r)if(1===e.touches.length){e.preventDefault();const t=i(e.touches[0]),n=t.x-r.x,o=t.y-r.y;r.delta=ee(Z(n)**2+Z(o)**2),r.radian=te(n,o)}else r=void 0})),o.addEventListener("touchend",(o=>{if(r){if(r.delta&&r.delta>=t&&r.radian){const t=(r.radian-e+Q)%(2*Q)-Q;n[t<0?"next":"prev"](),o.stopPropagation()}r=void 0}}),ne)},oe=new Map;oe.clear(),oe.set("none",{backward:{both:void 0,incoming:void 0,outgoing:void 0},forward:{both:void 0,incoming:void 0,outgoing:void 0}});const ie={both:"",outgoing:"outgoing-",incoming:"incoming-"},ae={forward:"",backward:"-backward"},se=e=>`--marp-bespoke-transition-animation-${e}`,le=e=>`--marp-transition-${e}`,ce=se("name"),de=se("duration"),ue=e=>new Promise((t=>{const n={},r=document.createElement("div"),o=e=>{r.remove(),t(e)};r.addEventListener("animationstart",(()=>o(n))),Object.assign(r.style,{animationName:e,animationDuration:"1s",animationFillMode:"both",animationPlayState:"paused",position:"absolute",pointerEvents:"none"}),document.body.appendChild(r);const i=getComputedStyle(r).getPropertyValue(le("duration"));i&&(n.defaultDuration=i),((e,t)=>{requestAnimationFrame((()=>{e.style.animationPlayState="running",requestAnimationFrame((()=>t(void 0)))}))})(r,o)})),fe=async e=>oe.has(e)?oe.get(e):(e=>{const t={},n=[];for(const[r,o]of Object.entries(ie))for(const[i,a]of Object.entries(ae)){const s=`marp-${o}transition${a}-${e}`;n.push(ue(s).then((e=>{t[i]=t[i]||{},t[i][r]=e?{...e,name:s}:void 0})))}return Promise.all(n).then((()=>t))})(e).then((t=>(oe.set(e,t),t))),me=e=>Object.values(e).flatMap(Object.values).every((e=>!e)),ge=(e,{type:t,backward:n})=>{const r=e[n?"backward":"forward"],o=(()=>{const e=r[t],n=e=>({[ce]:e.name});if(e)return n(e);if(r.both){const e=n(r.both);return"incoming"===t&&(e[se("direction")]="reverse"),e}})();return!o&&n?ge(e,{type:t,backward:!1}):o||{[ce]:"__bespoke_marp_transition_no_animation__"}},pe=e=>{if(e)try{const t=JSON.parse(e);if((e=>{if("object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&(void 0===t.duration||"string"==typeof t.duration)})(t))return t}catch(e){}},ve="_tSId",he="_tA",ye="bespoke-marp-transition-warming-up",be=window.matchMedia("(prefers-reduced-motion: reduce)"),we="__bespoke_marp_transition_reduced_outgoing__",xe="__bespoke_marp_transition_reduced_incoming__",ke={forward:{both:void 0,incoming:{name:xe},outgoing:{name:we}},backward:{both:void 0,incoming:{name:xe},outgoing:{name:we}}},$e=e=>{if(!document.startViewTransition)return;const t=t=>(void 0!==t&&(e._tD=t),e._tD);let n;t(!1),((...e)=>{const t=[...new Set(e).values()];return Promise.all(t.map((e=>fe(e)))).then()})(...Array.from(document.querySelectorAll("section[data-transition], section[data-transition-back]")).flatMap((e=>[e.dataset.transition,e.dataset.transitionBack].flatMap((e=>{const t=pe(e);return[null==t?void 0:t.name,(null==t?void 0:t.builtinFallback)?`__builtin__${t.name}`:void 0]})).filter((e=>!!e))))).then((()=>{document.querySelectorAll("style").forEach((e=>{e.innerHTML=e.innerHTML.replace(/--marp-transition-duration:[^;}]*[;}]/g,(e=>e.slice(0,-1)+"!important"+e.slice(-1)))}))}));const r=(n,{back:r,cond:o})=>i=>{var a;const s=t();if(s)return!!i[he]||!("object"!=typeof s||(s.skipTransition(),!i.forSync));if(!o(i))return!0;const l=e.slides[e.slide()],c=()=>{var e;return null!==(e=i.back)&&void 0!==e?e:r},d="data-transition"+(c()?"-back":""),u=l.querySelector(`section[${d}]`);if(!u)return!0;const f=pe(null!==(a=u.getAttribute(d))&&void 0!==a?a:void 0);return!f||((async(e,{builtinFallback:t=!0}={})=>{let n=await fe(e);if(me(n)){if(!t)return;return n=await fe(`__builtin__${e}`),me(n)?void 0:n}return n})(f.name,{builtinFallback:f.builtinFallback}).then((e=>{if(!e){t(!0);try{n(i)}finally{t(!1)}return}let r=e;be.matches&&(console.warn("Use a constant animation to transition because preferring reduced motion by viewer has detected."),r=ke);const o=document.getElementById(ve);o&&o.remove();const a=document.createElement("style");a.id=ve,document.head.appendChild(a),((e,t)=>{const n=[`:root{${le("direction")}:${t.backward?-1:1};}`,":root:has(.bespoke-marp-inactive){cursor:none;}"],r=t=>{var n,o,i;const a=(null===(n=e[t].both)||void 0===n?void 0:n.defaultDuration)||(null===(o=e[t].outgoing)||void 0===o?void 0:o.defaultDuration)||(null===(i=e[t].incoming)||void 0===i?void 0:i.defaultDuration);return"forward"===t?a:a||r("forward")},o=t.duration||r(t.backward?"backward":"forward");void 0!==o&&n.push(`::view-transition-group(*){${de}:${o};}`);const i=e=>Object.entries(e).map((([e,t])=>`${e}:${t};`)).join("");return n.push(`::view-transition-old(root){${i(ge(e,{...t,type:"outgoing"}))}}`,`::view-transition-new(root){${i(ge(e,{...t,type:"incoming"}))}}`),n})(r,{backward:c(),duration:f.duration}).forEach((e=>{var t;return null===(t=a.sheet)||void 0===t?void 0:t.insertRule(e)}));const s=document.documentElement.classList;s.add(ye);let l=!1;const d=()=>{l||(n(i),l=!0,s.remove(ye))},u=()=>{t(!1),a.remove(),s.remove(ye)};try{t(!0);const e=document.startViewTransition(d);t(e),e.finished.finally(u)}catch(e){console.error(e),d(),u()}})),!1)};e.on("prev",r((t=>e.prev({...t,[he]:!0})),{back:!0,cond:e=>{var t;return e.index>0&&!((null===(t=e.fragment)||void 0===t||t)&&n.fragmentIndex>0)}})),e.on("next",r((t=>e.next({...t,[he]:!0})),{cond:t=>t.index+1<e.slides.length&&!(n.fragmentIndex+1<n.fragments.length)})),setTimeout((()=>{e.on("slide",r((t=>e.slide(t.index,{...t,[he]:!0})),{cond:t=>{const n=e.slide();return t.index!==n&&(t.back=t.index<n,!0)}}))}),0),e.on("fragment",(e=>{n=e}))};let Ee;const Le=()=>(void 0===Ee&&(Ee="wakeLock"in navigator&&navigator.wakeLock),Ee),Se=async()=>{const e=Le();if(e)try{return await e.request("screen")}catch(e){console.warn(e)}return null},Pe=async()=>{if(!Le())return;let e;const t=()=>{e&&"visible"===document.visibilityState&&Se()};for(const e of["visibilitychange","fullscreenchange"])document.addEventListener(e,t);return e=await Se(),e};((e=document.getElementById(":$p"))=>{(()=>{const e=f("view");r.dataset.bespokeView=e===a||e===i?e:""})();const t=(e=>{const t=f(e);return m({[e]:void 0}),t})("sync")||void 0;n.from(e,((...e)=>{const t=s.findIndex((e=>u()===e));return e.map((([e,n])=>e[t]&&n)).filter((e=>e))})([[1,1,0],G({key:t})],[[1,1,1],W(e)],[[1,1,0],_],[[1,1,1],b],[[1,0,0],S()],[[1,1,1],T],[[1,1,1],z({history:!1})],[[1,1,0],I()],[[1,1,0],E],[[1,0,0],J],[[1,1,0],re()],[[1,0,0],M()],[[1,0,0],$e],[[1,1,1],w],[[1,1,0],Pe]))})()}();</script></body></html>