1# Mini-kitties - Example for illustrative purposes only.
2
3# This small example is loosely inspired by CryptoKitties.
4
5import smartpy as sp
6
7
8@sp.module
9def main():
10 class MiniKitties(sp.Contract):
11 def __init__(self, creator, newAuctionDuration, hatchingDuration):
12 self.private.newAuctionDuration = newAuctionDuration
13 self.private.hatchingDuration = hatchingDuration
14 self.data.kitties = {}
15 self.data.creator = creator
16
17 @sp.entrypoint
18 def build(self, params):
19 assert self.data.creator == sp.sender
20 assert params.kitty.isNew
21 sp.cast(params.kitty.kittyId, sp.int)
22 self.data.kitties[params.kitty.kittyId] = params.kitty
23
24 @sp.entrypoint
25 def sell(self, price, params):
26 assert sp.mutez(0) <= price
27 self.checkAvailable(
28 sp.record(
29 kitty=self.data.kitties[params.kittyId],
30 borrowPrice=params.borrowPrice,
31 borrow=False,
32 )
33 )
34 self.data.kitties[params.kittyId].price = params.price
35
36 @sp.entrypoint
37 def lend(self, price, params):
38 assert sp.mutez(0) <= price
39 self.checkAvailable(
40 sp.record(
41 kitty=self.data.kitties[params.kittyId],
42 borrowPrice=params.borrowPrice,
43 borrow=False,
44 )
45 )
46 self.data.kitties[params.kittyId].borrowPrice = params.price
47
48 @sp.entrypoint
49 def buy(self, params):
50 kitty = self.data.kitties[params.kittyId]
51 assert sp.mutez(0) < kitty.price
52 assert kitty.price <= params.price
53 assert sp.amount == params.price
54 sp.send(kitty.owner, params.price)
55 kitty.owner = sp.sender
56 if kitty.isNew:
57 kitty.isNew = False
58 kitty.auction = sp.add_seconds(sp.now, self.private.newAuctionDuration)
59 assert sp.now <= kitty.auction
60 if sp.now <= kitty.auction:
61 kitty.price = params.price + sp.mutez(1)
62 self.data.kitties[params.kittyId] = kitty
63
64 @sp.private(with_storage="read-write", with_operations=True)
65 def checkAvailable(self, params):
66 if params.borrow:
67 assert sp.mutez(0) < params.kitty.borrowPrice
68 borrowPrice = params.borrowPrice
69 assert params.kitty.borrowPrice < borrowPrice
70 assert sp.amount == borrowPrice
71 sp.send(params.kitty.owner, borrowPrice)
72 assert params.kitty.auction < sp.now
73 assert params.kitty.hatching < sp.now
74
75 @sp.private()
76 def newKitty(self, params):
77 return sp.record(
78 kittyId=params.kittyId,
79 owner=sp.sender,
80 price=sp.mutez(0),
81 isNew=False,
82 auction=sp.timestamp(0),
83 hatching=params.hatching,
84 generation=params.generation,
85 borrowPrice=sp.mutez(0),
86 )
87
88 @sp.entrypoint
89 def breed(self, params):
90 parent1 = params.parent1
91 parent2 = params.parent2
92 kitty1 = self.data.kitties[parent1]
93 kitty2 = self.data.kitties[parent2]
94 assert parent1 != parent2
95 self.checkAvailable(
96 sp.record(kitty=kitty1, borrowPrice=params.borrowPrice, borrow=False)
97 )
98 self.checkAvailable(
99 sp.record(
100 kitty=kitty2,
101 borrowPrice=params.borrowPrice,
102 borrow=kitty2.owner != sp.sender,
103 )
104 )
105 hatching = sp.add_seconds(sp.now, self.private.hatchingDuration)
106 self.data.kitties[parent1].hatching = hatching
107 self.data.kitties[parent2].hatching = hatching
108 kitty = self.newKitty(
109 sp.record(
110 kittyId=params.kittyId,
111 hatching=hatching,
112 generation=1 + sp.max(kitty1.generation, kitty2.generation),
113 )
114 )
115 self.data.kitties[kitty.kittyId] = kitty
116
117
118@sp.add_test()
119def test():
120 creator = sp.test_account("Creator")
121 alice = sp.test_account("Alice")
122 bob = sp.test_account("Robert")
123
124 scenario = sp.test_scenario("MiniKitties", main)
125 c1 = main.MiniKitties(
126 creator=creator.address, newAuctionDuration=10, hatchingDuration=100
127 )
128 scenario.h1("Mini Kitties")
129 scenario += c1
130
131 def newKitty(kittyId, price):
132 return sp.record(
133 kittyId=kittyId,
134 owner=creator.address,
135 price=sp.mutez(price),
136 isNew=True,
137 auction=sp.timestamp(0),
138 hatching=sp.timestamp(0),
139 generation=0,
140 borrowPrice=sp.mutez(0),
141 )
142
143 c1.build(kitty=newKitty(0, 10), _sender=creator)
144 c1.build(kitty=newKitty(1, 10), _sender=creator)
145 c1.build(kitty=newKitty(2, 10), _sender=creator)
146 c1.build(kitty=newKitty(3, 10), _sender=creator)
147 c1.buy(kittyId=1, price=sp.mutez(10), _sender=alice, _amount=sp.mutez(10))
148 c1.buy(kittyId=2, price=sp.mutez(10), _sender=alice, _amount=sp.mutez(10))
149 c1.buy(
150 kittyId=1,
151 price=sp.mutez(11),
152 _sender=bob,
153 _amount=sp.mutez(11),
154 _now=sp.timestamp(3),
155 )
156 c1.buy(
157 kittyId=1,
158 price=sp.mutez(15),
159 _sender=alice,
160 _amount=sp.mutez(15),
161 _now=sp.timestamp(9),
162 )
163 scenario.h2("A bad execution")
164 c1.buy(
165 kittyId=1,
166 price=sp.mutez(20),
167 _sender=bob,
168 _amount=sp.mutez(20),
169 _now=sp.timestamp(13),
170 _valid=False,
171 )
172 scenario.h2("Hatching")
173 c1.breed(
174 borrowPrice=sp.mutez(10),
175 kittyId=4,
176 parent1=1,
177 parent2=2,
178 _sender=alice,
179 _now=sp.timestamp(15),
180 )