Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate access control #605

Merged
merged 52 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f9b76f9
add accesscontrol
andrew-fleming Apr 11, 2023
926221a
add accesscontrol tests
andrew-fleming Apr 11, 2023
a55b6ef
remove mock, add impl to contract
andrew-fleming Apr 13, 2023
8f559e1
fix formatting
andrew-fleming Apr 13, 2023
c703136
remove accesscontrol mock
andrew-fleming Apr 13, 2023
8e7f00d
formatting, remove unused imports
andrew-fleming Apr 13, 2023
7227472
update branch
andrew-fleming Apr 26, 2023
6a8bf41
integrate erc165
andrew-fleming Apr 26, 2023
91fb4ca
fix typo
andrew-fleming Apr 26, 2023
4e356b0
Merge branch 'cairo-1' into cairo1-accesscontrol
andrew-fleming Apr 28, 2023
cad0760
update cairo to alpha7
andrew-fleming Apr 28, 2023
f58af18
update Cargo
andrew-fleming Apr 28, 2023
ac99ba5
update expected syntax
andrew-fleming Apr 28, 2023
0338489
Merge branch 'cairo-1' into cairo1-accesscontrol
andrew-fleming Apr 28, 2023
3888230
update expected syntax
andrew-fleming Apr 28, 2023
c50073a
Merge branch 'cairo-1' into cairo1-accesscontrol
andrew-fleming Apr 28, 2023
1db700b
update cairo to rc0
andrew-fleming May 6, 2023
abad2af
update Cargo
andrew-fleming May 6, 2023
89dc503
fix import
andrew-fleming May 6, 2023
054534f
simplify imports
andrew-fleming May 6, 2023
e987ee7
Apply suggestions from code review
andrew-fleming May 8, 2023
5b45cbe
fix storage mapping name
andrew-fleming May 8, 2023
c5a4a8b
rename impl
andrew-fleming May 8, 2023
76feaab
add warning
andrew-fleming May 8, 2023
85334b2
fix comment
andrew-fleming May 8, 2023
68ae5fc
remove constructor, setup test constructor in setup
andrew-fleming May 8, 2023
b55b3ba
fix format
andrew-fleming May 8, 2023
23ff2c6
fix import format
andrew-fleming May 8, 2023
65c9315
add test for granting already granted role
andrew-fleming May 9, 2023
5848197
add clarity to revoke role test
andrew-fleming May 9, 2023
de6fc51
add test for revoking already revoked role
andrew-fleming May 9, 2023
df6ad78
add test for renouncing already renounced role
andrew-fleming May 9, 2023
1c5df0d
add test for revoked admin role losing privileges
andrew-fleming May 9, 2023
79c979b
fix test_role_admin_cycle
andrew-fleming May 9, 2023
cc0695a
add target func as comment
andrew-fleming May 9, 2023
b8356d9
add default admin tests
andrew-fleming May 9, 2023
7ae0fee
refactor tests, rename actors
andrew-fleming May 10, 2023
74ddf7b
add tests for has_role and set_role_admin
andrew-fleming May 10, 2023
bd6943a
tidy up tests
andrew-fleming May 10, 2023
ec7660c
add general doc for events
andrew-fleming May 10, 2023
1b01b8f
fix assert_only_role test
andrew-fleming May 11, 2023
60d6592
remove redundant test
andrew-fleming May 11, 2023
574bdac
remove unnecessary assertion
andrew-fleming May 11, 2023
e48749a
remove duplicate test
andrew-fleming May 11, 2023
42961db
Update src/openzeppelin/access/accesscontrol.cairo
andrew-fleming May 11, 2023
974326c
fix imports, define constants locally
andrew-fleming May 11, 2023
0158a22
fix conflicts
andrew-fleming May 14, 2023
b0d58c1
Apply suggestions from code review
andrew-fleming May 18, 2023
25acc99
fix test name
andrew-fleming May 18, 2023
621654a
fix conflict
andrew-fleming May 19, 2023
5b85350
bump cairo
andrew-fleming May 19, 2023
80e62d7
fix formatting
andrew-fleming May 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/openzeppelin/access.cairo
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
mod accesscontrol;
mod ownable;
151 changes: 151 additions & 0 deletions src/openzeppelin/access/accesscontrol.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use starknet::ContractAddress;

const DEFAULT_ADMIN_ROLE: felt252 = 0;
const IACCESSCONTROL_ID: u32 = 0x7965db0b_u32;

