forked from starknet-edu/starknet-messaging-bridge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEvaluator.cairo
281 lines (252 loc) · 9.23 KB
/
Evaluator.cairo
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
# ######## Messaging bridge evaluator
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.math import assert_not_zero
from contracts.utils.ex00_base import (
tuto_erc20_address,
ex_initializer,
has_validated_exercise,
validate_and_distribute_points_once,
only_teacher,
teacher_accounts,
assigned_rank,
assign_rank_to_player,
random_attributes_storage,
max_rank_storage,
)
from contracts.IExerciseSolution import IExerciseSolution
from contracts.Il2nft import Il2nft
from starkware.starknet.common.syscalls import get_contract_address, get_caller_address
from starkware.cairo.common.uint256 import (
Uint256,
uint256_add,
uint256_sub,
uint256_le,
uint256_lt,
uint256_check,
uint256_eq,
)
from starkware.cairo.common.alloc import alloc
from starkware.starknet.common.messages import send_message_to_l1
from contracts.token.ERC20.ITDERC20 import ITDERC20
from contracts.token.ERC20.IERC20 import IERC20
#
# Declaring storage vars
# Storage vars are by default not visible through the ABI. They are similar to "private" variables in Solidity
#
@storage_var
func has_been_paired(contract_address : felt) -> (has_been_paired : felt):
end
@storage_var
func player_exercise_solution_storage(player_address : felt) -> (contract_address : felt):
end
@storage_var
func l1_nft_address_storage() -> (l1_nft_address : felt):
end
@storage_var
func l2_nft_address_storage() -> (l2_nft_address : felt):
end
@storage_var
func l1_users_storage(player_address : felt) -> (l1_user : felt):
end
@storage_var
func l1_dummy_token_address() -> (to_address : felt):
end
@storage_var
func l1_evaluator_address_storage() -> (l1_evaluator_address : felt):
end
@storage_var
func assigned_rand_var_storage(l2_contract : felt) -> (assigned_rand_var : felt):
end
@storage_var
func has_minted_storage(account : felt) -> (l1_user : felt):
end
#
# Declaring getters
# Public variables should be declared explicitly with a getter
#
@view
func player_exercise_solution{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
player_address : felt
) -> (contract_address : felt):
let (contract_address) = player_exercise_solution_storage.read(player_address)
return (contract_address)
end
# ######## Constructor
# This function is called when the contract is deployed
#
@constructor
func constructor{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
_tderc20_address : felt,
_players_registry : felt,
_workshop_id : felt,
dummy_token_address : felt,
l1_nft_address : felt,
l2_nft_address : felt,
l1_evaluator_address : felt,
_first_teacher : felt,
):
ex_initializer(_tderc20_address, _players_registry, _workshop_id)
# Hard coded value for now
max_rank_storage.write(100)
teacher_accounts.write(_first_teacher, 1)
l1_dummy_token_address.write(dummy_token_address)
l1_nft_address_storage.write(l1_nft_address)
l2_nft_address_storage.write(l2_nft_address)
l1_evaluator_address_storage.write(l1_evaluator_address)
return ()
end
# ######## External functions
# These functions are callable by other contracts
#
@external
func ex_0_a{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
l1_user : felt, amount : felt
):
alloc_locals
# Reading caller address
let (sender_address) = get_caller_address()
# Checking that the user got a slot assigned
assign_rank_to_player(sender_address)
let (rank) = assigned_rank(sender_address)
let (secret_value) = random_attributes_storage.read(rank, 0)
# Sending the Mint message.
let (message_payload : felt*) = alloc()
assert message_payload[0] = l1_user
assert message_payload[1] = amount
assert message_payload[2] = secret_value + 32
let (l1_contract_address) = l1_dummy_token_address.read()
send_message_to_l1(to_address=l1_contract_address, payload_size=3, payload=message_payload)
has_minted_storage.write(sender_address, l1_user)
return ()
end
@l1_handler
func ex_0_b{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
from_address : felt, l2_user : felt, l1_user : felt, secret_value : felt
):
# Checking if the user has send the message
let (has_minted) = has_minted_storage.read(l2_user)
with_attr error_message("User did not call ex_0_a"):
assert_not_zero(has_minted)
end
# Make sure the message was sent by the intended L1 contract
let (l1_contract_address) = l1_dummy_token_address.read()
with_attr error_message("Message was not sent by the official L1 contract"):
assert from_address = l1_contract_address
end
let (rank) = assigned_rank(l2_user)
let (value) = random_attributes_storage.read(rank, 0)
with_attr error_message("Wrong secret value"):
assert value = secret_value
end
validate_and_distribute_points_once(l2_user, 0, 2)
return ()
end
@external
func submit_exercise{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
solution_address : felt
):
# Reading caller address
let (sender_address) = get_caller_address()
# Checking this contract was not used by another group before
let (has_solution_been_submitted_before) = has_been_paired.read(solution_address)
with_attr error_message("Solution already submitted"):
assert has_solution_been_submitted_before = 0
end
# Assigning passed ERC20 as player ERC20
player_exercise_solution_storage.write(sender_address, solution_address)
has_been_paired.write(solution_address, 1)
# Checking if player has validated this exercise before
let (has_validated) = has_validated_exercise(sender_address, 0)
# This is necessary because of revoked references. Don't be scared, they won't stay around for too long...
return ()
end
@external
func ex1a{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(l1_user : felt):
alloc_locals
# Reading caller address
let (sender_address) = get_caller_address()
# Retrieve exercise address
let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address)
with_attr error_message("L1 user address is 0"):
assert_not_zero(l1_user)
end
l1_users_storage.write(sender_address, l1_user)
IExerciseSolution.create_l1_nft_message(
contract_address=submited_exercise_address, l1_user=l1_user
)
return ()
end
@l1_handler
func ex1b{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
from_address : felt, l2_user : felt, l1_user : felt
):
let (l1_nft_address) = l1_nft_address_storage.read()
with_attr error_message("Message was not sent by the official L1 contract"):
assert from_address = l1_nft_address
end
let (submited_l1_user) = l1_users_storage.read(l2_user)
with_attr error_message("Not the same L1 user submitted on ex1a"):
assert submited_l1_user = l1_user
end
validate_and_distribute_points_once(l2_user, 1, 2)
return ()
end
@l1_handler
func ex2{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
from_address : felt, l2_user : felt
):
let (l2_nft_address) = l2_nft_address_storage.read()
Il2nft.mint_from_l1(contract_address=l2_nft_address, l2_user=l2_user)
validate_and_distribute_points_once(l2_user, 2, 2)
return ()
end
@external
func ex3_a{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
l1PlayerContract : felt
):
let (sender_address) = get_caller_address()
let (message_payload : felt*) = alloc()
assert message_payload[0] = sender_address
send_message_to_l1(to_address=l1PlayerContract, payload_size=1, payload=message_payload)
return ()
end
@l1_handler
func ex3_b{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
from_address : felt, l2_user : felt
):
let (l1_evaluator_address) = l1_evaluator_address_storage.read()
with_attr error_message("Message was not sent by the official L1 contract"):
assert from_address = l1_evaluator_address
end
validate_and_distribute_points_once(l2_user, 3, 2)
return ()
end
@l1_handler
func ex4_a{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
from_address : felt, l2ReceiverContract : felt, rand_value : felt
):
let (l1_evaluator_address) = l1_evaluator_address_storage.read()
with_attr error_message("Message was not sent by the official L1 contract"):
assert from_address = l1_evaluator_address
end
assigned_rand_var_storage.write(l2ReceiverContract, rand_value)
return ()
end
@external
func ex4_b{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# Reading caller address
let (sender_address) = get_caller_address()
# Retrieve exercise address
let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address)
let (assigned_var) = assigned_rand_var_storage.read(submited_exercise_address)
with_attr error_message("No value was assigned"):
assert_not_zero(assigned_var)
end
let (value) = IExerciseSolution.l1_assigned_var(contract_address=submited_exercise_address)
with_attr error_message("assigned value and actual value don't match"):
assert value = assigned_var
end
validate_and_distribute_points_once(sender_address, 4, 2)
return ()
end