templates.minikitties

  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    )