Skip to content

Commit 0f0509d

Browse files
authored
[Cairo] Support AccessControlDefaultAdminRules (#698)
1 parent 3d34a00 commit 0f0509d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4477
-481
lines changed

.changeset/sixty-turkeys-pay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openzeppelin/wizard-common': patch
3+
---
4+
5+
Add AI descriptions for AccessControl in Cairo-alpha

.github/workflows/compile-cairo-alpha-project.yml

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,31 @@ jobs:
4747
set -e
4848
4949
declare -a all_kinds=("ERC20" "ERC721" "ERC1155" "Account" "Multisig" "Governor" "Vesting" "Custom")
50-
declare -a all_royalty_info_options=("disabled" "enabled_default" "enabled_custom")
50+
declare -a all_access_options=("disabled" "ownable" "roles" "roles-dar-default" "roles-dar-custom")
51+
declare -a all_royalty_options=("disabled" "enabled-default" "enabled-custom")
5152
for kind in "${all_kinds[@]}"; do
5253
scarb clean
5354
5455
if [[ "$kind" == "ERC721" || "$kind" == "ERC1155" ]]; then
55-
for royalty_info_option in "${all_royalty_info_options[@]}"; do
56-
proj_name="'$kind (royalty info: $royalty_info_option)' test project"
56+
for access_option in "${all_access_options[@]}"; do
57+
for royalty_option in "${all_royalty_options[@]}"; do
58+
proj_name="'$kind, access: $access_option, royalty: $royalty_option' test project"
59+
echo "Generating $proj_name..."
60+
yarn run update_scarb_project --kind=$kind --access=$access_option --royalty=$royalty_option
61+
62+
echo "Compiling $proj_name..."
63+
scarb build
64+
65+
echo "✅ Compiled $proj_name!"
66+
echo "---------------------------------"
67+
done
68+
done
69+
70+
elif [[ "$kind" == "ERC20" || "$kind" == "Custom" ]]; then
71+
for access_option in "${all_access_options[@]}"; do
72+
proj_name="'$kind, access: $access_option' test project"
5773
echo "Generating $proj_name..."
58-
yarn run update_scarb_project $kind $royalty_info_option
74+
yarn run update_scarb_project --kind=$kind --access=$access_option
5975
6076
echo "Compiling $proj_name..."
6177
scarb build
@@ -68,7 +84,7 @@ jobs:
6884
proj_name="'$kind' test project"
6985
7086
echo "Generating $proj_name..."
71-
yarn run update_scarb_project $kind
87+
yarn run update_scarb_project --kind=$kind
7288
7389
echo "Compiling $proj_name..."
7490
scarb build

packages/common/src/ai/descriptions/cairo.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ export const cairoCommonDescriptions = {
2727
'Provides information for how much royalty is owed and to whom, based on a sale price. Follows ERC-2981 standard.',
2828
};
2929

30+
export const cairoAlphaAccessDescriptions = {
31+
accessType:
32+
'The type of access control to provision. Ownable is a simple mechanism with a single account authorized for all privileged actions. Roles is a flexible mechanism with a separate role for each privileged action. A role can have many authorized accounts. Roles (Default Admin Rules) provides additional enforced security measures on top of standard Roles mechanism for managing the most privileged role: default admin.',
33+
darInitialDelay: 'The initial delay for the default admin role (in case Roles (Default Admin Rules) is used).',
34+
darDefaultDelayIncrease:
35+
'The default delay increase for the default admin role (in case Roles (Default Admin Rules) is used).',
36+
};
37+
3038
export const cairoRoyaltyInfoDescriptions = {
3139
enabled: 'Whether to enable royalty feature for the contract',
3240
defaultRoyaltyFraction:

packages/core/cairo_alpha/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Add AccessControlDefaultAdminRules. ([#698](https://github.com/OpenZeppelin/contracts-wizard/pull/698))
6+
57
- **Breaking changes**:
68
- Use OpenZeppelin Contracts for Cairo v3.0.0-alpha.3. ([#688](https://github.com/OpenZeppelin/contracts-wizard/pull/688))
79
- Use OpenZeppelin Contracts for Cairo v3.0.0-alpha.2. ([#663](https://github.com/OpenZeppelin/contracts-wizard/pull/663))

packages/core/cairo_alpha/src/common-options.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Argument } from './contract';
22
import type { Access } from './set-access-control';
3+
import { AccessControl } from './set-access-control';
34
import type { Info } from './set-info';
45
import { defaults as infoDefaults } from './set-info';
56
import type { Upgradeable } from './set-upgradeable';
@@ -11,7 +12,7 @@ export const defaults: Required<CommonOptions> = {
1112

1213
export const contractDefaults: Required<CommonContractOptions> = {
1314
...defaults,
14-
access: false,
15+
access: AccessControl.None(),
1516
} as const;
1617

1718
export interface CommonOptions {

packages/core/cairo_alpha/src/custom.test.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { custom } from '.';
44
import type { CustomOptions } from './custom';
55
import { buildCustom } from './custom';
66
import { printContract } from './print';
7+
import { AccessControl, darDefaultOpts, darCustomOpts } from './set-access-control';
78

89
function testCustom(title: string, opts: Partial<CustomOptions>) {
910
test(title, t => {
@@ -48,20 +49,28 @@ testCustom('upgradeable', {
4849

4950
testCustom('access control disabled', {
5051
upgradeable: false,
51-
access: false,
52+
access: AccessControl.None(),
5253
});
5354

5455
testCustom('access control ownable', {
55-
access: 'ownable',
56+
access: AccessControl.Ownable(),
5657
});
5758

5859
testCustom('access control roles', {
59-
access: 'roles',
60+
access: AccessControl.Roles(),
61+
});
62+
63+
testCustom('access control roles default admin rules (default opts)', {
64+
access: AccessControl.RolesDefaultAdminRules(darDefaultOpts),
65+
});
66+
67+
testCustom('access control roles default admin rules (custom opts)', {
68+
access: AccessControl.RolesDefaultAdminRules(darCustomOpts),
6069
});
6170

6271
testCustom('pausable with access control disabled', {
6372
// API should override access to true since it is required for pausable
64-
access: false,
73+
access: AccessControl.None(),
6574
pausable: true,
6675
upgradeable: false,
6776
});
@@ -70,7 +79,7 @@ testAPIEquivalence('custom API default');
7079

7180
testAPIEquivalence('custom API full upgradeable', {
7281
name: 'CustomContract',
73-
access: 'roles',
82+
access: AccessControl.Roles(),
7483
pausable: true,
7584
upgradeable: true,
7685
});

packages/core/cairo_alpha/src/custom.test.ts.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,169 @@ Generated by [AVA](https://avajs.dev).
380380
}␊
381381
`
382382

383+
## access control roles default admin rules (default opts)
384+
385+
> Snapshot 1
386+
387+
`// SPDX-License-Identifier: MIT␊
388+
// Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.3␊
389+
390+
const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊
391+
392+
#[starknet::contract]␊
393+
mod MyContract {␊
394+
use openzeppelin::access::accesscontrol::extensions::{␊
395+
AccessControlDefaultAdminRulesComponent,␊
396+
DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊
397+
};␊
398+
use openzeppelin::interfaces::upgrades::IUpgradeable;␊
399+
use openzeppelin::introspection::src5::SRC5Component;␊
400+
use openzeppelin::upgrades::UpgradeableComponent;␊
401+
use starknet::{ClassHash, ContractAddress};␊
402+
use super::UPGRADER_ROLE;␊
403+
404+
const INITIAL_DELAY: u64 = 86400; // 1 day␊
405+
406+
component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊
407+
component!(path: SRC5Component, storage: src5, event: SRC5Event);␊
408+
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊
409+
410+
// External␊
411+
#[abi(embed_v0)]␊
412+
impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl<ContractState>;␊
413+
414+
// Internal␊
415+
impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl<ContractState>;␊
416+
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊
417+
418+
#[storage]␊
419+
struct Storage {␊
420+
#[substorage(v0)]␊
421+
accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊
422+
#[substorage(v0)]␊
423+
src5: SRC5Component::Storage,␊
424+
#[substorage(v0)]␊
425+
upgradeable: UpgradeableComponent::Storage,␊
426+
}␊
427+
428+
#[event]␊
429+
#[derive(Drop, starknet::Event)]␊
430+
enum Event {␊
431+
#[flat]␊
432+
AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊
433+
#[flat]␊
434+
SRC5Event: SRC5Component::Event,␊
435+
#[flat]␊
436+
UpgradeableEvent: UpgradeableComponent::Event,␊
437+
}␊
438+
439+
#[constructor]␊
440+
fn constructor(␊
441+
ref self: ContractState,␊
442+
initial_default_admin: ContractAddress,␊
443+
upgrader: ContractAddress,␊
444+
) {␊
445+
self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊
446+
447+
self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊
448+
}␊
449+
450+
//␊
451+
// Upgradeable␊
452+
//␊
453+
454+
#[abi(embed_v0)]␊
455+
impl UpgradeableImpl of IUpgradeable<ContractState> {␊
456+
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊
457+
self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊
458+
self.upgradeable.upgrade(new_class_hash);␊
459+
}␊
460+
}␊
461+
}␊
462+
`
463+
464+
## access control roles default admin rules (custom opts)
465+
466+
> Snapshot 1
467+
468+
`// SPDX-License-Identifier: MIT␊
469+
// Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.3␊
470+
471+
const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊
472+
473+
#[starknet::contract]␊
474+
mod MyContract {␊
475+
use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊
476+
use openzeppelin::interfaces::upgrades::IUpgradeable;␊
477+
use openzeppelin::introspection::src5::SRC5Component;␊
478+
use openzeppelin::upgrades::UpgradeableComponent;␊
479+
use starknet::{ClassHash, ContractAddress};␊
480+
use super::UPGRADER_ROLE;␊
481+
482+
const INITIAL_DELAY: u64 = 172800; // 2 days␊
483+
484+
component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊
485+
component!(path: SRC5Component, storage: src5, event: SRC5Event);␊
486+
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊
487+
488+
// External␊
489+
#[abi(embed_v0)]␊
490+
impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl<ContractState>;␊
491+
492+
// Internal␊
493+
impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl<ContractState>;␊
494+
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊
495+
496+
#[storage]␊
497+
struct Storage {␊
498+
#[substorage(v0)]␊
499+
accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊
500+
#[substorage(v0)]␊
501+
src5: SRC5Component::Storage,␊
502+
#[substorage(v0)]␊
503+
upgradeable: UpgradeableComponent::Storage,␊
504+
}␊
505+
506+
#[event]␊
507+
#[derive(Drop, starknet::Event)]␊
508+
enum Event {␊
509+
#[flat]␊
510+
AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊
511+
#[flat]␊
512+
SRC5Event: SRC5Component::Event,␊
513+
#[flat]␊
514+
UpgradeableEvent: UpgradeableComponent::Event,␊
515+
}␊
516+
517+
#[constructor]␊
518+
fn constructor(␊
519+
ref self: ContractState,␊
520+
initial_default_admin: ContractAddress,␊
521+
upgrader: ContractAddress,␊
522+
) {␊
523+
self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊
524+
525+
self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊
526+
}␊
527+
528+
impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊
529+
const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊
530+
}␊
531+
532+
//␊
533+
// Upgradeable␊
534+
//␊
535+
536+
#[abi(embed_v0)]␊
537+
impl UpgradeableImpl of IUpgradeable<ContractState> {␊
538+
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊
539+
self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊
540+
self.upgradeable.upgrade(new_class_hash);␊
541+
}␊
542+
}␊
543+
}␊
544+
`
545+
383546
## pausable with access control disabled
384547

385548
> Snapshot 1
307 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)