#[abi]
trait IAccessControl {
fn has_role(role: felt252, account: ContractAddress) -> bool;
fn get_role_admin(role: felt252) -> felt252;
fn grant_role(role: felt252, account: ContractAddress);
fn revoke_role(role: felt252, account: ContractAddress);
fn renounce_role(role: felt252, account: ContractAddress);
}

#[contract]
mod AccessControl {
use super::IAccessControl;
use super::DEFAULT_ADMIN_ROLE;
use super::IACCESSCONTROL_ID;
use openzeppelin::introspection::erc165::ERC165;
use starknet::ContractAddress;
use starknet::get_caller_address;

struct Storage {
role_admin: LegacyMap<felt252, felt252>,
role_members: LegacyMap<(felt252, ContractAddress), bool>,
}

/// Emitted when `account` is granted `role`.
///
/// `sender` is the account that originated the contract call, an admin role
/// bearer (except if `_grant_role` is called during initialization from the constructor).
#[event]
fn RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress) {}

/// Emitted when `account` is revoked `role`.
///
/// `sender` is the account that originated the contract call:
/// - If using `revoke_role`, it is the admin role bearer.
/// - If using `renounce_role`, it is the role bearer (i.e. `account`).
#[event]
fn RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress) {}
martriay marked this conversation as resolved.
Show resolved Hide resolved

/// Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`
///
/// `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
/// {RoleAdminChanged} not being emitted signaling this.
#[event]
fn RoleAdminChanged(role: felt252, previous_admin_role: felt252, new_admin_role: felt252) {}

impl AccessControlImpl of IAccessControl {
fn has_role(role: felt252, account: ContractAddress) -> bool {
role_members::read((role, account))
}

fn get_role_admin(role: felt252) -> felt252 {
role_admin::read(role)
}

fn grant_role(role: felt252, account: ContractAddress) {
let admin = get_role_admin(role);
assert_only_role(admin);
_grant_role(role, account);
}

fn revoke_role(role: felt252, account: ContractAddress) {
let admin: felt252 = get_role_admin(role);
assert_only_role(admin);
_revoke_role(role, account);
}

fn renounce_role(role: felt252, account: ContractAddress) {
let caller: ContractAddress = get_caller_address();
assert(caller == account, 'Can only renounce role for self');
_revoke_role(role, account);
}
}

#[view]
fn supports_interface(interface_id: u32) -> bool {
ERC165::supports_interface(interface_id)
}

#[view]
fn has_role(role: felt252, account: ContractAddress) -> bool {
AccessControlImpl::has_role(role, account)
}

#[view]
fn get_role_admin(role: felt252) -> felt252 {
AccessControlImpl::get_role_admin(role)
}

#[external]
fn grant_role(role: felt252, account: ContractAddress) {
AccessControlImpl::grant_role(role, account);
}

#[external]
fn revoke_role(role: felt252, account: ContractAddress) {
AccessControlImpl::revoke_role(role, account);
}

#[external]
fn renounce_role(role: felt252, account: ContractAddress) {
AccessControlImpl::renounce_role(role, account);
}

#[internal]
fn initializer() {
ERC165::register_interface(IACCESSCONTROL_ID);
}

#[internal]
fn assert_only_role(role: felt252) {
let caller: ContractAddress = get_caller_address();
let authorized: bool = has_role(role, caller);
assert(authorized, 'Caller is missing role');
}

//
// WARNING
// The following internal methods are unprotected and should not be used
// outside of a contract's constructor.
//

#[internal]
fn _grant_role(role: felt252, account: ContractAddress) {
if !has_role(role, account) {
let caller: ContractAddress = get_caller_address();
role_members::write((role, account), true);
RoleGranted(role, account, caller);
}
}

#[internal]
fn _revoke_role(role: felt252, account: ContractAddress) {
if has_role(role, account) {
let caller: ContractAddress = get_caller_address();
role_members::write((role, account), false);
RoleRevoked(role, account, caller);
}
}

#[internal]
fn _set_role_admin(role: felt252, admin_role: felt252) {
let previous_admin_role: felt252 = get_role_admin(role);
role_admin::write(role, admin_role);
RoleAdminChanged(role, previous_admin_role, admin_role);
}
}
1 change: 1 addition & 0 deletions src/openzeppelin/tests.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod test_accesscontrol;
mod test_reentrancyguard;
mod test_ownable;
mod test_erc165;
Expand Down
Loading