Skip to content

Commit a3632a9

Browse files
feat: implement whitelist component and contract
- Add WhitelistComponent with admin-controlled whitelist functionality - Create WhitelistedContract that uses the whitelist component - Add basic whitelist management functions (add/remove/check) - Implement admin-only access control for whitelist management - Add events for whitelist address changes - Update project dependencies and configuration
1 parent 3489e4a commit a3632a9

5 files changed

Lines changed: 121 additions & 54 deletions

File tree

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
scarb 2.11.4

Scarb.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ edition = "2024_07"
66
# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html
77
# [executable]
88
[dependencies]
9+
starknet = "2.11.4"
910

1011
[cairo]
1112
enable-gas = false
1213

1314
[dev-dependencies]
14-
cairo_test = "2.11.2"
15-
# cairo_execute = "2.11.3"

src/lib.cairo

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,2 @@
1-
fn main() {
2-
// Function calls (Uncomment to execute them)
3-
// say_name("Sylvia Nnoruka!");
4-
// intro_to_felt();
5-
6-
let num_1 = 5;
7-
let num_2 = 10;
8-
let sum = sum_num(num_1, num_2);
9-
println!("The sum of {} and {} is = {}", num_1, num_2, sum);
10-
11-
// check_u16(6553); // Uncomment if needed
12-
is_greater_than_50(3);
13-
}
14-
15-
// DATA TYPES IN CAIRO
16-
// - felts: felt252 (Field elements)
17-
// - ByteArray: Represents a sequence of bytes
18-
// - Integers:
19-
// - Signed: i8, i16, i32, i64, i128, i256
20-
// - Unsigned: u8, u16, u32, u64, u128, u256
21-
// - Boolean: bool
22-
23-
// Function to demonstrate ByteArray usage
24-
fn say_name(x: ByteArray) {
25-
println!("{}", x);
26-
}
27-
28-
// Function to demonstrate felt252 usage
29-
fn intro_to_felt() {
30-
let x = 40000;
31-
println!("{}", x);
32-
}
33-
34-
// Function to sum two u8 integers
35-
fn sum_num(x: u8, y: u8) -> u8 {
36-
return x + y;
37-
}
38-
39-
// Function to print a u16 integer
40-
fn check_u16(x: u16) {
41-
println!("{x}");
42-
}
43-
44-
// Function to check if a u32 integer is greater than 50
45-
fn is_greater_than_50(x: u32) -> bool {
46-
if x > 50 {
47-
println!("true");
48-
return true;
49-
}
50-
println!("false");
51-
return false;
52-
}
1+
pub mod whitelist_component;
2+
pub mod whitelist_contract;

src/whitelist_component.cairo

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use starknet::ContractAddress;
2+
3+
#[starknet::interface]
4+
pub trait IWhitelist<TContractState> {
5+
fn add_to_whitelist(ref self: TContractState, address: ContractAddress);
6+
fn remove_from_whitelist(ref self: TContractState, address: ContractAddress);
7+
fn is_whitelisted(self: @TContractState, address: ContractAddress) -> bool;
8+
}
9+
10+
#[starknet::component]
11+
pub mod WhitelistComponent {
12+
use starknet::storage::{
13+
Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess,
14+
StoragePointerWriteAccess,
15+
};
16+
use starknet::{ContractAddress, get_caller_address};
17+
use super::IWhitelist;
18+
19+
#[storage]
20+
pub struct Storage {
21+
admin: ContractAddress,
22+
whitelist_addresses: Map<ContractAddress, bool>,
23+
}
24+
25+
#[event]
26+
#[derive(Drop, starknet::Event)]
27+
pub enum Event {
28+
AddressAdded: AddressAdded,
29+
AddressRemoved: AddressRemoved,
30+
}
31+
32+
#[derive(Drop, starknet::Event)]
33+
pub struct AddressAdded {
34+
address: ContractAddress,
35+
}
36+
37+
#[derive(Drop, starknet::Event)]
38+
pub struct AddressRemoved {
39+
address: ContractAddress,
40+
}
41+
42+
#[embeddable_as(WhitelistComponent)]
43+
pub impl WhitelistComponentImpl<
44+
TContractState, +HasComponent<TContractState>,
45+
> of IWhitelist<ComponentState<TContractState>> {
46+
fn add_to_whitelist(ref self: ComponentState<TContractState>, address: ContractAddress) {
47+
self.only_admin(get_caller_address());
48+
self.whitelist_addresses.write(address, true);
49+
self.emit(Event::AddressAdded(AddressAdded { address }));
50+
}
51+
52+
fn remove_from_whitelist(
53+
ref self: ComponentState<TContractState>, address: ContractAddress,
54+
) {
55+
self.only_admin(get_caller_address());
56+
self.whitelist_addresses.write(address, false);
57+
self.emit(Event::AddressRemoved(AddressRemoved { address }));
58+
}
59+
60+
fn is_whitelisted(self: @ComponentState<TContractState>, address: ContractAddress) -> bool {
61+
self.whitelist_addresses.read(address)
62+
}
63+
}
64+
65+
#[generate_trait]
66+
pub impl InternalImpl<
67+
TContractState, +HasComponent<TContractState>,
68+
> of InternalTrait<TContractState> {
69+
fn initializer(ref self: ComponentState<TContractState>, admin: ContractAddress) {
70+
self.admin.write(admin);
71+
}
72+
73+
fn only_admin(self: @ComponentState<TContractState>, caller: ContractAddress) {
74+
let admin: ContractAddress = self.admin.read();
75+
76+
assert(caller == admin, 'Caller not Admin');
77+
}
78+
}
79+
}

src/whitelist_contract.cairo

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#[starknet::contract]
2+
mod WhitelistedContract {
3+
use starknet::get_caller_address;
4+
use crate::whitelist_component::WhitelistComponent;
5+
6+
component!(path: WhitelistComponent, storage: whitelist, event: WhitelistEvent);
7+
8+
#[abi(embed_v0)]
9+
impl WhitelistImpl = WhitelistComponent::WhitelistComponent<ContractState>;
10+
impl InternalImpl = WhitelistComponent::InternalImpl<ContractState>;
11+
12+
#[storage]
13+
pub struct Storage {
14+
#[substorage(v0)]
15+
whitelist: WhitelistComponent::Storage,
16+
}
17+
18+
#[event]
19+
#[derive(Drop, starknet::Event)]
20+
pub enum Event {
21+
WhitelistEvent: WhitelistComponent::Event,
22+
}
23+
24+
#[constructor]
25+
fn constructor(ref self: ContractState) {
26+
let deployer = get_caller_address();
27+
self.whitelist.initializer(deployer);
28+
}
29+
30+
#[external(v0)]
31+
fn whitelisted_function(ref self: ContractState) -> felt252 {
32+
// Only whitelisted addresses can call this function
33+
let caller = get_caller_address();
34+
assert(self.whitelist.is_whitelisted(caller), 'Caller is not whitelisted');
35+
36+
'success'
37+
}
38+
}

0 commit comments

Comments
 (0)