forked from starknet-edu/starknet-cairo-101
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ex12.cairo
157 lines (133 loc) · 4.5 KB
/
ex12.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
// ######## Ex 12
// Events
// In this exercise, you need to:
// - Use a function to get assigned a private variable
// - Use a function to emit event with the value of the private variable
// - Your points are credited by the contract
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.math import assert_not_zero
from starkware.starknet.common.syscalls import get_caller_address
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) {
}
@storage_var
func values_mapped_secret_storage(slot: felt) -> (values_mapped_secret_storage: felt) {
}
@storage_var
func was_initialized() -> (was_initialized: felt) {
}
@storage_var
func next_slot() -> (next_slot: felt) {
}
@event
func assign_user_slot_called(account: felt, secret_value: felt) {
}
//
// 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,);
}
//
// 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 ();
}
//
// 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();
// Checking that the user got a slot assigned
let (user_slot) = user_slots_storage.read(sender_address);
with_attr error_message("User slot not assigned. Call assign_user_slot") {
assert_not_zero(user_slot);
}
// Checking that the value provided by the user is the one we expect
// Still sneaky.
// Or not. Is this psyops?
let (value) = values_mapped_secret_storage.read(user_slot);
with_attr error_message("Input value is not the expected secret value") {
assert value = expected_value;
}
// Checking if the user has validated the exercise before
validate_exercise(sender_address);
// Sending points to the address specified as parameter
distribute_points(sender_address, 2);
return ();
}
@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_secret_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);
}
let (user_slot) = user_slots_storage.read(sender_address);
let (secret_value) = values_mapped_secret_storage.read(user_slot);
// Emit an event with secret value
assign_user_slot_called.emit(sender_address, secret_value + 32);
return ();
}
//
// External functions - Administration
// Only admins can call these. You don't need to understand them to finish the exercise.
//
@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;
}
// Storing passed values in the store
set_a_random_value(values_len, values);
// Mark that value store was initialized
was_initialized.write(1);
return ();
}
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 ();
}
set_a_random_value(values_len=values_len - 1, values=values + 1);
values_mapped_secret_storage.write(values_len - 1, [values]);
return ();
}