forked from starknet-edu/starknet-cairo-101
-
Notifications
You must be signed in to change notification settings - Fork 10
/
ex04.cairo
154 lines (133 loc) · 4.42 KB
/
ex04.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
# ######## Ex 04
# Reading a mapping
# In this exercise, you need to:
# - Use a function to read a variable
# - Use a function to read a value in a mapping, where the slot you read is the value from the first call
# - Use a function to show you know the correct value of the value in the mapping
# - Your points are credited by the contract
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.starknet.common.syscalls import get_caller_address
from starkware.cairo.common.math import assert_not_zero
from contracts.utils.ex00_base import (
tderc20_address,
has_validated_exercise,
distribute_points,
validate_exercise,
ex_initializer,
)
#
# Declaring storage vars
# Storage vars are by default not visible through the ABI. They are similar to "private" variables in Solidity
#
@storage_var
func user_slots_storage(account : felt) -> (user_slots_storage : felt):
end
@storage_var
func values_mapped_storage(slot : felt) -> (values_mapped_storage : felt):
end
@storage_var
func was_initialized() -> (was_initialized : felt):
end
@storage_var
func next_slot() -> (next_slot : felt):
end
#
# Declaring getters
# Public variables should be declared explicitly with a getter
#
@view
func user_slots{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
account : felt
) -> (user_slot : felt):
let (user_slot) = user_slots_storage.read(account)
return (user_slot)
end
@view
func values_mapped{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
slot : felt
) -> (value : felt):
let (value) = values_mapped_storage.read(slot)
return (value)
end
#
# Constructor
#
@constructor
func constructor{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
_tderc20_address : felt, _players_registry : felt, _workshop_id : felt, _exercise_id : felt
):
ex_initializer(_tderc20_address, _players_registry, _workshop_id, _exercise_id)
return ()
end
#
# External functions
#
@external
func claim_points{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
expected_value : felt
):
# Reading caller address
let (sender_address) = get_caller_address()
with_attr error_message("User slot not assigned. Call assign_user_slot"):
# Checking that the user got a slot assigned
let (user_slot) = user_slots_storage.read(sender_address)
assert_not_zero(user_slot)
end
# Checking that the value provided by the user is the one we expect
# Yes, I'm sneaky
let (value) = values_mapped_storage.read(user_slot)
with_attr error_message("Input value is not the expected secret value"):
assert value = expected_value + 32
end
# Checking if the user has validated the exercice before
validate_exercise(sender_address)
# Sending points to the address specified as parameter
distribute_points(sender_address, 2)
return ()
end
@external
func assign_user_slot{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# Reading caller address
let (sender_address) = get_caller_address()
let (next_slot_temp) = next_slot.read()
let (next_value) = values_mapped_storage.read(next_slot_temp + 1)
if next_value == 0:
user_slots_storage.write(sender_address, 1)
next_slot.write(0)
else:
user_slots_storage.write(sender_address, next_slot_temp + 1)
next_slot.write(next_slot_temp + 1)
end
return ()
end
#
# External functions - Administration
# Only admins can call these. You don't need to understand them to finish the exercice.
#
@external
func set_random_values{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
values_len : felt, values : felt*
):
# Check if the random values were already initialized
let (was_initialized_read) = was_initialized.read()
with_attr error_message("random values already initialized"):
assert was_initialized_read = 0
end
# Storing passed values in the store
set_a_random_value(values_len, values)
# Mark that value store was initialized
was_initialized.write(1)
return ()
end
func set_a_random_value{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
values_len : felt, values : felt*
):
if values_len == 0:
# Start with sum=0.
return ()
end
set_a_random_value(values_len=values_len - 1, values=values + 1)
values_mapped_storage.write(values_len - 1, [values])
return ()
end