-
Notifications
You must be signed in to change notification settings - Fork 4
/
PunksV1.rb
169 lines (150 loc) · 6.97 KB
/
PunksV1.rb
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
class Punks < Contract
# You can use this hash to verify the image file containing
# all the punks
IMAGE_HASH = "0xac39af4793119ee46bbff351d8cb6b5f23da60222126add4268e261199a2921b";
event :Assign,
to: Address, # indexed
punkIndex: UInt
event :Transfer,
from: Address, # indexed
to: Address, # indexed
value: UInt
event :PunkTransfer,
from: Address, # indexed
to: Address, # indexed
punkIndex: UInt
event :PunkOffered,
punkIndex: UInt, # indexed
minValue: UInt,
toAddress: Address # indexed
event :PunkBought,
punkIndex: UInt, # indexed
value: UInt,
fromAddress: Address, # indexed
toAddress: Address # indexed
event :PunkNoLongerForSale,
punkIndex: UInt # indexed
struct :Offer,
isForSale: Bool,
punkIndex: UInt,
seller: Address,
minValue: UInt, # in ether
onlySellTo: Address # specify to sell only to a specific person
storage owner: Address,
name: String,
symbol: String,
decimals: UInt,
totalSupply: UInt,
nextPunkIndexToAssign: UInt,
punksRemainingToAssign: UInt,
numberOfPunksToReserve: UInt,
numberOfPunksReserved: UInt,
punkIndexToAddress: mapping( UInt, Address ),
balanceOf: mapping( Address, UInt ), # This creates an array with all balances
punksOfferedForSale: mapping( UInt, Offer ), # A record of punks that are offered for sale at a specific minimum value, and perhaps to a specific person
pendingWithdrawals: mapping( Address, UInt )
sig []
def constructor
@owner = msg.sender
@totalSupply = 10000 # Update total supply
@punksRemainingToAssign = @totalSupply
@numberOfPunksToReserve = 1000
@name = "PUNKS" # Set the name for display purposes
@symbol = "P" # Set the symbol for display purposes
@decimals = 0 # Amount of decimals for display purposes
end
sig [UInt]
def reservePunksForOwner( maxForThisRun: )
assert msg.sender == @owner
assert @numberOfPunksReserved < @numberOfPunksToReserve
numberPunksReservedThisRun = 0
while @numberOfPunksReserved < @numberOfPunksToReserve && numberPunksReservedThisRun < maxForThisRun
@punkIndexToAddress[ @nextPunkIndexToAssign ] = msg.sender
log Assign, to: msg.sender, punkIndex: @nextPunkIndexToAssign
numberPunksReservedThisRun +=1
@nextPunkIndexToAssign += 1
end
@punksRemainingToAssign -= numberPunksReservedThisRun
@numberOfPunksReserved += numberPunksReservedThisRun
@balanceOf[msg.sender] += numberPunksReservedThisRun
end
sig [UInt]
def getPunk( punkIndex: )
assert @punksRemainingToAssign > 0
assert @punkIndexToAddress[punkIndex] == address(0)
@punkIndexToAddress[punkIndex] = msg.sender
@balanceOf[msg.sender] += 1
@punksRemainingToAssign -= 1
log Assign, to: msg.sender, punkIndex: punkIndex
end
# Transfer ownership of a punk to another user without requiring payment
sig [Address, UInt]
def transferPunk( to:, punkIndex: )
assert @punkIndexToAddress[punkIndex] == msg.sender
@punkIndexToAddress[punkIndex] = to
@balanceOf[msg.sender] -= 1
@balanceOf[to] += 1
log Transfer, from: msg.sender, to: to, value: 1
log PunkTransfer, from: msg.sender, to: to, punkIndex: punkIndex
end
sig [UInt]
def punkNoLongerForSale( punkIndex: )
assert @punkIndexToAddress[punkIndex] == msg.sender
@punksOfferedForSale[punkIndex] = Offer.new(
isForSale: false,
punkIndex: punnkIndex,
seller: msg.sender,
minValue: 0,
onlySellTo: address(0))
log PunkNoLongerForSale, punkIndex: punkIndex
end
sig [UInt, UInt]
def offerPunkForSale( punkIndex:, minSalePriceInWei: )
assert @punkIndexToAddress[punkIndex] == msg.sender
@punksOfferedForSale[punkIndex] = Offer.new(
isForSale: true,
punkIndex: punkIndex,
seller: msg.sender,
minValue: minSalePriceInWei,
onlySellTo: address(0))
log PunkOffered, punkIndex: punkIndex, minValue: minSalePriceInWei,
toAddress: address(0)
end
sig [UInt, UInt, Address]
def offerPunkForSaleToAddress( punkIndex:, minSalePriceInWei:, toAddress: )
assert @punkIndexToAddress[punkIndex] == msg.sender
@punksOfferedForSale[punkIndex] = Offer.new(
isForSale: true,
punkIndex: punkIndex,
seller: msg.sender,
minValue: minSalePriceInWei,
onlySellTo: toAddress)
log PunkOffered, punkIndex: punkIndex, minValue: minSalePriceInWei,
toAddress: toAddress
end
sig [UInt]
def buyPunk( punkIndex: ) # payable
offer = @punksOfferedForSale[ punkIndex ]
assert offer.isForSale, "punk not actually for sale"
assert offer.onlySellTo == address(0) || offer.onlySellTo == msg.sender, "punk not supposed to be sold to this user"
assert msg.value >= offer.minValue, "Didn't send enough ETH"
assert offer.seller == @punkIndexToAddress[punkIndex], "Seller no longer owner of punk"
@punkIndexToAddress[punkIndex] = msg.sender
@balanceOf[offer.seller] -= 1
@balanceOf[msg.sender] += 1
log Transfer, from: offer.seller, to: msg.sender, value: 1
punkNoLongerForSale( punkIndex )
@pendingWithdrawals[offer.seller] += msg.value
log PunkBought, punkIndex: punkIndex, value: msg.value,
fromAddress: offer.seller,
toAddress: msg.sender
end
sig []
def withdraw
amount = @pendingWithdrawals[msg.sender]
# Remember to zero the pending refund before
# sending to prevent re-entrancy attacks
@pendingWithdrawals[ msg.sender ] = 0
msg.sender.transfer(amount)
end
end