This repository has been archived by the owner on Sep 19, 2024. It is now read-only.
generated from huff-language/huff-project-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHuffd1.huff
347 lines (288 loc) · 16.6 KB
/
Huffd1.huff
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
/// @title Huffd1
/// @notice SPDX-License-Identifier: MIT
/// @author erhant <https://github.com/erhant>
/// @notice An NFT where instead of mappings we use polynomials
/// over a finite field with a large prime order.
///////////////////////////////////////////////////////////////////////////////
//// INCLUDES ////
///////////////////////////////////////////////////////////////////////////////
#include "./util/Owned.huff"
#include "./util/Polynomial.huff"
///////////////////////////////////////////////////////////////////////////////
//// TABLE ////
///////////////////////////////////////////////////////////////////////////////
// #define table Basis {
// 0x01050700020c000607
// }
// #define constant TOTAL_SUPPLY = 0x03
// #define constant ORDER = 0x0d
// #define constant COEFF_SIZE = 0x01
#define table Basis {
0x0000000000000000000000000000000000000001aed4ed4ed4ed4ed4ed4ed4ed4ed4ed4ed4ed4eb2716596596596596596596596596596596596595467bb5f442d26609eed7d10b499827bb5f442d251a1ffffffffffffffffffffffffffffffffffffe306795ceb240795ceb240795ceb240795ceb240780eaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa83d3a3e4e8f93a3e4e8f93a3e4e8f93a3e4e8f92fddefbefbefbefbefbefbefbefbefbefbefbefbc7a5bc18334a5116d889fa66c2ddf4fbc18334a4f300000000000000000000000000000000000000000000000000000000000000000000000000000009257c57c57c57c57c57c57c57c57c57c57c57c565220ea0ea0ea0ea0ea0ea0ea0ea0ea0ea0ea0ea15c7a4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4f7b79a4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4f90b3e93e93e93e93e93e93e93e93e93e93e93e93c837e93e93e93e93e93e93e93e93e93e93e93e93df5ef56f56f56f56f56f56f56f56f56f56f56f56e42c6326326326326326326326326326326326325b0000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffbfb507507507507507507507507507507507507510615f15f15f15f15f15f15f15f15f15f15f15f128e582d82d82d82d82d82d82d82d82d82d82d82d6a0ec16c16c16c16c16c16c16c16c16c16c16c16ba92d82d82d82d82d82d82d82d82d82d82d82d82be416c16c16c16c16c16c16c16c16c16c16c16c160d29da9da9da9da9da9da9da9da9da9da9da9da774e736736736736736736736736736736736736650000000000000000000000000000000000000000000000000000000000000000000000000000001c749f49f49f49f49f49f49f49f49f49f49f49f444e3518a6dfc3518a6dfc3518a6dfc3518a6dfc36b4eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeebf7cfa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4ed3444444444444444444444444444444444444439016c16c16c16c16c16c16c16c16c16c16c16c16c082d82d82d82d82d82d82d82d82d82d82d82d82c9e480f2b9d6480f2b9d6480f2b9d6480f2b9d62b00000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffc95ccccccccccccccccccccccccccccccccccccd0de3333333333333333333333333333333333332b8f53e93e93e93e93e93e93e93e93e93e93e93e93cce4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa1d27a4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa03be93e93e93e93e93e93e93e93e93e93e93e93de864fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa379293e93e93e93e93e93e93e93e93e93e93e93e79000000000000000000000000000000000000000033333333333333333333333333333333333333433fffffffffffffffffffffffffffffffffffffb2d00000000000000000000000000000000000001e2c71c71c71c71c71c71c71c71c71c71c71c71c452e7d27d27d27d27d27d27d27d27d27d27d27d280ac71c71c71c71c71c71c71c71c71c71c71c71c5060e38e38e38e38e38e38e38e38e38e38e38e38d2e71c71c71c71c71c71c71c71c71c71c71c71c6f26d6c16c16c16c16c16c16c16c16c16c16c16c1580000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffc31b05b05b05b05b05b05b05b05b05b05b05b05b2626480f2b9d6480f2b9d6480f2b9d6480f2b9d61a5a22222222222222222222222222222222222227b305b05b05b05b05b05b05b05b05b05b05b05ade6dddddddddddddddddddddddddddddddddddddcbc4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4d61cfa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4fa4f561b7f0d4629b7f0d4629b7f0d4629b7f0d4629a60000000000000000000000000000000000000000b6db6db6db6db6db6db6db6db6db6db6db6db6bf541d41d41d41d41d41d41d41d41d41d41d41d4002ea0ea0ea0ea0ea0ea0ea0ea0ea0ea0ea0ea0ea740b60b60b60b60b60b60b60b60b60b60b60b60a2013e93e93e93e93e93e93e93e93e93e93e93e941460b60b60b60b60b60b60b60b60b60b60b60b5fee7b87b87b87b87b87b87b87b87b87b87b87b878ea521521521521521521521521521521521521503b18c98c98c98c98c98c98c98c98c98c98c98c96c00000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffff95f50750750750750750750750750750750750742cc57c57c57c57c57c57c57c57c57c57c57c57c2fe4d82d82d82d82d82d82d82d82d82d82d82d82b0c65b05b05b05b05b05b05b05b05b05b05b05b0365182d82d82d82d82d82d82d82d82d82d82d82d7479b05b05b05b05b05b05b05b05b05b05b05b059a6a54854854854854854854854854854854854841d39cd9cd9cd9cd9cd9cd9cd9cd9cd9cd9cd9cd760000000000000000000000000000000000000000c71c71c71c71c71c71c71c71c71c71c71c71c6f8d4374374374374374374374374374374374374105d116d889fa66c2ddf4fbc18334a5116d889fa56c0888888888888888888888888888888888888657cb9d6480f2b9d6480f2b9d6480f2b9d6480f2a39cccccccccccccccccccccccccccccccccccccb084d4629b7f0d4629b7f0d4629b7f0d4629b7f0bc4e736736736736736736736736736736736736655a43e7ccb5aee9277605993d220b043e7ccb5ade
}
#define constant TOTAL_SUPPLY = 0xa // 10 tokens
#define constant COEFF_SIZE = 0x14 // 20 byte
#define constant ORDER = 0xffffffffffffffffffffffffffffffffffffffd1
///////////////////////////////////////////////////////////////////////////////
//// INTERFACES ////
///////////////////////////////////////////////////////////////////////////////
#define function name() nonpayable returns (string)
#define function symbol() nonpayable returns (string)
#define function ownerOf(uint256) view returns (address)
#define function balanceOf(address) view returns (uint256)
#define function getApproved(uint256) view returns (address)
#define function approve(address,uint256) nonpayable returns ()
#define function transfer(address, uint256) nonpayable returns ()
#define function transferFrom(address,address,uint256) nonpayable returns ()
///////////////////////////////////////////////////////////////////////////////
//// STORAGE ////
///////////////////////////////////////////////////////////////////////////////
/// @dev Starting slot of the ownership polynomial in reverse coefficient form.
#define constant OWN_SLOT = 0xbabe69babe69babe69babe69babe69
/// @dev Starting slot of the approval polynomial in reverse coefficient form.
#define constant APV_SLOT = 0xface42face42face42face42face42
///////////////////////////////////////////////////////////////////////////////
//// UTIL MACROS ////
///////////////////////////////////////////////////////////////////////////////
/// @dev Utility function to SLOAD a polynomial at a storage slot
/// to the memory at the given memory slot.
#define macro LOAD_POLY(slot) = takes (1) returns (2) {
// input: [m] (memoryOffset)
<slot> // [m, s] (storageSlot)
swap1 // [s, m]
[TOTAL_SUPPLY] // [s, m, l] (length)
POLY_SLOAD() // [m, l]
// output; [m, l] (memoryOffset, length)
}
/// @dev Updates a polynomial so that P(t) = a becomes P(t) = b
/// where P is stored in memory at mP with l coefficients.
///
/// Returns the given tokenId in the stack.
#define macro UPDATE_POLY(poly) = takes (5) returns (1) {
// input: // [t, mP, l, a, b] (point, memOffset, len, old, new)
// find scale amount
[ORDER] // [t, mP, l, a, b, p]
swap2 // [t, mP, l, p, b, a]
dup3 sub // [t, mP, l, p, b, -a] (-a = p - a) in field
addmod // [t, mP, l, v] (v := b - a) in field
// load basis polynomial
__tablestart(Basis) // [t, mP, l, v, c]
dup5 // [t, mP, l, v, c, t]
POLY_OFFSET(COEFF_SIZE, TOTAL_SUPPLY)
// [t, mP, l, v, c, o]
add // [t, mP, l, v, c] (codeOffset)
[COEFF_SIZE] // [t, mP, l, v, c, s] (coefficient size)
dup5 dup5 // [t, mP, l, v, c, s, mP, l]
0x20 mul // [t, mP, l, v, c, s, mP, l'] (l' := l * 32)
add // [t, mP, l, v, c, s, mQ] (memory offset)
dup5 // [t, mP, l, v, c, s, mQ, l]
POLY_CODECOPY() // [t, mP, l, v, mQ, l]
pop // [t, mP, l, v, mQ]
swap2 // [t, mP, mQ, v, l]
swap1 // [t, mP, mQ, l, v]
// scale basis polynomial with (b - a)
POLY_SCALE(ORDER) // [t, mP, mQ, l]
// add scaled basis polynomial to balance polynomial
POLY_ADD(ORDER) // [t, mP, l]
// store the new polynomial
<poly> swap1 // [t, mP, sQ, l]
POLY_SSTORE() // [t, sQ, l]
pop pop // [t]
}
///////////////////////////////////////////////////////////////////////////////
//// HANDLER MACROS ////
///////////////////////////////////////////////////////////////////////////////
/// @dev Returns the string "Huffd1".
#define macro NAME() = takes (0) returns (0) {
0x20 0x00 mstore // [] (mem[0] := offset) (32)
0x06 0x20 mstore // [] (mem[32] := length) (12 hex chars, 6 bytes)
__RIGHTPAD(0x487566666431) // [s] (s := "Huffd1")
0x40 mstore // [] (mem[64] := s)
0x60 0x00 return
}
/// @dev Returns the string "FFD1".
#define macro SYMBOL() = takes (0) returns (0) {
0x20 0x00 mstore // [] (mem[0] := offset) (32)
0x04 0x20 mstore // [] (mem[32] := length) (8 hex chars, 4 bytes)
__RIGHTPAD(0x46464431) // [s] (s := "FFD1")
0x40 mstore // [] (mem[64] := s)
0x60 0x00 return
}
/// @dev takes a token id, and replaces it with the owner of that token.
#define macro OWNER_OF() = takes (1) returns (1) {
0x04 calldataload // [t] (tokenId)
0x00 // [t, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [t, m, l]
dup3 // [t, m, l, t] (token id)
POLY_EVAL(ORDER) // [t, m, l, a] (address)
swap3 // [a, m, l, t]
pop pop pop // [a]
0x00 mstore // [] (mem[0] := a)
0x20 0x00 return
}
/// @dev takes a token id, and replaces it with the address that is approved for that token.
#define macro GET_APPROVED() = takes (0) returns (0) {
0x04 calldataload // [t] (tokenId)
0x00 // [t, m] (memoryOffset)
LOAD_POLY(APV_SLOT) // [t, m, l]
dup3 // [t, m, l, t] (token id)
POLY_EVAL(ORDER) // [t, m, l, a] (address)
swap3 // [a, m, l, t]
pop pop pop // [a]
0x00 mstore // [] (mem[0] := a)
0x20 0x00 return
}
/// @dev Takes a token id, a source and destination address
#define macro TRANSFER_FROM() = takes (0) returns (0) {
0x44 calldataload // [t] (tokenId)
// load ownership polynomial
0x00 // [t, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [t, m, l]
// assert that token is owned by `from` address
dup3 // [t, m, l, t]
POLY_EVAL(ORDER) // [t, m, l, o] (owner)
0x04 calldataload // [t, m, l, o, a] (from address)
eq // [t, m, l, a == o]
success jumpi
// OR, assert that token is approved to `to` address
// load approval polynomial
dup1 // [t, mO, l, mA] (memoryOffset) at the length
LOAD_POLY(APV_SLOT) // [t, mO, l, mA, l]
dup5 // [t, mO, l, mA, l, t]
POLY_EVAL(ORDER) // [t, mO, l, mA, l, w] (approval)
0x24 calldataload // [t, mO, l, mA, l, o, b] (to address)
eq // [t, mO, l, mA, l, b == o]
swap2 pop pop // [t, mO, l, b == o]
success jumpi
0x00 0x00 revert
success:
// [t, m, l]
// update polynomial
0x04 calldataload // [t, m, l, a] (from address)
0x24 calldataload // [t, m, l, a, b] (to address)
UPDATE_POLY(OWN_SLOT) // [t]
0x00 0x00 return
}
/// @dev Takes a token id, a source and destination address
#define macro TRANSFER() = takes (0) returns (0) {
0x24 calldataload // [t] (tokenId)
// load ownership polynomial
0x00 // [t, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [t, m, l]
// assert that token is owner the caller
dup3 // [t, m, l, t]
POLY_EVAL(ORDER) // [t, m, l, o] (owner)
caller // [t, m, l, o, a] (from address)
eq // [t, m, l, a == o]
success jumpi
0x00 0x00 revert
success:
// update polynomial
caller // [t, m, l, a] (from address)
0x04 calldataload // [t, m, l, a, b] (to address)
UPDATE_POLY(OWN_SLOT) // [t]
0x00 0x00 return
}
/// @dev Takes a token id, a source and destination address, approves the
/// given token id to the destination address if source owns it.
#define macro APPROVE() = takes (0) returns (0) {
0x24 calldataload // [t] (tokenId)
// load ownership polynomial
0x00 // [t, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [t, m, l]
// assert that token is owner the caller
dup3 // [t, m, l, t]
POLY_EVAL(ORDER) // [t, m, l, o] (owner)
caller // [t, m, l, o, a] (from address)
eq // [t, m, l, a == o]
success jumpi
0x00 0x00 revert
success:
// load approval polynomial (can override the prev poly)
pop // [t, m] (same memoryOffset)
LOAD_POLY(APV_SLOT) // [t, m, l]
// get current aproval
dup3 // [t, m, l, t]
POLY_EVAL(ORDER) // [t, m, l, a]
// update with the new approve address
0x04 calldataload // [t, m, l, a, b]
UPDATE_POLY(APV_SLOT) // [t]
0x00 0x00 return
}
#define macro BALANCE_OF() = takes (0) returns (0) {
0x04 calldataload // [a] (address)
// load ownership polynomial once at the start
0x00 // [a, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [a, m, l]
0x00 // [a, m, l, s] (total balance initially 0)
swap1 // [a, m, s, l]
0x00 // [a, m, s, l, i] (index starts with 0)
loop_begin:
// [a, m, s, l, i]
// loop condition
dup2 dup2 // [a, m, s, l, i, l, i]
lt iszero // [a, m, s, l, i, i >= l]
loop_end jumpi
// check ownership for token i
dup4 // [a, m, s, l, i, m]
dup3 // [a, m, s, l, i, m, l]
dup3 // [a, m, s, l, i, m, l, i] (token id = index)
POLY_EVAL(ORDER)// [a, m, s, l, i, m, l, o] (owner)
// check if owner is the given address
dup8 // [a, m, s, l, i, m, l, o, a]
eq // [a, m, s, l, i, m, l, eq] (eq := o == a)
// add to total balance
dup6 // [a, m, s, l, i, m, l, eq, s]
add // [a, m, s, l, i, m, l, s'] (s' := s + eq)
swap5 // [a, m, s',l, i, m, l, s]
pop pop pop // [a, m, s, l, i]
// increment index
0x01 add // [a, m, s, l, i'] (i' := i + 1)
// [a, m, s, l, i]
loop_begin jump
loop_end:
pop pop // [a, m, s]
swap2 // [s, m, a]
pop pop // [s]
0x00 mstore // [] (mem[0] := s)
0x20 0x00 return
}
///////////////////////////////////////////////////////////////////////////////
//// MAIN ////
///////////////////////////////////////////////////////////////////////////////
#define macro HUFFD1_CONSTRUCTOR() = takes (0) returns (0) {
OWNED_CONSTRUCTOR()
// the constant polynomial equal to OWNER will result
// in all tokens being owned by that OWNER
[OWNER] sload // [owner]
[OWN_SLOT] sstore // []
}
#define macro HUFFD1_MAIN() = takes (1) returns (1) {
OWNED_MAIN()
dup1 __FUNC_SIG(name) eq name jumpi
dup1 __FUNC_SIG(symbol) eq symbol jumpi
dup1 __FUNC_SIG(ownerOf) eq ownerOf jumpi
dup1 __FUNC_SIG(approve) eq approve jumpi
dup1 __FUNC_SIG(transfer) eq transfer jumpi
dup1 __FUNC_SIG(balanceOf) eq balanceOf jumpi
dup1 __FUNC_SIG(getApproved) eq getApproved jumpi
dup1 __FUNC_SIG(transferFrom) eq transferFrom jumpi
no_match jump
name:
NAME()
symbol:
SYMBOL()
ownerOf:
OWNER_OF()
transfer:
TRANSFER()
transferFrom:
TRANSFER_FROM()
getApproved:
GET_APPROVED()
approve:
APPROVE()
balanceOf:
BALANCE_OF()
no_match:
}