From ba2e792bf347b640ece5bc06e0cccc436ebcae0f Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 19 Aug 2025 13:18:22 +0300 Subject: [PATCH 01/40] Add AccessControlDefaultAdminRulesComponent to set-access-control --- .../cairo_alpha/src/set-access-control.ts | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index 33014de5b..70d3dc4ed 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -2,7 +2,7 @@ import type { BaseFunction, BaseImplementedTrait, ContractBuilder } from './cont import { defineComponents } from './utils/define-components'; import { addSRC5Component } from './common-components'; -export const accessOptions = [false, 'ownable', 'roles'] as const; +export const accessOptions = [false, 'ownable', 'roles', 'roles-default-admin-rules'] as const; export const DEFAULT_ACCESS_CONTROL = 'ownable'; export type Access = (typeof accessOptions)[number]; @@ -55,6 +55,41 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { } break; } + case 'roles-default-admin-rules': { + const initParams = [{ lit: 'INITIAL_DELAY' }, { lit: 'initial_default_admin' }]; + if (c.addComponent(components.AccessControlDefaultAdminRulesComponent, initParams, true)) { + if (c.interfaceFlags.has('ISRC5')) { + c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { + name: 'AccessControlDefaultAdminRulesImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl', + }); + c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { + name: 'AccessControlImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlImpl', + }); + c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { + name: 'AccessControlCamelImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl', + }); + c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { + name: 'AccessControlWithDelayImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl', + }); + } else { + c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { + name: 'AccessControlMixinImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl', + }); + c.addInterfaceFlag('ISRC5'); + } + addSRC5Component(c); + + c.addUseClause('starknet', 'ContractAddress'); + c.addConstructorArgument({ name: 'initial_default_admin', type: 'ContractAddress' }); + + } + break; + } } } @@ -79,22 +114,26 @@ export function requireAccessControl( c.addFunctionCodeBefore(trait, fn, 'self.ownable.assert_only_owner()'); break; } - case 'roles': { + case 'roles': + case 'roles-default-admin-rules': { const roleId = roleIdPrefix + '_ROLE'; const addedSuper = c.addSuperVariable({ name: roleId, type: 'felt252', value: `selector!("${roleId}")`, }); + const substorageName = access === 'roles-default-admin-rules' + ? components.AccessControlDefaultAdminRulesComponent.substorage.name + : components.AccessControlComponent.substorage.name; if (roleOwner !== undefined) { c.addUseClause('starknet', 'ContractAddress'); c.addConstructorArgument({ name: roleOwner, type: 'ContractAddress' }); if (addedSuper) { - c.addConstructorCode(`self.accesscontrol._grant_role(${roleId}, ${roleOwner})`); + c.addConstructorCode(`self.${substorageName}._grant_role(${roleId}, ${roleOwner})`); } } - c.addFunctionCodeBefore(trait, fn, `self.accesscontrol.assert_only_role(${roleId})`); + c.addFunctionCodeBefore(trait, fn, `self.${substorageName}.assert_only_role(${roleId})`); break; } @@ -142,4 +181,26 @@ const components = defineComponents({ }, ], }, + AccessControlDefaultAdminRulesComponent: { + path: 'openzeppelin_access::accesscontrol::extensions', + substorage: { + name: 'accesscontrol_DAR', + type: 'AccessControlDefaultAdminRulesComponent::Storage', + }, + event: { + name: 'AccessControlDefaultAdminRulesEvent', + type: 'AccessControlDefaultAdminRulesComponent::Event', + }, + impls: [ + { + name: 'AccessControlMixinImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl', + }, + { + name: 'AccessControlDefaultAdminRulesInternalImpl', + embed: false, + value: 'AccessControlDefaultAdminRulesComponent::InternalImpl', + }, + ], + } }); From 80e8cd7fe9d3f3535961fbfc0218aa1c9ce761f4 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 19 Aug 2025 13:18:37 +0300 Subject: [PATCH 02/40] Add basic support for AccessControlDefaultAdminRulesComponent in UI --- .../cairo_alpha/AccessControlSection.svelte | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/ui/src/cairo_alpha/AccessControlSection.svelte b/packages/ui/src/cairo_alpha/AccessControlSection.svelte index 9df0e3195..b4a399605 100644 --- a/packages/ui/src/cairo_alpha/AccessControlSection.svelte +++ b/packages/ui/src/cairo_alpha/AccessControlSection.svelte @@ -6,7 +6,7 @@ export let access: Access; export let required: boolean; - let defaultValueWhenEnabled: 'ownable' | 'roles' = 'ownable'; + let defaultValueWhenEnabled: 'ownable' | 'roles' | 'roles-default-admin-rules' = 'ownable'; let wasRequired = required; let wasAccess = access; @@ -44,12 +44,19 @@ Simple mechanism with a single account authorized for all privileged actions. - + + From efe47ba81bc6fe277662c02041efc80365bdd793 Mon Sep 17 00:00:00 2001 From: immrsd Date: Thu, 25 Sep 2025 11:02:59 +0300 Subject: [PATCH 03/40] Use IERC2981Admin impl for AccessControlDefaultAdminRules --- .../core/cairo_alpha/src/set-access-control.ts | 18 +++++++----------- .../core/cairo_alpha/src/set-royalty-info.ts | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index 70d3dc4ed..42f1cc026 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -59,14 +59,14 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { const initParams = [{ lit: 'INITIAL_DELAY' }, { lit: 'initial_default_admin' }]; if (c.addComponent(components.AccessControlDefaultAdminRulesComponent, initParams, true)) { if (c.interfaceFlags.has('ISRC5')) { - c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { - name: 'AccessControlDefaultAdminRulesImpl', - value: 'AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl', - }); c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { name: 'AccessControlImpl', value: 'AccessControlDefaultAdminRulesComponent::AccessControlImpl', }); + c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { + name: 'AccessControlDefaultAdminRulesImpl', + value: 'AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl', + }); c.addImplToComponent(components.AccessControlDefaultAdminRulesComponent, { name: 'AccessControlCamelImpl', value: 'AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl', @@ -86,7 +86,7 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { c.addUseClause('starknet', 'ContractAddress'); c.addConstructorArgument({ name: 'initial_default_admin', type: 'ContractAddress' }); - + c.addConstructorArgument({ name: 'initial_default_admin', type: 'ContractAddress' }); } break; } @@ -182,9 +182,9 @@ const components = defineComponents({ ], }, AccessControlDefaultAdminRulesComponent: { - path: 'openzeppelin_access::accesscontrol::extensions', + path: 'openzeppelin::access::accesscontrol::extensions', substorage: { - name: 'accesscontrol_DAR', + name: 'accesscontrol_dar', type: 'AccessControlDefaultAdminRulesComponent::Storage', }, event: { @@ -192,10 +192,6 @@ const components = defineComponents({ type: 'AccessControlDefaultAdminRulesComponent::Event', }, impls: [ - { - name: 'AccessControlMixinImpl', - value: 'AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl', - }, { name: 'AccessControlDefaultAdminRulesInternalImpl', embed: false, diff --git a/packages/core/cairo_alpha/src/set-royalty-info.ts b/packages/core/cairo_alpha/src/set-royalty-info.ts index ae13ee2a0..a8f89d9d2 100644 --- a/packages/core/cairo_alpha/src/set-royalty-info.ts +++ b/packages/core/cairo_alpha/src/set-royalty-info.ts @@ -90,6 +90,21 @@ export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, }); c.addConstructorCode('self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin)'); break; + case 'roles-default-admin-rules': + c.addImplToComponent(components.ERC2981Component, { + name: 'ERC2981AdminAccessControlDefaultAdminRulesImpl', + value: `ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl`, + }); + c.addConstructorArgument({ + name: 'royalty_admin', + type: 'ContractAddress', + }); + c.addConstructorCode('self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin)'); + break; + default: { + const _: never = access; + throw new Error('Unknown access control option'); + } } if (feeDenominator === DEFAULT_FEE_DENOMINATOR) { From 95bc5af16dd50ba7909a8f95a2c896e6da12e6ab Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:01:41 +0300 Subject: [PATCH 04/40] Update set-acess-control to support AccessControlDefaultAdminRules --- .../cairo_alpha/src/set-access-control.ts | 136 +++++++++++++++--- 1 file changed, 117 insertions(+), 19 deletions(-) diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index 42f1cc026..5156ec36d 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -1,23 +1,60 @@ import type { BaseFunction, BaseImplementedTrait, ContractBuilder } from './contract'; import { defineComponents } from './utils/define-components'; import { addSRC5Component } from './common-components'; +import { durationToSeconds } from './utils/duration'; +import { OptionsError } from './error'; +import { toUint } from './utils/convert-strings'; + +export type AccessType = + | false + | 'ownable' + | 'roles' // AccessControl + | 'roles-dar'; // AccessControlDefaultAdminRules + +export type RolesDefaultAdminRulesOptions = { + darInitialDelay: string; + darDefaultDelayIncrease: string; +}; + +export type Access = { type: AccessType } & RolesDefaultAdminRulesOptions; + +export const darDefaultOpts: RolesDefaultAdminRulesOptions = { + darInitialDelay: '1 day', + darDefaultDelayIncrease: '5 days', +}; + +export const darCustomOps: RolesDefaultAdminRulesOptions = { + darInitialDelay: '2 days', + darDefaultDelayIncrease: '1 week', +}; + +export const AccessControl = { + None: { type: false, ...darDefaultOpts } as const, + Ownable: { type: 'ownable', ...darDefaultOpts } as const, + Roles: { type: 'roles', ...darDefaultOpts } as const, + RolesDefaultAdminRules: (opts: RolesDefaultAdminRulesOptions) => { + return { type: 'roles-dar', ...opts } as const; + }, +} as const; -export const accessOptions = [false, 'ownable', 'roles', 'roles-default-admin-rules'] as const; export const DEFAULT_ACCESS_CONTROL = 'ownable'; +export const accessOptions = [ + AccessControl.None, + AccessControl.Ownable, + AccessControl.Roles, + AccessControl.RolesDefaultAdminRules(darDefaultOpts), + AccessControl.RolesDefaultAdminRules(darCustomOps), +] as const; -export type Access = (typeof accessOptions)[number]; +const DEFAULT_ADMIN_DELAY_INCREASE_WAIT = BigInt(5 * 24 * 60 * 60); // 5 days -/** - * Sets access control for the contract by adding inheritance. - */ +/// Sets access control for the contract by adding inheritance. export function setAccessControl(c: ContractBuilder, access: Access): void { - switch (access) { + switch (access.type) { case 'ownable': { c.addComponent(components.OwnableComponent, [{ lit: 'owner' }], true); - c.addUseClause('starknet', 'ContractAddress'); c.addConstructorArgument({ name: 'owner', type: 'ContractAddress' }); - break; } case 'roles': { @@ -55,7 +92,7 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { } break; } - case 'roles-default-admin-rules': { + case 'roles-dar': { const initParams = [{ lit: 'INITIAL_DELAY' }, { lit: 'initial_default_admin' }]; if (c.addComponent(components.AccessControlDefaultAdminRulesComponent, initParams, true)) { if (c.interfaceFlags.has('ISRC5')) { @@ -83,10 +120,41 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { c.addInterfaceFlag('ISRC5'); } addSRC5Component(c); + const initialDelay = toUint(getInitialDelay(access), 'darInitialDelay', 'u64'); + c.addConstant({ + name: 'INITIAL_DELAY', + type: 'u64', + value: initialDelay.toString(), + comment: access.darInitialDelay, + inlineComment: true, + }); + const defaultAdminDelayIncreaseWait = toUint( + getDefaultAdminDelayIncreaseWait(access), + 'darDefaultDelayIncrease', + 'u64', + ); + if (defaultAdminDelayIncreaseWait == DEFAULT_ADMIN_DELAY_INCREASE_WAIT) { + c.addUseClause('openzeppelin::access::accesscontrol::extensions', 'DefaultConfig', { + alias: 'AccessControlDefaultAdminRulesDefaultConfig', + }); + } else { + const trait: BaseImplementedTrait = { + name: 'AccessControlDefaultAdminRulesImmutableConfig', + of: 'AccessControlDefaultAdminRulesComponent::ImmutableConfig', + tags: [], + }; + c.addImplementedTrait(trait); + c.addSuperVariableToTrait(trait, { + name: 'DEFAULT_ADMIN_DELAY_INCREASE_WAIT', + type: 'u64', + value: defaultAdminDelayIncreaseWait.toString(), + comment: access.darDefaultDelayIncrease, + inlineComment: true, + }); + } c.addUseClause('starknet', 'ContractAddress'); c.addConstructorArgument({ name: 'initial_default_admin', type: 'ContractAddress' }); - c.addConstructorArgument({ name: 'initial_default_admin', type: 'ContractAddress' }); } break; } @@ -100,31 +168,33 @@ export function requireAccessControl( c: ContractBuilder, trait: BaseImplementedTrait, fn: BaseFunction, - access: Access, + accessObj: Access, roleIdPrefix: string, roleOwner: string | undefined, ): void { - if (access === false) { - access = DEFAULT_ACCESS_CONTROL; + const access = { ...accessObj }; // make a copy to avoid triggering UI updates + if (access.type === false) { + access.type = DEFAULT_ACCESS_CONTROL; } setAccessControl(c, access); - switch (access) { + switch (access.type) { case 'ownable': { c.addFunctionCodeBefore(trait, fn, 'self.ownable.assert_only_owner()'); break; } case 'roles': - case 'roles-default-admin-rules': { + case 'roles-dar': { const roleId = roleIdPrefix + '_ROLE'; const addedSuper = c.addSuperVariable({ name: roleId, type: 'felt252', value: `selector!("${roleId}")`, }); - const substorageName = access === 'roles-default-admin-rules' - ? components.AccessControlDefaultAdminRulesComponent.substorage.name - : components.AccessControlComponent.substorage.name; + const substorageName = + access.type === 'roles-dar' + ? components.AccessControlDefaultAdminRulesComponent.substorage.name + : components.AccessControlComponent.substorage.name; if (roleOwner !== undefined) { c.addUseClause('starknet', 'ContractAddress'); c.addConstructorArgument({ name: roleOwner, type: 'ContractAddress' }); @@ -140,6 +210,34 @@ export function requireAccessControl( } } +function getInitialDelay(opts: RolesDefaultAdminRulesOptions): number { + try { + return durationToSeconds(opts.darInitialDelay); + } catch (e) { + if (e instanceof Error) { + throw new OptionsError({ + darInitialDelay: e.message, + }); + } else { + throw e; + } + } +} + +function getDefaultAdminDelayIncreaseWait(opts: RolesDefaultAdminRulesOptions): number { + try { + return durationToSeconds(opts.darDefaultDelayIncrease); + } catch (e) { + if (e instanceof Error) { + throw new OptionsError({ + darDefaultDelayIncrease: e.message, + }); + } else { + throw e; + } + } +} + const components = defineComponents({ OwnableComponent: { path: 'openzeppelin::access::ownable', @@ -198,5 +296,5 @@ const components = defineComponents({ value: 'AccessControlDefaultAdminRulesComponent::InternalImpl', }, ], - } + }, }); From 03372ce6fad62023c3dd018e02d99ae27d064e5e Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:05:43 +0300 Subject: [PATCH 05/40] Support AccessControlDAR in set-royalty-info --- .../cairo_alpha/src/set-access-control.ts | 4 +++ .../core/cairo_alpha/src/set-royalty-info.ts | 26 ++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index 5156ec36d..9f84b2361 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -207,6 +207,10 @@ export function requireAccessControl( break; } + default: { + const _: never = access.type; + throw new Error('Unknown access type'); + } } } diff --git a/packages/core/cairo_alpha/src/set-royalty-info.ts b/packages/core/cairo_alpha/src/set-royalty-info.ts index a8f89d9d2..b060d8d53 100644 --- a/packages/core/cairo_alpha/src/set-royalty-info.ts +++ b/packages/core/cairo_alpha/src/set-royalty-info.ts @@ -53,18 +53,18 @@ export type RoyaltyInfoOptions = { feeDenominator: string; }; -export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, access: Access): void { +export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, accessObj: Access): void { if (!options.enabled) { return; } - if (access === false) { - access = DEFAULT_ACCESS_CONTROL; + const access = { ...accessObj }; // make a copy to avoid triggering UI updates + if (access.type === false) { + access.type = DEFAULT_ACCESS_CONTROL; } setAccessControl(c, access); const { defaultRoyaltyFraction, feeDenominator } = getRoyaltyParameters(options); const initParams = [{ lit: 'default_royalty_receiver' }, defaultRoyaltyFraction]; - c.addComponent(components.ERC2981Component, initParams, true); c.addUseClause('starknet', 'ContractAddress'); c.addConstructorArgument({ @@ -72,14 +72,15 @@ export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, type: 'ContractAddress', }); - switch (access) { - case 'ownable': + switch (access.type) { + case 'ownable': { c.addImplToComponent(components.ERC2981Component, { name: 'ERC2981AdminOwnableImpl', value: `ERC2981Component::ERC2981AdminOwnableImpl`, }); break; - case 'roles': + } + case 'roles': { c.addImplToComponent(components.ERC2981Component, { name: 'ERC2981AdminAccessControlImpl', value: `ERC2981Component::ERC2981AdminAccessControlImpl`, @@ -90,7 +91,8 @@ export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, }); c.addConstructorCode('self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin)'); break; - case 'roles-default-admin-rules': + } + case 'roles-dar': { c.addImplToComponent(components.ERC2981Component, { name: 'ERC2981AdminAccessControlDefaultAdminRulesImpl', value: `ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl`, @@ -101,14 +103,14 @@ export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, }); c.addConstructorCode('self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin)'); break; + } default: { - const _: never = access; - throw new Error('Unknown access control option'); + const _: never = access.type; + throw new Error('Unknown access type'); } } - if (feeDenominator === DEFAULT_FEE_DENOMINATOR) { - c.addUseClause('openzeppelin::token::common::erc2981', 'DefaultConfig'); + c.addUseClause('openzeppelin::token::common::erc2981', 'DefaultConfig', { alias: 'ERC2981DefaultConfig' }); } else { const trait: BaseImplementedTrait = { name: 'ERC2981ImmutableConfig', From 2a48369a16eb418c5b380e03297c21f0958ab0b6 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:07:10 +0300 Subject: [PATCH 06/40] Improve printing logic for trait constants to include comments --- packages/core/cairo_alpha/src/print.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/core/cairo_alpha/src/print.ts b/packages/core/cairo_alpha/src/print.ts index 7853f1319..ecac44fa2 100644 --- a/packages/core/cairo_alpha/src/print.ts +++ b/packages/core/cairo_alpha/src/print.ts @@ -7,6 +7,7 @@ import type { ContractFunction, ImplementedTrait, UseClause, + Variable, } from './contract'; import { formatLines, spaceBetween } from './utils/format-lines'; @@ -34,7 +35,7 @@ export function printContract(contract: Contract): string { `mod ${contract.name} {`, spaceBetween( printUseClauses(contract), - printConstants(contract), + printConstants(contract.constants), printComponentDeclarations(contract), printImpls(contract), printStorage(contract), @@ -135,9 +136,9 @@ function sortUseClauses(contract: Contract): UseClause[] { }); } -function printConstants(contract: Contract): Lines[] { +function printConstants(constants: Variable[]): Lines[] { const lines = []; - for (const constant of contract.constants) { + for (const constant of constants) { // inlineComment is optional, default to false const inlineComment = constant.inlineComment ?? false; const commented = !!constant.comment; @@ -284,7 +285,7 @@ function printImplementedTrait(trait: ImplementedTrait): Lines[] { implLines.push(...trait.tags.map(t => `#[${t}]`)); implLines.push(`impl ${trait.name} of ${trait.of} {`); - const superVars = withSemicolons(trait.superVariables.map(v => `const ${v.name}: ${v.type} = ${v.value}`)); + const superVars = printConstants(trait.superVariables); implLines.push(superVars); const fns = trait.functions.map(fn => printFunction(fn)); From 3d1acde88eb1cc4623ebaee3c583d21789cbc4d2 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:08:11 +0300 Subject: [PATCH 07/40] Support AccessControl changes in Vesting, Governor, and Multisig --- packages/core/cairo_alpha/src/governor.ts | 8 ++++---- packages/core/cairo_alpha/src/multisig.ts | 4 ++-- packages/core/cairo_alpha/src/utils/duration.ts | 2 +- packages/core/cairo_alpha/src/vesting.ts | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/core/cairo_alpha/src/governor.ts b/packages/core/cairo_alpha/src/governor.ts index 12b46b9d3..7268fd387 100644 --- a/packages/core/cairo_alpha/src/governor.ts +++ b/packages/core/cairo_alpha/src/governor.ts @@ -7,7 +7,7 @@ import { printContract } from './print'; import { setInfo } from './set-info'; import { setUpgradeableGovernor } from './set-upgradeable'; import { defineComponents } from './utils/define-components'; -import { durationToTimestamp } from './utils/duration'; +import { durationToSeconds } from './utils/duration'; import { addSNIP12Metadata, addSRC5Component } from './common-components'; import { toUint, isNaturalNumber } from './utils/convert-strings'; export const clockModeOptions = ['timestamp'] as const; @@ -269,7 +269,7 @@ const components = defineComponents({ function addBase(c: ContractBuilder, _: GovernorOptions) { c.addUseClause('starknet', 'ContractAddress'); - c.addUseClause('openzeppelin::governance::governor', 'DefaultConfig'); + c.addUseClause('openzeppelin::governance::governor', 'DefaultConfig', { alias: 'GovernorDefaultConfig' }); c.addConstructorArgument({ name: 'votes_token', type: 'ContractAddress' }); c.addUseClause('openzeppelin::governance::governor::GovernorComponent', 'InternalTrait', { alias: 'GovernorInternalTrait', @@ -316,7 +316,7 @@ function addSettings(c: ContractBuilder, allOpts: Required) { function getVotingDelay(opts: Required): number { try { if (opts.clockMode === 'timestamp') { - return durationToTimestamp(opts.delay); + return durationToSeconds(opts.delay); } else { throw new Error('Invalid clock mode'); } @@ -334,7 +334,7 @@ function getVotingDelay(opts: Required): number { function getVotingPeriod(opts: Required): number { try { if (opts.clockMode === 'timestamp') { - return durationToTimestamp(opts.period); + return durationToSeconds(opts.period); } else { throw new Error('Invalid clock mode'); } diff --git a/packages/core/cairo_alpha/src/multisig.ts b/packages/core/cairo_alpha/src/multisig.ts index 8b017d39e..416b9bcc4 100644 --- a/packages/core/cairo_alpha/src/multisig.ts +++ b/packages/core/cairo_alpha/src/multisig.ts @@ -2,7 +2,7 @@ import type { Contract } from './contract'; import { ContractBuilder } from './contract'; import type { CommonOptions } from './common-options'; import { contractDefaults as commonDefaults } from './common-options'; -import { setAccessControl } from './set-access-control'; +import { setAccessControl, AccessControl } from './set-access-control'; import { setUpgradeableMultisig } from './set-upgradeable'; import { setInfo } from './set-info'; import { defineComponents } from './utils/define-components'; @@ -46,7 +46,7 @@ export function buildMultisig(opts: MultisigOptions): Contract { // A Multisig contract is exclusively governed by its own multisig process. // The collective approval of the designated signers determines all actions. // No other access-control mechanism should override or bypass this process. - setAccessControl(c, false); + setAccessControl(c, AccessControl.None); return c; } diff --git a/packages/core/cairo_alpha/src/utils/duration.ts b/packages/core/cairo_alpha/src/utils/duration.ts index cfbaf279e..254e805c2 100644 --- a/packages/core/cairo_alpha/src/utils/duration.ts +++ b/packages/core/cairo_alpha/src/utils/duration.ts @@ -11,7 +11,7 @@ const month = 30 * day; const year = 365 * day; const secondsForUnit = { second, minute, hour, day, week, month, year }; -export function durationToTimestamp(duration: string): number { +export function durationToSeconds(duration: string): number { const match = duration.trim().match(durationPattern); if (!match || match.length < 2) { diff --git a/packages/core/cairo_alpha/src/vesting.ts b/packages/core/cairo_alpha/src/vesting.ts index b5fa9cc85..2e9c0e0ec 100644 --- a/packages/core/cairo_alpha/src/vesting.ts +++ b/packages/core/cairo_alpha/src/vesting.ts @@ -1,14 +1,14 @@ import type { BaseImplementedTrait, Contract } from './contract'; import { ContractBuilder } from './contract'; import { contractDefaults as commonDefaults } from './common-options'; -import { setAccessControl } from './set-access-control'; +import { AccessControl, setAccessControl } from './set-access-control'; import { setUpgradeable } from './set-upgradeable'; import type { Info } from './set-info'; import { setInfo } from './set-info'; import { defineComponents } from './utils/define-components'; import { printContract } from './print'; import { OptionsError } from './error'; -import { durationToTimestamp } from './utils/duration'; +import { durationToSeconds } from './utils/duration'; import { toUint, validateUint } from './utils/convert-strings'; export type VestingSchedule = 'linear' | 'custom'; @@ -55,7 +55,7 @@ export function buildVesting(opts: VestingOptions): Contract { setInfo(c, allOpts.info); // Vesting component depends on Ownable component - const access = 'ownable'; + const access = AccessControl.Ownable; setAccessControl(c, access); // Must be non-upgradable to guarantee vesting according to the schedule @@ -159,7 +159,7 @@ function getVestingStart(opts: VestingOptions): { timestampInSec: bigint; format function getVestingDuration(opts: VestingOptions): number { try { - return durationToTimestamp(opts.duration); + return durationToSeconds(opts.duration); } catch (e) { if (e instanceof Error) { throw new OptionsError({ @@ -173,7 +173,7 @@ function getVestingDuration(opts: VestingOptions): number { function getCliffDuration(opts: VestingOptions): number { try { - return durationToTimestamp(opts.cliffDuration); + return durationToSeconds(opts.cliffDuration); } catch (e) { if (e instanceof Error) { throw new OptionsError({ From ccdd7d9fb43d72468164f74ad6fc237199df48a7 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:09:49 +0300 Subject: [PATCH 08/40] Update cairo-alpha index file --- packages/core/cairo_alpha/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/cairo_alpha/src/index.ts b/packages/core/cairo_alpha/src/index.ts index 91eee658a..25d51a165 100644 --- a/packages/core/cairo_alpha/src/index.ts +++ b/packages/core/cairo_alpha/src/index.ts @@ -6,7 +6,7 @@ export { ContractBuilder } from './contract'; export { printContract } from './print'; -export type { Access } from './set-access-control'; +export type { Access, AccessType } from './set-access-control'; export type { Account } from './account'; export type { Upgradeable } from './set-upgradeable'; export type { Info } from './set-info'; From 954776b6f79a2c4b652fa13b101795d16565b61b Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:10:55 +0300 Subject: [PATCH 09/40] Update access control type in common options --- packages/core/cairo_alpha/src/common-options.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/cairo_alpha/src/common-options.ts b/packages/core/cairo_alpha/src/common-options.ts index 5cdee43e0..c0d6a295a 100644 --- a/packages/core/cairo_alpha/src/common-options.ts +++ b/packages/core/cairo_alpha/src/common-options.ts @@ -1,5 +1,6 @@ import type { Argument } from './contract'; import type { Access } from './set-access-control'; +import { AccessControl } from './set-access-control'; import type { Info } from './set-info'; import { defaults as infoDefaults } from './set-info'; import type { Upgradeable } from './set-upgradeable'; @@ -11,7 +12,7 @@ export const defaults: Required = { export const contractDefaults: Required = { ...defaults, - access: false, + access: { ...AccessControl.None }, } as const; export interface CommonOptions { From 390913fafe6a47e332ffc4478608e089a68a34b9 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:11:21 +0300 Subject: [PATCH 10/40] Update ERC20 tests --- packages/core/cairo_alpha/src/erc20.test.ts | 61 ++++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/packages/core/cairo_alpha/src/erc20.test.ts b/packages/core/cairo_alpha/src/erc20.test.ts index 760cc8b53..1978635db 100644 --- a/packages/core/cairo_alpha/src/erc20.test.ts +++ b/packages/core/cairo_alpha/src/erc20.test.ts @@ -3,6 +3,7 @@ import test from 'ava'; import type { ERC20Options } from './erc20'; import { buildERC20, getInitialSupply } from './erc20'; import { printContract } from './print'; +import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; import type { OptionsError } from '.'; import { erc20 } from '.'; @@ -48,12 +49,22 @@ testERC20('erc20 burnable', { testERC20('erc20 pausable', { pausable: true, - access: 'ownable', + access: AccessControl.Ownable, }); testERC20('erc20 pausable with roles', { pausable: true, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC20('erc20 pausable with roles-DAR (default opts)', { + pausable: true, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testERC20('erc20 pausable with roles-DAR (custom opts)', { + pausable: true, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC20('erc20 burnable pausable', { @@ -86,12 +97,22 @@ test('erc20 votes, decimals too high', async t => { testERC20('erc20 mintable', { mintable: true, - access: 'ownable', + access: AccessControl.Ownable, }); testERC20('erc20 mintable with roles', { mintable: true, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC20('erc20 mintable with roles-DAR (default opts)', { + mintable: true, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testERC20('erc20 mintable with roles-DAR (custom opts)', { + mintable: true, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC20('erc20 votes', { @@ -137,7 +158,7 @@ testERC20('erc20 votes, non-upgradeable', { testERC20('erc20 full, non-upgradeable', { premint: '2000', - access: 'ownable', + access: AccessControl.Ownable, burnable: true, mintable: true, votes: true, @@ -149,7 +170,7 @@ testERC20('erc20 full, non-upgradeable', { testERC20('erc20 full upgradeable', { premint: '2000', - access: 'ownable', + access: AccessControl.Ownable, burnable: true, mintable: true, votes: true, @@ -161,7 +182,31 @@ testERC20('erc20 full upgradeable', { testERC20('erc20 full upgradeable with roles', { premint: '2000', - access: 'roles', + access: AccessControl.Roles, + burnable: true, + mintable: true, + votes: true, + pausable: true, + upgradeable: true, + appName: 'MY_DAPP_NAME', + appVersion: 'MY_DAPP_VERSION', +}); + +testERC20('erc20 full upgradeable with roles-DAR (default opts)', { + premint: '2000', + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), + burnable: true, + mintable: true, + votes: true, + pausable: true, + upgradeable: true, + appName: 'MY_DAPP_NAME', + appVersion: 'MY_DAPP_VERSION', +}); + +testERC20('erc20 full upgradeable with roles-DAR (custom opts)', { + premint: '2000', + access: AccessControl.RolesDefaultAdminRules(darCustomOps), burnable: true, mintable: true, votes: true, @@ -180,7 +225,7 @@ testAPIEquivalence('erc20 API full upgradeable', { symbol: 'CTK', decimals: '6', premint: '2000', - access: 'roles', + access: AccessControl.Roles, burnable: true, mintable: true, votes: true, From 5dbb32cf6f3cd84c0447c3445e61f46950d92fd5 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:11:33 +0300 Subject: [PATCH 11/40] Update ERC721 tests --- packages/core/cairo_alpha/src/erc721.test.ts | 41 +++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/packages/core/cairo_alpha/src/erc721.test.ts b/packages/core/cairo_alpha/src/erc721.test.ts index b5f4583e9..1d6c14c9a 100644 --- a/packages/core/cairo_alpha/src/erc721.test.ts +++ b/packages/core/cairo_alpha/src/erc721.test.ts @@ -4,6 +4,7 @@ import type { ERC721Options } from './erc721'; import { buildERC721 } from './erc721'; import { printContract } from './print'; import { royaltyInfoOptions } from './set-royalty-info'; +import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; import type { OptionsError } from '.'; import { erc721 } from '.'; @@ -90,7 +91,17 @@ testERC721('pausable + enumerable', { testERC721('mintable + roles', { mintable: true, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC721('mintable + roles-DAR (default opts)', { + mintable: true, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testERC721('mintable + roles-DAR (custom opts)', { + mintable: true, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC721('royalty info disabled', { @@ -99,22 +110,42 @@ testERC721('royalty info disabled', { testERC721('royalty info enabled default + ownable', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: 'ownable', + access: AccessControl.Ownable, }); testERC721('royalty info enabled default + roles', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC721('royalty info enabled default + roles-DAR (default opts)', { + royaltyInfo: royaltyInfoOptions.enabledDefault, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testERC721('royalty info enabled default + roles-DAR (custom opts)', { + royaltyInfo: royaltyInfoOptions.enabledDefault, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC721('royalty info enabled custom + ownable', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: 'ownable', + access: AccessControl.Ownable, }); testERC721('royalty info enabled custom + roles', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC721('royalty info enabled custom + roles-DAR (default opts)', { + royaltyInfo: royaltyInfoOptions.enabledCustom, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testERC721('royalty info enabled custom + roles-DAR (custom opts)', { + royaltyInfo: royaltyInfoOptions.enabledCustom, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC721('full non-upgradeable', { From 77099e5729a5deae5e580e6d300e6f0db6560467 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:11:54 +0300 Subject: [PATCH 12/40] Update ERC1155 tests --- packages/core/cairo_alpha/src/erc1155.test.ts | 72 ++++++++++++++++--- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/packages/core/cairo_alpha/src/erc1155.test.ts b/packages/core/cairo_alpha/src/erc1155.test.ts index 066e86c4b..75ec6e993 100644 --- a/packages/core/cairo_alpha/src/erc1155.test.ts +++ b/packages/core/cairo_alpha/src/erc1155.test.ts @@ -5,6 +5,7 @@ import type { ERC1155Options } from './erc1155'; import { buildERC1155 } from './erc1155'; import { printContract } from './print'; import { royaltyInfoOptions } from './set-royalty-info'; +import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; const NAME = 'MyToken'; const CUSTOM_NAME = 'CustomToken'; @@ -54,7 +55,7 @@ testERC1155('basic non-upgradeable', { testERC1155('basic', {}); testERC1155('basic + roles', { - access: 'roles', + access: AccessControl.Roles, }); testERC1155('no updatable uri', { @@ -75,7 +76,17 @@ testERC1155('mintable', { testERC1155('mintable + roles', { mintable: true, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC1155('mintable + roles DAR (default opts)', { + mintable: true, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testERC1155('mintable + roles DAR (custom opts)', { + mintable: true, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC1155('royalty info disabled', { @@ -84,33 +95,72 @@ testERC1155('royalty info disabled', { testERC1155('royalty info enabled default + ownable', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: 'ownable', + access: AccessControl.Ownable, }); testERC1155('royalty info enabled default + roles', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC1155('royalty info enabled default + roles-DAR (custom opts)', { + royaltyInfo: royaltyInfoOptions.enabledDefault, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testERC1155('royalty info enabled custom + ownable', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: 'ownable', + access: AccessControl.Ownable, }); testERC1155('royalty info enabled custom + roles', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: 'roles', + access: AccessControl.Roles, +}); + +testERC1155('royalty info enabled custom + roles-DAR (default opts)', { + royaltyInfo: royaltyInfoOptions.enabledCustom, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), }); -testERC1155('full non-upgradeable', { +testERC1155('royalty info enabled custom + roles-DAR (custom opts)', { + royaltyInfo: royaltyInfoOptions.enabledCustom, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), +}); + +testERC1155('full non-upgradeable roles', { ...allFeaturesON, - access: 'roles', + access: AccessControl.Roles, upgradeable: false, }); -testERC1155('full upgradeable', { +testERC1155('full upgradeable roles', { + ...allFeaturesON, + access: AccessControl.Roles, + upgradeable: true, +}); + +testERC1155('full non-upgradeable roles-DAR (default opts)', { + ...allFeaturesON, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), + upgradeable: false, +}); + +testERC1155('full non-upgradeable roles-DAR (custom opts)', { + ...allFeaturesON, + access: AccessControl.RolesDefaultAdminRules(darCustomOps), + upgradeable: false, +}); + +testERC1155('full upgradeable roles-DAR (default opts)', { + ...allFeaturesON, + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), + upgradeable: true, +}); + +testERC1155('full upgradeable roles-DAR (custom opts)', { ...allFeaturesON, - access: 'roles', + access: AccessControl.RolesDefaultAdminRules(darCustomOps), upgradeable: true, }); @@ -122,7 +172,7 @@ testAPIEquivalence('API full upgradeable', { ...allFeaturesON, name: CUSTOM_NAME, baseUri: BASE_URI, - access: 'roles', + access: AccessControl.Roles, upgradeable: true, }); From f75e13ebf1d7171a03b5a5b6bd7b4998900c4942 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:12:08 +0300 Subject: [PATCH 13/40] Update Custom contract tests --- packages/core/cairo_alpha/src/custom.test.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/core/cairo_alpha/src/custom.test.ts b/packages/core/cairo_alpha/src/custom.test.ts index 9b3059094..cebb355d9 100644 --- a/packages/core/cairo_alpha/src/custom.test.ts +++ b/packages/core/cairo_alpha/src/custom.test.ts @@ -4,6 +4,7 @@ import { custom } from '.'; import type { CustomOptions } from './custom'; import { buildCustom } from './custom'; import { printContract } from './print'; +import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; function testCustom(title: string, opts: Partial) { test(title, t => { @@ -48,20 +49,28 @@ testCustom('upgradeable', { testCustom('access control disabled', { upgradeable: false, - access: false, + access: AccessControl.None, }); testCustom('access control ownable', { - access: 'ownable', + access: AccessControl.Ownable, }); testCustom('access control roles', { - access: 'roles', + access: AccessControl.Roles, +}); + +testCustom('access control roles default admin rules (default opts)', { + access: AccessControl.RolesDefaultAdminRules(darDefaultOpts), +}); + +testCustom('access control roles default admin rules (custom opts)', { + access: AccessControl.RolesDefaultAdminRules(darCustomOps), }); testCustom('pausable with access control disabled', { // API should override access to true since it is required for pausable - access: false, + access: AccessControl.None, pausable: true, upgradeable: false, }); @@ -70,7 +79,7 @@ testAPIEquivalence('custom API default'); testAPIEquivalence('custom API full upgradeable', { name: 'CustomContract', - access: 'roles', + access: AccessControl.Roles, pausable: true, upgradeable: true, }); From de7e743434ee2c282b486e65d1e0f482f0706085 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:12:39 +0300 Subject: [PATCH 14/40] Update ERC20 test snapshots --- .../core/cairo_alpha/src/erc20.test.ts.md | 1007 +++++++++++++++-- .../core/cairo_alpha/src/erc20.test.ts.snap | Bin 2948 -> 3957 bytes packages/core/cairo_alpha/src/test.ts | 2 +- 3 files changed, 933 insertions(+), 76 deletions(-) diff --git a/packages/core/cairo_alpha/src/erc20.test.ts.md b/packages/core/cairo_alpha/src/erc20.test.ts.md index 100c83dbf..bd0436a5e 100644 --- a/packages/core/cairo_alpha/src/erc20.test.ts.md +++ b/packages/core/cairo_alpha/src/erc20.test.ts.md @@ -436,6 +436,269 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## erc20 pausable with roles-DAR (default opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{PAUSER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ + ␊ + component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ + ␊ + // Internal␊ + impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc20: ERC20Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC20Event: ERC20Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.erc20.initializer("MyToken", "MTK");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ + recipient: ContractAddress,␊ + amount: u256,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.unpause();␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## erc20 pausable with roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{PAUSER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ + ␊ + // Internal␊ + impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc20: ERC20Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC20Event: ERC20Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.erc20.initializer("MyToken", "MTK");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ + recipient: ContractAddress,␊ + amount: u256,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.unpause();␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + ## erc20 burnable pausable > Snapshot 1 @@ -957,44 +1220,257 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## erc20 votes +## erc20 mintable with roles-DAR (default opts) > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ - use openzeppelin::governance::votes::VotesComponent;␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ - use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::erc20::{␊ + DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ + };␊ use openzeppelin::upgrades::UpgradeableComponent;␊ - use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ - use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ - use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress};␊ + use super::{MINTER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ - component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ - component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ - impl NoncesImpl = NoncesComponent::NoncesImpl;␊ - #[abi(embed_v0)]␊ - impl VotesImpl = VotesComponent::VotesImpl;␊ - #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ - impl VotesInternalImpl = VotesComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc20: ERC20Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC20Event: ERC20Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + minter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.erc20.initializer("MyToken", "MTK");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc20.mint(recipient, amount);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## erc20 mintable with roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::erc20::{␊ + DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ + };␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{MINTER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ + ␊ + // Internal␊ + impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc20: ERC20Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC20Event: ERC20Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + minter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.erc20.initializer("MyToken", "MTK");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc20.mint(recipient, amount);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## erc20 votes + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::governance::votes::VotesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ + use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ + use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ + use starknet::{ClassHash, ContractAddress};␊ + ␊ + component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ + component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ + #[abi(embed_v0)]␊ + impl NoncesImpl = NoncesComponent::NoncesImpl;␊ + #[abi(embed_v0)]␊ + impl VotesImpl = VotesComponent::VotesImpl;␊ + #[abi(embed_v0)]␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + ␊ + // Internal␊ + impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl VotesInternalImpl = VotesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ ␊ @@ -1174,22 +1650,252 @@ Generated by [AVA](https://avajs.dev). 'MY_DAPP_VERSION'␊ }␊ }␊ - ␊ - //␊ - // Upgradeable␊ - //␊ - ␊ - #[abi(embed_v0)]␊ - impl UpgradeableImpl of IUpgradeable {␊ - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.ownable.assert_only_owner();␊ - self.upgradeable.upgrade(new_class_hash);␊ - }␊ - }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.ownable.assert_only_owner();␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## erc20 votes, non-upgradeable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::governance::votes::VotesComponent;␊ + use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ + use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ + use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ + use starknet::ContractAddress;␊ + ␊ + component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ + component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ + #[abi(embed_v0)]␊ + impl NoncesImpl = NoncesComponent::NoncesImpl;␊ + #[abi(embed_v0)]␊ + impl VotesImpl = VotesComponent::VotesImpl;␊ + ␊ + // Internal␊ + impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl VotesInternalImpl = VotesComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc20: ERC20Component::Storage,␊ + #[substorage(v0)]␊ + nonces: NoncesComponent::Storage,␊ + #[substorage(v0)]␊ + votes: VotesComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC20Event: ERC20Component::Event,␊ + #[flat]␊ + NoncesEvent: NoncesComponent::Event,␊ + #[flat]␊ + VotesEvent: VotesComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(ref self: ContractState) {␊ + self.erc20.initializer("MyToken", "MTK");␊ + }␊ + ␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn after_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ + recipient: ContractAddress,␊ + amount: u256,␊ + ) {␊ + let mut contract_state = self.get_contract_mut();␊ + contract_state.votes.transfer_voting_units(from, recipient, amount);␊ + }␊ + }␊ + ␊ + //␊ + // SNIP12 Metadata␊ + //␊ + ␊ + impl SNIP12MetadataImpl of SNIP12Metadata {␊ + fn name() -> felt252 {␊ + 'MY_DAPP_NAME'␊ + }␊ + ␊ + fn version() -> felt252 {␊ + 'v1'␊ + }␊ + }␊ + }␊ + ` + +## erc20 full, non-upgradeable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::governance::votes::VotesComponent;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ + use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ + use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ + use starknet::{ContractAddress, get_caller_address};␊ + ␊ + component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ + component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + #[abi(embed_v0)]␊ + impl NoncesImpl = NoncesComponent::NoncesImpl;␊ + #[abi(embed_v0)]␊ + impl VotesImpl = VotesComponent::VotesImpl;␊ + ␊ + // Internal␊ + impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl VotesInternalImpl = VotesComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc20: ERC20Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + ownable: OwnableComponent::Storage,␊ + #[substorage(v0)]␊ + nonces: NoncesComponent::Storage,␊ + #[substorage(v0)]␊ + votes: VotesComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC20Event: ERC20Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + OwnableEvent: OwnableComponent::Event,␊ + #[flat]␊ + NoncesEvent: NoncesComponent::Event,␊ + #[flat]␊ + VotesEvent: VotesComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ + self.erc20.initializer("MyToken", "MTK");␊ + self.ownable.initializer(owner);␊ + ␊ + self.erc20.mint(recipient, 2000000000000000000000);␊ + }␊ + ␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ + recipient: ContractAddress,␊ + amount: u256,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + ␊ + fn after_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ + recipient: ContractAddress,␊ + amount: u256,␊ + ) {␊ + let mut contract_state = self.get_contract_mut();␊ + contract_state.votes.transfer_voting_units(from, recipient, amount);␊ + }␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.ownable.assert_only_owner();␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.ownable.assert_only_owner();␊ + self.pausable.unpause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn burn(ref self: ContractState, value: u256) {␊ + self.erc20.burn(get_caller_address(), value);␊ + }␊ + ␊ + #[external(v0)]␊ + fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ + self.ownable.assert_only_owner();␊ + self.erc20.mint(recipient, amount);␊ + }␊ + }␊ + ␊ + //␊ + // SNIP12 Metadata␊ + //␊ + ␊ + impl SNIP12MetadataImpl of SNIP12Metadata {␊ + fn name() -> felt252 {␊ + 'MY_DAPP_NAME'␊ + }␊ + ␊ + fn version() -> felt252 {␊ + 'MY_DAPP_VERSION'␊ + }␊ + }␊ }␊ ` -## erc20 votes, non-upgradeable +## erc20 full upgradeable > Snapshot 1 @@ -1198,37 +1904,57 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyToken {␊ + use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::governance::votes::VotesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ - use starknet::ContractAddress;␊ + use starknet::{ClassHash, ContractAddress, get_caller_address};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ impl VotesInternalImpl = VotesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + ownable: OwnableComponent::Storage,␊ + #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ @@ -1237,17 +1963,36 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + OwnableEvent: OwnableComponent::Event,␊ + #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ - fn constructor(ref self: ContractState) {␊ + fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ + self.ownable.initializer(owner);␊ + ␊ + self.erc20.mint(recipient, 2000000000000000000000);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ + recipient: ContractAddress,␊ + amount: u256,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + ␊ fn after_update(␊ ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ @@ -1258,6 +2003,33 @@ Generated by [AVA](https://avajs.dev). contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.ownable.assert_only_owner();␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.ownable.assert_only_owner();␊ + self.pausable.unpause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn burn(ref self: ContractState, value: u256) {␊ + self.erc20.burn(get_caller_address(), value);␊ + }␊ + ␊ + #[external(v0)]␊ + fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ + self.ownable.assert_only_owner();␊ + self.erc20.mint(recipient, amount);␊ + }␊ + }␊ ␊ //␊ // SNIP12 Metadata␊ @@ -1269,35 +2041,57 @@ Generated by [AVA](https://avajs.dev). }␊ ␊ fn version() -> felt252 {␊ - 'v1'␊ + 'MY_DAPP_VERSION'␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.ownable.assert_only_owner();␊ + self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## erc20 full, non-upgradeable +## erc20 full upgradeable with roles > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ use openzeppelin::governance::votes::VotesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ - use starknet::{ContractAddress, get_caller_address};␊ + use starknet::{ClassHash, ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ @@ -1305,7 +2099,7 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlMixinImpl = AccessControlComponent::AccessControlMixinImpl;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl;␊ #[abi(embed_v0)]␊ @@ -1314,8 +2108,9 @@ Generated by [AVA](https://avajs.dev). // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ impl PausableInternalImpl = PausableComponent::InternalImpl;␊ - impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ impl VotesInternalImpl = VotesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -1324,11 +2119,15 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ - ownable: OwnableComponent::Storage,␊ + accesscontrol: AccessControlComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ @@ -1339,19 +2138,34 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ - OwnableEvent: OwnableComponent::Event,␊ + AccessControlEvent: AccessControlComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ - fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ + fn constructor(␊ + ref self: ContractState,␊ + recipient: ContractAddress,␊ + default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ self.erc20.initializer("MyToken", "MTK");␊ - self.ownable.initializer(owner);␊ + self.accesscontrol.initializer();␊ ␊ self.erc20.mint(recipient, 2000000000000000000000);␊ + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ + self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ @@ -1381,13 +2195,13 @@ Generated by [AVA](https://avajs.dev). impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ ␊ @@ -1398,7 +2212,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol.assert_only_role(MINTER_ROLE);␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ @@ -1416,21 +2230,41 @@ Generated by [AVA](https://avajs.dev). 'MY_DAPP_VERSION'␊ }␊ }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ }␊ ` -## erc20 full upgradeable +## erc20 full upgradeable with roles-DAR (default opts) > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ @@ -1438,10 +2272,14 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ @@ -1452,7 +2290,7 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl;␊ #[abi(embed_v0)]␊ @@ -1461,7 +2299,7 @@ Generated by [AVA](https://avajs.dev). // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ impl PausableInternalImpl = PausableComponent::InternalImpl;␊ - impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl VotesInternalImpl = VotesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ @@ -1472,7 +2310,9 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ - ownable: OwnableComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ @@ -1489,7 +2329,9 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ - OwnableEvent: OwnableComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ @@ -1499,11 +2341,21 @@ Generated by [AVA](https://avajs.dev). }␊ ␊ #[constructor]␊ - fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ + fn constructor(␊ + ref self: ContractState,␊ + recipient: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ self.erc20.initializer("MyToken", "MTK");␊ - self.ownable.initializer(owner);␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ ␊ self.erc20.mint(recipient, 2000000000000000000000);␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ @@ -1533,13 +2385,13 @@ Generated by [AVA](https://avajs.dev). impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ ␊ @@ -1550,7 +2402,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ @@ -1576,14 +2428,14 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## erc20 full upgradeable with roles +## erc20 full upgradeable with roles-DAR (custom opts) > Snapshot 1 @@ -1596,7 +2448,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ @@ -1608,10 +2460,12 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ @@ -1623,7 +2477,7 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlMixinImpl = AccessControlComponent::AccessControlMixinImpl;␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl;␊ #[abi(embed_v0)]␊ @@ -1632,7 +2486,7 @@ Generated by [AVA](https://avajs.dev). // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl;␊ impl PausableInternalImpl = PausableComponent::InternalImpl;␊ - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl VotesInternalImpl = VotesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ @@ -1643,7 +2497,7 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ - accesscontrol: AccessControlComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ @@ -1662,7 +2516,7 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ - AccessControlEvent: AccessControlComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ @@ -1677,19 +2531,18 @@ Generated by [AVA](https://avajs.dev). fn constructor(␊ ref self: ContractState,␊ recipient: ContractAddress,␊ - default_admin: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ pauser: ContractAddress,␊ minter: ContractAddress,␊ upgrader: ContractAddress,␊ ) {␊ self.erc20.initializer("MyToken", "MTK");␊ - self.accesscontrol.initializer();␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ ␊ self.erc20.mint(recipient, 2000000000000000000000);␊ - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ - self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ - self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ - self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ @@ -1714,18 +2567,22 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ - self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ - self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ ␊ @@ -1736,7 +2593,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ - self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ @@ -1762,7 +2619,7 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ diff --git a/packages/core/cairo_alpha/src/erc20.test.ts.snap b/packages/core/cairo_alpha/src/erc20.test.ts.snap index b568d321c5eb238673d24017ae60b0b97b02166c..436b186514578b62662a858c53591c8d4220b6c6 100644 GIT binary patch literal 3957 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 diff --git a/packages/core/cairo_alpha/src/test.ts b/packages/core/cairo_alpha/src/test.ts index f5a99332c..30ad85d75 100644 --- a/packages/core/cairo_alpha/src/test.ts +++ b/packages/core/cairo_alpha/src/test.ts @@ -112,7 +112,7 @@ test('is access control required', async t => { case 'ERC721': case 'ERC1155': case 'Custom': - if (!contract.options.access) { + if (!contract.options.access?.type) { if (isAccessControlRequired(contract.options)) { t.regex(contract.source, regexOwnable, JSON.stringify(contract.options)); } else { From d75ba2218aad6a4392959c72a0122010d178d3cb Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:12:51 +0300 Subject: [PATCH 15/40] Update ERC721 test snapshots --- .../core/cairo_alpha/src/erc721.test.ts.md | 817 +++++++++++++++++- .../core/cairo_alpha/src/erc721.test.ts.snap | Bin 3618 -> 4700 bytes 2 files changed, 773 insertions(+), 44 deletions(-) diff --git a/packages/core/cairo_alpha/src/erc721.test.ts.md b/packages/core/cairo_alpha/src/erc721.test.ts.md index 804b6a2a3..a1e3c95aa 100644 --- a/packages/core/cairo_alpha/src/erc721.test.ts.md +++ b/packages/core/cairo_alpha/src/erc721.test.ts.md @@ -850,6 +850,257 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## mintable + roles-DAR (default opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{MINTER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + ␊ + // Internal␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + minter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn safe_mint(␊ + ref self: ContractState,␊ + recipient: ContractAddress,␊ + token_id: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc721.safe_mint(recipient, token_id, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn safeMint(␊ + ref self: ContractState,␊ + recipient: ContractAddress,␊ + tokenId: u256,␊ + data: Span,␊ + ) {␊ + self.safe_mint(recipient, tokenId, data);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## mintable + roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{MINTER_ROLE, UPGRADER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + ␊ + // Internal␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + minter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn safe_mint(␊ + ref self: ContractState,␊ + recipient: ContractAddress,␊ + token_id: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc721.safe_mint(recipient, token_id, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn safeMint(␊ + ref self: ContractState,␊ + recipient: ContractAddress,␊ + tokenId: u256,␊ + data: Span,␊ + ) {␊ + self.safe_mint(recipient, tokenId, data);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + ## royalty info disabled > Snapshot 1 @@ -859,28 +1110,337 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ + #[abi(embed_v0)]␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + ␊ + // Internal␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + ownable: OwnableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + OwnableEvent: OwnableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(ref self: ContractState, owner: ContractAddress) {␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + self.ownable.initializer(owner);␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.ownable.assert_only_owner();␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled default + ownable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ + #[abi(embed_v0)]␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminOwnableImpl = ERC2981Component::ERC2981AdminOwnableImpl;␊ + ␊ + // Internal␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + ownable: OwnableComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + OwnableEvent: OwnableComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + owner: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + ) {␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + self.ownable.initializer(owner);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.ownable.assert_only_owner();␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled default + roles + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::UPGRADER_ROLE;␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + ␊ + // Internal␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol: AccessControlComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlEvent: AccessControlComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + default_admin: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + self.accesscontrol.initializer();␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ + self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled default + roles-DAR (default opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ + use super::UPGRADER_ROLE;␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ ␊ component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ ␊ // Internal␊ impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ - impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -889,9 +1449,11 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ - ownable: OwnableComponent::Storage,␊ + erc2981: ERC2981Component::Storage,␊ }␊ ␊ #[event]␊ @@ -902,15 +1464,27 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ - OwnableEvent: OwnableComponent::Event,␊ + ERC2981Event: ERC2981Component::Event,␊ }␊ ␊ #[constructor]␊ - fn constructor(ref self: ContractState, owner: ContractAddress) {␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ self.erc721.initializer("MyToken", "MTK", "");␊ - self.ownable.initializer(owner);␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ ␊ //␊ @@ -920,14 +1494,131 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## royalty info enabled default + ownable +## royalty info enabled default + roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::UPGRADER_ROLE;␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ + ␊ + // Internal␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled custom + ownable > Snapshot 1 @@ -939,7 +1630,7 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ + use openzeppelin::token::common::erc2981::ERC2981Component;␊ use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ @@ -1005,7 +1696,11 @@ Generated by [AVA](https://avajs.dev). ) {␊ self.erc721.initializer("MyToken", "MTK", "");␊ self.ownable.initializer(owner);␊ - self.erc2981.initializer(default_royalty_receiver, 500);␊ + self.erc2981.initializer(default_royalty_receiver, 15125);␊ + }␊ + ␊ + impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ + const FEE_DENOMINATOR: u128 = 100000;␊ }␊ ␊ //␊ @@ -1022,7 +1717,7 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## royalty info enabled default + roles +## royalty info enabled custom + roles > Snapshot 1 @@ -1036,7 +1731,7 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ + use openzeppelin::token::common::erc2981::ERC2981Component;␊ use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ @@ -1109,12 +1804,16 @@ Generated by [AVA](https://avajs.dev). ) {␊ self.erc721.initializer("MyToken", "MTK", "");␊ self.accesscontrol.initializer();␊ - self.erc2981.initializer(default_royalty_receiver, 500);␊ + self.erc2981.initializer(default_royalty_receiver, 15125);␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ + ␊ + impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ + const FEE_DENOMINATOR: u128 = 100000;␊ + }␊ ␊ //␊ // Upgradeable␊ @@ -1130,26 +1829,34 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## royalty info enabled custom + ownable +## royalty info enabled custom + roles-DAR (default opts) > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::common::erc2981::ERC2981Component;␊ use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ + use super::UPGRADER_ROLE;␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ ␊ component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ @@ -1157,17 +1864,23 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ #[abi(embed_v0)]␊ impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ #[abi(embed_v0)]␊ impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981AdminOwnableImpl = ERC2981Component::ERC2981AdminOwnableImpl;␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ ␊ // Internal␊ impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ - impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ @@ -1178,7 +1891,7 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ - ownable: OwnableComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ @@ -1193,7 +1906,7 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ - OwnableEvent: OwnableComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ @@ -1203,12 +1916,17 @@ Generated by [AVA](https://avajs.dev). #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ - owner: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ + upgrader: ContractAddress,␊ default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ ) {␊ self.erc721.initializer("MyToken", "MTK", "");␊ - self.ownable.initializer(owner);␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ self.erc2981.initializer(default_royalty_receiver, 15125);␊ + ␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ ␊ impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ @@ -1222,14 +1940,14 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## royalty info enabled custom + roles +## royalty info enabled custom + roles-DAR (custom opts) > Snapshot 1 @@ -1240,7 +1958,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::common::erc2981::ERC2981Component;␊ @@ -1248,10 +1966,12 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ use super::UPGRADER_ROLE;␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ ␊ component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ @@ -1259,21 +1979,23 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ #[abi(embed_v0)]␊ impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ #[abi(embed_v0)]␊ impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ ␊ // Internal␊ impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ @@ -1284,7 +2006,7 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ - accesscontrol: AccessControlComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ @@ -1299,7 +2021,7 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ - AccessControlEvent: AccessControlComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ @@ -1309,20 +2031,23 @@ Generated by [AVA](https://avajs.dev). #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ - default_admin: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ upgrader: ContractAddress,␊ default_royalty_receiver: ContractAddress,␊ royalty_admin: ContractAddress,␊ ) {␊ self.erc721.initializer("MyToken", "MTK", "");␊ - self.accesscontrol.initializer();␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ self.erc2981.initializer(default_royalty_receiver, 15125);␊ ␊ - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ - self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ - self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ const FEE_DENOMINATOR: u128 = 100000;␊ }␊ @@ -1334,7 +2059,7 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ @@ -1355,7 +2080,9 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ use openzeppelin::token::erc721::ERC721Component;␊ use openzeppelin::token::erc721::extensions::ERC721EnumerableComponent;␊ use openzeppelin::utils::contract_clock::ERC6372TimestampClock;␊ @@ -1880,7 +2607,9 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ use openzeppelin::token::erc721::ERC721Component;␊ use openzeppelin::token::erc721::extensions::ERC721EnumerableComponent;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ diff --git a/packages/core/cairo_alpha/src/erc721.test.ts.snap b/packages/core/cairo_alpha/src/erc721.test.ts.snap index 6e2bc6dbe5910924ff17c0795997ba1bee633738..1ba8a22146ed787f02a2a81463cda2c4651bb98b 100644 GIT binary patch literal 4700 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 S(hrVr6cYWSmCD0`fd2uP0`o!u literal 3618 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 From 83b013d13788943b3406ef220cf3d14a0214d2f3 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:13:02 +0300 Subject: [PATCH 16/40] Update ERC1155 test snapshots --- .../core/cairo_alpha/src/erc1155.test.ts.md | 1983 +++++++++++++++-- .../core/cairo_alpha/src/erc1155.test.ts.snap | Bin 3460 -> 4937 bytes 2 files changed, 1815 insertions(+), 168 deletions(-) diff --git a/packages/core/cairo_alpha/src/erc1155.test.ts.md b/packages/core/cairo_alpha/src/erc1155.test.ts.md index 1f94d3534..9bd0d3231 100644 --- a/packages/core/cairo_alpha/src/erc1155.test.ts.md +++ b/packages/core/cairo_alpha/src/erc1155.test.ts.md @@ -879,36 +879,52 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## royalty info disabled +## mintable + roles DAR (default opts) > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ + use super::{MINTER_ROLE, UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ ␊ component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ ␊ // Internal␊ impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ - impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ @@ -918,7 +934,7 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ - ownable: OwnableComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ @@ -931,23 +947,68 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ - OwnableEvent: OwnableComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ - fn constructor(ref self: ContractState, owner: ContractAddress) {␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ - self.ownable.initializer(owner);␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_id: u256,␊ + value: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchMint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.batch_mint(account, tokenIds, values, data);␊ + }␊ + ␊ #[external(v0)]␊ fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ self.erc1155._set_base_uri(base_uri);␊ }␊ ␊ @@ -964,53 +1025,57 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## royalty info enabled default + ownable +## mintable + roles DAR (custom opts) > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ + use super::{MINTER_ROLE, UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ ␊ component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ - component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981AdminOwnableImpl = ERC2981Component::ERC2981AdminOwnableImpl;␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ ␊ // Internal␊ impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ - impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ - impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -1019,11 +1084,9 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ - ownable: OwnableComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ - #[substorage(v0)]␊ - erc2981: ERC2981Component::Storage,␊ }␊ ␊ #[event]␊ @@ -1034,30 +1097,72 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ - OwnableEvent: OwnableComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ - #[flat]␊ - ERC2981Event: ERC2981Component::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ - owner: ContractAddress,␊ - default_royalty_receiver: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ ) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ - self.ownable.initializer(owner);␊ - self.erc2981.initializer(default_royalty_receiver, 500);␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_id: u256,␊ + value: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchMint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.batch_mint(account, tokenIds, values, data);␊ + }␊ + ␊ #[external(v0)]␊ fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ self.erc1155._set_base_uri(base_uri);␊ }␊ ␊ @@ -1074,61 +1179,44 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.ownable.assert_only_owner();␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## royalty info enabled default + roles +## royalty info disabled > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ - const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ - const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ - ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ - use super::{UPGRADER_ROLE, URI_SETTER_ROLE};␊ ␊ component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ - component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ - #[abi(embed_v0)]␊ - impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ - #[abi(embed_v0)]␊ - impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ - #[abi(embed_v0)]␊ - impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ - #[abi(embed_v0)]␊ - impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ - #[abi(embed_v0)]␊ - impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ ␊ // Internal␊ impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ - impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -1137,11 +1225,9 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ - accesscontrol: AccessControlComponent::Storage,␊ + ownable: OwnableComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ - #[substorage(v0)]␊ - erc2981: ERC2981Component::Storage,␊ }␊ ␊ #[event]␊ @@ -1152,30 +1238,15 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ - AccessControlEvent: AccessControlComponent::Event,␊ + OwnableEvent: OwnableComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ - #[flat]␊ - ERC2981Event: ERC2981Component::Event,␊ }␊ ␊ #[constructor]␊ - fn constructor(␊ - ref self: ContractState,␊ - default_admin: ContractAddress,␊ - uri_setter: ContractAddress,␊ - upgrader: ContractAddress,␊ - default_royalty_receiver: ContractAddress,␊ - royalty_admin: ContractAddress,␊ - ) {␊ + fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ - self.accesscontrol.initializer();␊ - self.erc2981.initializer(default_royalty_receiver, 500);␊ - ␊ - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ - self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ - self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ - self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + self.ownable.initializer(owner);␊ }␊ ␊ #[generate_trait]␊ @@ -1183,7 +1254,7 @@ Generated by [AVA](https://avajs.dev). impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ - self.accesscontrol.assert_only_role(URI_SETTER_ROLE);␊ + self.ownable.assert_only_owner();␊ self.erc1155._set_base_uri(base_uri);␊ }␊ ␊ @@ -1200,14 +1271,14 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.ownable.assert_only_owner();␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` -## royalty info enabled custom + ownable +## royalty info enabled default + ownable > Snapshot 1 @@ -1219,7 +1290,9 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::token::common::erc2981::ERC2981Component;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ @@ -1285,13 +1358,9 @@ Generated by [AVA](https://avajs.dev). ) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ self.ownable.initializer(owner);␊ - self.erc2981.initializer(default_royalty_receiver, 15125);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ }␊ ␊ - impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ - const FEE_DENOMINATOR: u128 = 100000;␊ - }␊ - ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ @@ -1321,7 +1390,7 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## royalty info enabled custom + roles +## royalty info enabled default + roles > Snapshot 1 @@ -1336,7 +1405,9 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::token::common::erc2981::ERC2981Component;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ @@ -1410,7 +1481,7 @@ Generated by [AVA](https://avajs.dev). ) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ self.accesscontrol.initializer();␊ - self.erc2981.initializer(default_royalty_receiver, 15125);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ @@ -1418,10 +1489,6 @@ Generated by [AVA](https://avajs.dev). self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ ␊ - impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ - const FEE_DENOMINATOR: u128 = 100000;␊ - }␊ - ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ @@ -1451,55 +1518,59 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## full non-upgradeable +## royalty info enabled default + roles-DAR (custom opts) > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ ␊ - const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ - const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ - use openzeppelin::security::pausable::PausableComponent;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ - use openzeppelin::token::erc1155::ERC1155Component;␊ - use starknet::{ContractAddress, get_caller_address};␊ - use super::{MINTER_ROLE, PAUSER_ROLE, URI_SETTER_ROLE};␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ ␊ component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ - component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ - impl PausableImpl = PausableComponent::PausableImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ #[abi(embed_v0)]␊ impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ #[abi(embed_v0)]␊ impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ ␊ // Internal␊ impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ - impl PausableInternalImpl = PausableComponent::InternalImpl;␊ - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ #[storage]␊ @@ -1509,9 +1580,9 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ - pausable: PausableComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ - accesscontrol: AccessControlComponent::Storage,␊ + upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ erc2981: ERC2981Component::Storage,␊ }␊ @@ -1524,9 +1595,9 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ - PausableEvent: PausableComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ - AccessControlEvent: AccessControlComponent::Event,␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ ERC2981Event: ERC2981Component::Event,␊ }␊ @@ -1534,49 +1605,1374 @@ Generated by [AVA](https://avajs.dev). #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ - default_admin: ContractAddress,␊ - pauser: ContractAddress,␊ - minter: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ default_royalty_receiver: ContractAddress,␊ royalty_admin: ContractAddress,␊ ) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ - self.accesscontrol.initializer();␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ self.erc2981.initializer(default_royalty_receiver, 500);␊ ␊ - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ - self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ - self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ - self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ - self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ ␊ - impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ - fn before_update(␊ - ref self: ERC1155Component::ComponentState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - token_ids: Span,␊ - values: Span,␊ - ) {␊ - let contract_state = self.get_contract();␊ - contract_state.pausable.assert_not_paused();␊ - }␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ - fn pause(ref self: ContractState) {␊ - self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ - self.pausable.pause();␊ - }␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled custom + ownable + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::ownable::OwnableComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::ERC2981Component;␊ + use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminOwnableImpl = ERC2981Component::ERC2981AdminOwnableImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl OwnableInternalImpl = OwnableComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + ownable: OwnableComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + OwnableEvent: OwnableComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + owner: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.ownable.initializer(owner);␊ + self.erc2981.initializer(default_royalty_receiver, 15125);␊ + }␊ + ␊ + impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ + const FEE_DENOMINATOR: u128 = 100000;␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.ownable.assert_only_owner();␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.ownable.assert_only_owner();␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled custom + roles + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::ERC2981Component;␊ + use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol: AccessControlComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlEvent: AccessControlComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + default_admin: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol.initializer();␊ + self.erc2981.initializer(default_royalty_receiver, 15125);␊ + ␊ + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ + self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ + const FEE_DENOMINATOR: u128 = 100000;␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled custom + roles-DAR (default opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::ERC2981Component;␊ + use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 15125);␊ + ␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ + const FEE_DENOMINATOR: u128 = 100000;␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## royalty info enabled custom + roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::token::common::erc2981::ERC2981Component;␊ + use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::{UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 15125);␊ + ␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + impl ERC2981ImmutableConfig of ERC2981Component::ImmutableConfig {␊ + const FEE_DENOMINATOR: u128 = 100000;␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## full non-upgradeable roles + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc1155::ERC1155Component;␊ + use starknet::{ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, URI_SETTER_ROLE};␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol: AccessControlComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlEvent: AccessControlComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol.initializer();␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ + self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ + from: ContractAddress,␊ + to: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.pausable.unpause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn burn(ref self: ContractState, account: ContractAddress, token_id: u256, value: u256) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.burn(account, token_id, value);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_burn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.batch_burn(account, token_ids, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchBurn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + ) {␊ + self.batch_burn(account, tokenIds, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_id: u256,␊ + value: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchMint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.batch_mint(account, tokenIds, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + }␊ + ` + +## full upgradeable roles + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol: AccessControlComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlEvent: AccessControlComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol.initializer();␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ + self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ + from: ContractAddress,␊ + to: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.pausable.unpause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn burn(ref self: ContractState, account: ContractAddress, token_id: u256, value: u256) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.burn(account, token_id, value);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_burn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.batch_burn(account, token_ids, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchBurn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + ) {␊ + self.batch_burn(account, tokenIds, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_id: u256,␊ + value: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchMint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.batch_mint(account, tokenIds, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## full non-upgradeable roles-DAR (default opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc1155::ERC1155Component;␊ + use starknet::{ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ + from: ContractAddress,␊ + to: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.unpause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn burn(ref self: ContractState, account: ContractAddress, token_id: u256, value: u256) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.burn(account, token_id, value);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_burn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.batch_burn(account, token_ids, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchBurn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + ) {␊ + self.batch_burn(account, tokenIds, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_id: u256,␊ + value: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchMint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.batch_mint(account, tokenIds, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + }␊ + ` + +## full non-upgradeable roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc1155::ERC1155Component;␊ + use starknet::{ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ + from: ContractAddress,␊ + to: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ - self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ ␊ @@ -1621,7 +3017,7 @@ Generated by [AVA](https://avajs.dev). value: u256,␊ data: Span,␊ ) {␊ - self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ }␊ ␊ @@ -1633,7 +3029,7 @@ Generated by [AVA](https://avajs.dev). values: Span,␊ data: Span,␊ ) {␊ - self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ }␊ ␊ @@ -1650,7 +3046,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ - self.accesscontrol.assert_only_role(URI_SETTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ self.erc1155._set_base_uri(base_uri);␊ }␊ ␊ @@ -1662,7 +3058,7 @@ Generated by [AVA](https://avajs.dev). }␊ ` -## full upgradeable +## full upgradeable roles-DAR (default opts) > Snapshot 1 @@ -1676,20 +3072,27 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyToken {␊ - use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ use openzeppelin::interfaces::upgrades::IUpgradeable;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ - use openzeppelin::token::common::erc2981::{DefaultConfig, ERC2981Component};␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ use openzeppelin::token::erc1155::ERC1155Component;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ ␊ component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ ␊ @@ -1699,22 +3102,24 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlImpl = AccessControlComponent::AccessControlImpl;␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlCamelImpl = AccessControlComponent::AccessControlCamelImpl;␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ #[abi(embed_v0)]␊ - impl AccessControlWithDelayImpl = AccessControlComponent::AccessControlWithDelayImpl;␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ #[abi(embed_v0)]␊ impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ #[abi(embed_v0)]␊ impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ #[abi(embed_v0)]␊ - impl ERC2981AdminAccessControlImpl = ERC2981Component::ERC2981AdminAccessControlImpl;␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ ␊ // Internal␊ impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ impl PausableInternalImpl = PausableComponent::InternalImpl;␊ - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ ␊ @@ -1727,7 +3132,7 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ - accesscontrol: AccessControlComponent::Storage,␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ @@ -1744,7 +3149,7 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ - AccessControlEvent: AccessControlComponent::Event,␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ @@ -1754,7 +3159,7 @@ Generated by [AVA](https://avajs.dev). #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ - default_admin: ContractAddress,␊ + initial_default_admin: ContractAddress,␊ pauser: ContractAddress,␊ minter: ContractAddress,␊ uri_setter: ContractAddress,␊ @@ -1763,15 +3168,14 @@ Generated by [AVA](https://avajs.dev). royalty_admin: ContractAddress,␊ ) {␊ self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ - self.accesscontrol.initializer();␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ self.erc2981.initializer(default_royalty_receiver, 500);␊ ␊ - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ - self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ - self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ - self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ - self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ - self.accesscontrol._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ }␊ ␊ impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ @@ -1792,13 +3196,13 @@ Generated by [AVA](https://avajs.dev). impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ - self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ - self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ ␊ @@ -1843,7 +3247,7 @@ Generated by [AVA](https://avajs.dev). value: u256,␊ data: Span,␊ ) {␊ - self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ }␊ ␊ @@ -1855,7 +3259,7 @@ Generated by [AVA](https://avajs.dev). values: Span,␊ data: Span,␊ ) {␊ - self.accesscontrol.assert_only_role(MINTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ }␊ ␊ @@ -1872,7 +3276,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ - self.accesscontrol.assert_only_role(URI_SETTER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ self.erc1155._set_base_uri(base_uri);␊ }␊ ␊ @@ -1889,7 +3293,250 @@ Generated by [AVA](https://avajs.dev). #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ - self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## full upgradeable roles-DAR (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ + const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ + const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::security::pausable::PausableComponent;␊ + use openzeppelin::token::common::erc2981::{␊ + DefaultConfig as ERC2981DefaultConfig, ERC2981Component␊ + };␊ + use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress, get_caller_address};␊ + use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE, URI_SETTER_ROLE};␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + component!(path: ERC2981Component, storage: erc2981, event: ERC2981Event);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ + #[abi(embed_v0)]␊ + impl PausableImpl = PausableComponent::PausableImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlImpl = AccessControlDefaultAdminRulesComponent::AccessControlImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlDefaultAdminRulesImpl = AccessControlDefaultAdminRulesComponent::AccessControlDefaultAdminRulesImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlCamelImpl = AccessControlDefaultAdminRulesComponent::AccessControlCamelImpl;␊ + #[abi(embed_v0)]␊ + impl AccessControlWithDelayImpl = AccessControlDefaultAdminRulesComponent::AccessControlWithDelayImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981Impl = ERC2981Component::ERC2981Impl;␊ + #[abi(embed_v0)]␊ + impl ERC2981InfoImpl = ERC2981Component::ERC2981InfoImpl;␊ + #[abi(embed_v0)]␊ + impl ERC2981AdminAccessControlDefaultAdminRulesImpl = ERC2981Component::ERC2981AdminAccessControlDefaultAdminRulesImpl;␊ + ␊ + // Internal␊ + impl ERC1155InternalImpl = ERC1155Component::InternalImpl;␊ + impl PausableInternalImpl = PausableComponent::InternalImpl;␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + impl ERC2981InternalImpl = ERC2981Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc1155: ERC1155Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + pausable: PausableComponent::Storage,␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + #[substorage(v0)]␊ + erc2981: ERC2981Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC1155Event: ERC1155Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + PausableEvent: PausableComponent::Event,␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + #[flat]␊ + ERC2981Event: ERC2981Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + pauser: ContractAddress,␊ + minter: ContractAddress,␊ + uri_setter: ContractAddress,␊ + upgrader: ContractAddress,␊ + default_royalty_receiver: ContractAddress,␊ + royalty_admin: ContractAddress,␊ + ) {␊ + self.erc1155.initializer("https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + self.erc2981.initializer(default_royalty_receiver, 500);␊ + ␊ + self.accesscontrol_dar._grant_role(PAUSER_ROLE, pauser);␊ + self.accesscontrol_dar._grant_role(MINTER_ROLE, minter);␊ + self.accesscontrol_dar._grant_role(URI_SETTER_ROLE, uri_setter);␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + self.accesscontrol_dar._grant_role(ERC2981Component::ROYALTY_ADMIN_ROLE, royalty_admin);␊ + }␊ + ␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ + from: ContractAddress,␊ + to: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let contract_state = self.get_contract();␊ + contract_state.pausable.assert_not_paused();␊ + }␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + #[generate_trait]␊ + #[abi(per_item)]␊ + impl ExternalImpl of ExternalTrait {␊ + #[external(v0)]␊ + fn pause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.pause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn unpause(ref self: ContractState) {␊ + self.accesscontrol_dar.assert_only_role(PAUSER_ROLE);␊ + self.pausable.unpause();␊ + }␊ + ␊ + #[external(v0)]␊ + fn burn(ref self: ContractState, account: ContractAddress, token_id: u256, value: u256) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.burn(account, token_id, value);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_burn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + ) {␊ + let caller = get_caller_address();␊ + if account != caller {␊ + assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ + }␊ + self.erc1155.batch_burn(account, token_ids, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchBurn(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + ) {␊ + self.batch_burn(account, tokenIds, values);␊ + }␊ + ␊ + #[external(v0)]␊ + fn mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_id: u256,␊ + value: u256,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batch_mint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + token_ids: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.accesscontrol_dar.assert_only_role(MINTER_ROLE);␊ + self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn batchMint(␊ + ref self: ContractState,␊ + account: ContractAddress,␊ + tokenIds: Span,␊ + values: Span,␊ + data: Span,␊ + ) {␊ + self.batch_mint(account, tokenIds, values, data);␊ + }␊ + ␊ + #[external(v0)]␊ + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) {␊ + self.accesscontrol_dar.assert_only_role(URI_SETTER_ROLE);␊ + self.erc1155._set_base_uri(base_uri);␊ + }␊ + ␊ + #[external(v0)]␊ + fn setBaseUri(ref self: ContractState, baseUri: ByteArray) {␊ + self.set_base_uri(baseUri);␊ + }␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ diff --git a/packages/core/cairo_alpha/src/erc1155.test.ts.snap b/packages/core/cairo_alpha/src/erc1155.test.ts.snap index 49034d52eb785ae46ae567c538c87f07b1ac5932..47e7d4d441aea3a345abc3ccd2d10726c980005b 100644 GIT binary patch literal 4937 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 literal 3460 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 From 0a9315f61ab0f71af250b17b2e7ee555866452b1 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:13:19 +0300 Subject: [PATCH 17/40] Update Custom contract test snapshots --- .../core/cairo_alpha/src/custom.test.ts.md | 163 ++++++++++++++++++ .../core/cairo_alpha/src/custom.test.ts.snap | Bin 1361 -> 1668 bytes 2 files changed, 163 insertions(+) diff --git a/packages/core/cairo_alpha/src/custom.test.ts.md b/packages/core/cairo_alpha/src/custom.test.ts.md index bf0e63c67..ae01b1f44 100644 --- a/packages/core/cairo_alpha/src/custom.test.ts.md +++ b/packages/core/cairo_alpha/src/custom.test.ts.md @@ -380,6 +380,169 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## access control roles default admin rules (default opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyContract {␊ + use openzeppelin::access::accesscontrol::extensions::{␊ + AccessControlDefaultAdminRulesComponent,␊ + DefaultConfig as AccessControlDefaultAdminRulesDefaultConfig␊ + };␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::UPGRADER_ROLE;␊ + ␊ + const INITIAL_DELAY: u64 = 86400; // 1 day␊ + ␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ + ␊ + // Internal␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + +## access control roles default admin rules (custom opts) + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo 3.0.0-alpha.2␊ + ␊ + const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ + ␊ + #[starknet::contract]␊ + mod MyContract {␊ + use openzeppelin::access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent;␊ + use openzeppelin::interfaces::upgrades::IUpgradeable;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::{ClassHash, ContractAddress};␊ + use super::UPGRADER_ROLE;␊ + ␊ + const INITIAL_DELAY: u64 = 172800; // 2 days␊ + ␊ + component!(path: AccessControlDefaultAdminRulesComponent, storage: accesscontrol_dar, event: AccessControlDefaultAdminRulesEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl AccessControlMixinImpl = AccessControlDefaultAdminRulesComponent::AccessControlMixinImpl;␊ + ␊ + // Internal␊ + impl AccessControlDefaultAdminRulesInternalImpl = AccessControlDefaultAdminRulesComponent::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + accesscontrol_dar: AccessControlDefaultAdminRulesComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + AccessControlDefaultAdminRulesEvent: AccessControlDefaultAdminRulesComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(␊ + ref self: ContractState,␊ + initial_default_admin: ContractAddress,␊ + upgrader: ContractAddress,␊ + ) {␊ + self.accesscontrol_dar.initializer(INITIAL_DELAY, initial_default_admin);␊ + ␊ + self.accesscontrol_dar._grant_role(UPGRADER_ROLE, upgrader);␊ + }␊ + ␊ + impl AccessControlDefaultAdminRulesImmutableConfig of AccessControlDefaultAdminRulesComponent::ImmutableConfig {␊ + const DEFAULT_ADMIN_DELAY_INCREASE_WAIT: u64 = 604800; // 1 week␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.accesscontrol_dar.assert_only_role(UPGRADER_ROLE);␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + ## pausable with access control disabled > Snapshot 1 diff --git a/packages/core/cairo_alpha/src/custom.test.ts.snap b/packages/core/cairo_alpha/src/custom.test.ts.snap index 39401ca412b105d98f3767f8ddeee8e56cdcb20e..fe5288cdb4b9ea883847dddcf0954d437c526a11 100644 GIT binary patch literal 1668 zcmV-~27CEIRzVHWW`ctVMj=H(=WhZ~*5|(>5)bWq@IOn}MV)k`!xJ z6aphrF%g*(NGg9C_^`t+JMTVpA7ICQgMF8sciDBIM9HKjId)*XuA^LHN$)+r_xSjJ zKTzTa_t^98Q~v88SP$Sld`dUeG~no0ZDLw_G50O0j^@R^sm}UEcwF zmx(&KssI3h6!jT8!SA9=E?8&_a1h^9GQCQ#qN4Uy)DCu0=n0+)_vr3#M!dh=ov(O9 zj)5Ow`d*ob5ZN~7976w`$_a$c7YFIR63hPAyGH-EkP^ytiG66zoL*el>fmXCNfX^@$hDuA` zS=r7vJ(wcRtV&~QQi&$!B75uWpmiZIqsUW5h>l4WcaO1Soo%edrAWGgmuT;i3qsrS z#!hDJbiz`hZ;}ih2qf^g{XyGQ8#J=71)Mxo!{lWTLR}~`%%Il;7PF2IwKnqdRC3|5 z60N2wjOwT#M}A2_sLa(yu$C;6oL~$qy~O>f3f`#;2QzYpt4-zyHLbYg+K7cP4Z9$^ zVMOP8Nc6oJEYqUEqKCCYGkR&}MWm^x@z_3%C&6d2A(sN}UX@`NaO}Ad81q?^nUfuF zVDYYKQA)KnmEbi(i6F=$?=h=Js%k0rl44G3T8mtNa?QHZ>t0^_F3=m-Krw1gx-_Y% z;!r6*w`|$3tPbKG2-4oAN1KTlagLd=eCl0VQN&dhvLUUNbMm`tj;Cq$2H~p{ppfUn z^wIKv25$YcT;f(nlVdw%L|j6cescy&Ia@{?r6}IIGtisB0MFmn<6TY38P7% z3W+jF>Q7@Kuzfs?PF*wMG$)7|qVseZ#Dp+EU7dMJngZHSmVr!{I~Z#|H$jtQ4SDJ} z;4bqsccLYR!__Va%oi2g^XhY zv?5tCYwgjJM!Bm|?rM~~8s)A=xvMdM&~+X+ zdk}$y?*WHIOuqdO7b^K=QyZY??RaU6vBi3#?zU< z`AFr%05b@UVU1Y^cx`s!j3oMhJk4Qk$L5kox6;Pj*S;*-U znqelj!THOQmsli2VT=kih)mKg3Pi0FhN!S4C|9#6Q!^dbVE!6YM$4|H;VdknGBcsm zs%$zYPq8kZ<#DWJ?m#qmfQ9m2HM!{rg0Ez0Sml{P!>W~ANWoeI$>il|aL%E;#{+gW>9ics#eap54icXuoJ5w(GlAv$b14f*{;_0(QXj zttT5B+p=jq0uH(yg$)jwuL62#If&&`#Eh-m%^8bRJ82S`8EF`+9Ol-7&`epPBiDJ! zJ%_E{G19o$>{RhaYbGpJ7O=rojdowlcV;-7jZBs_RL{oDsp!_|R8$?cDPp338cg)} z+s;Hs>`^6iEMkt2o^3u?)NxZ%M_zKrk~@~%vE+^=cPzQ%4Y}hey{6j@MLZSJc98Fm z(QgKH`#Fhm&fKw$g16c)8vCvKLCgBF-absQZ)@Yp^K{$f9OKiH08fhmf1P~D9#ha! zKV3VzcgNtn|1R!FTw|WH>$^D6DL#cGa$_>5@*LZoevdut6K9KaMr__b<0=n#&FSH; OUgdxG&tnFIMgRbj058)3 literal 1361 zcmV-X1+Mx*RzVvRa8<>FAo&!u$mjcIVuXo(&bWqnH21L@n2k45*0oo6M{Q^M% z9%ZQOGs%f91#*3kx`c8cy=kwt*H(!a3`l#u(Rlq{NWw1|NQ`YIe%2WJ4%)j()zNJO zA%r4PpObSqiywvLp)Ju-@=nQ&8l#4a+E-CK;F8djq7d%s^FNGue|tV(@rDAB9{~HH z%wtS!8-&2vzhcn@V!WUHh@A2nFu7TwNSOrg5*q}@ssaSYy_0bCJmLH=*`Mzx#@h0 zG_xv=nMoy@nv3mqI%wxw0%yciMM(Oz3Bx`(*5%qtQi^mKc&YXty{4=ey?9#~JDadf z=({vSN0LbRemrQ8X@kc0wSd!)YM8R@VXO-khRJ)KvsiTePHPWdo=Pt4E74|_!nlsc zag>(?#>!ml0oKw*QWA_|Wt6%fSHYQjaDdZGXl`>qXlccr)J7r%EF7Zvg%O?W5jplE zU#3-o#UERhX7ti5i%3(?;<0^}OoGo7LoP$wyCw%03GiHujQMOunTvM3+~Qr)qKwqq zD#2~asHDWBAAmPwRkajHX)&iYtwpYXxo2JJbss(ZF48xyTrp}+x-6}z>QEV6S$4Ev zSpy;l7-f5x9&I6FA_Q=0`OLeq;)t6nWJ6jj=k#~e98c34<>6}(kWiGu^y%_{25$Yc zT;oi)I~mB} z5D)P$WHa+H9jb)q)YS0l)bQf2CQjYesJj|#R|L+fyVcLyUEJh{HHj^0MWLsVcdo39L+SJ9q25&TR3tIS}0yA?lo zlV@$m-`@FQ>ty%X+S=ah{T%x+nmj_%XjBn^EvX-!g>ZWV`JXGWjq7jis_g<#k&4B zJv>Qx&_mlLr!Srvr0d_sZ5%xEX2;mY-1_?*u4O!u9n^Ox=JX6;*0&rM=U&3RwGQeF T1#^0#VAS{@>WdS)_b>ne-aejm From 0ad8e185343b9694c0fb9dfee3d3d423bc6dc0f2 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:13:34 +0300 Subject: [PATCH 18/40] Update Governor test snapshots --- .../core/cairo_alpha/src/governor.test.ts.md | 40 +++++++++++++----- .../cairo_alpha/src/governor.test.ts.snap | Bin 2330 -> 2333 bytes 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/packages/core/cairo_alpha/src/governor.test.ts.md b/packages/core/cairo_alpha/src/governor.test.ts.md index aa8516e55..0378f2ae4 100644 --- a/packages/core/cairo_alpha/src/governor.test.ts.md +++ b/packages/core/cairo_alpha/src/governor.test.ts.md @@ -13,7 +13,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -155,7 +157,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -273,7 +277,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -415,7 +421,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -557,7 +565,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod CustomGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -699,7 +709,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -841,7 +853,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesComponent␊ @@ -992,7 +1006,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -1134,7 +1150,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesQuorumFractionComponent␊ @@ -1276,7 +1294,9 @@ Generated by [AVA](https://avajs.dev). ␊ #[starknet::contract]␊ mod MyGovernor {␊ - use openzeppelin::governance::governor::{DefaultConfig, GovernorComponent};␊ + use openzeppelin::governance::governor::{␊ + DefaultConfig as GovernorDefaultConfig, GovernorComponent␊ + };␊ use openzeppelin::governance::governor::extensions::{␊ GovernorCountingSimpleComponent, GovernorSettingsComponent,␊ GovernorTimelockExecutionComponent, GovernorVotesComponent␊ diff --git a/packages/core/cairo_alpha/src/governor.test.ts.snap b/packages/core/cairo_alpha/src/governor.test.ts.snap index a0b4c8124c2aeeb27fcfc83539c6c4222b72461a..793cc2153f73c120ed0e62265e6964be667165a4 100644 GIT binary patch literal 2333 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 literal 2330 zcmZ|Gc~BCF0>^PovlNd`^8(C`%%jZk#+7v~6>L58S`R8+aW&H-uQl()15Z3y6{EB; z^QshuKuyrr0>dl3!ZbBgM9JGc+BZA%-prdf@AuzlzVowkx6*LEc`Y0p6m~}=5+*AN zKuTp_DXjpVb`jcSj6SK`U=TB?Cij?0$9Kfi*0szusv-q0aUn8~^tV6LQzFSRqX$4`WZEp_cGGTK)k zkWZiWaxc}3AT*$a85L)6a__(3U7Ig#FcFq zsxN@_YisjD4Oahr;i&HLF4RaPG?#(E@}_b`gwRPHvKNZbCVpew7-!{9RO4hrKSxV8 zfB4mNb2iR^cMTwb z4-*_5MuQ_MZa4h%xQ<`q*BnmZEyz`s-h43QL{m6xfvtqpt zQ%qWon5GW7AgMlP4IZx+py|iYc+>V9#2?Az5R=3ylL!{4l9*ZHJ9U@RT+sicM`}^I zKY1kcd8|C{|Hy%0_fp*cY>i3skSy zNz3*AX_vOSp9uW{y?KR;t*W^Ys8QU>AHn5DkNaEr+9LJP222mx9ZRychcSv@fRNQQ z=x7w_8&}Q8Nym3Ar1^}9ISjwitU$XydC)|`0DNaW41W3T>}7@dk!b3B;g-)^PEYES zWT;PdH^)O%>2W}CqCp`tw>f9bwos~WO@8@at&#DYx3XT_DBT^`?dYYhTtT^Dw{ECV zN-bnsCWiT(pN=<1=K4h{>Wgr1a4S zjRPfK&U!WJ;iw~sMy z>_O49F14^C*SxQh=v)4zpx1?HhUG}tep%jF_tB3}bp^hS^9#qEn-t$3Dk?44@OJg3 zr*L!1(LcB?9UigB1DB0zzv%kbERN~=XjAVvyxX5=lK_%(@FEk zKV9TB`ApRe@p^h-TI-5H$S>{h1D6!-^Bh{Cu=TY4?|2Pvf%CdE{glB^b5WY3zl{Pb z=Qcu@iQo;<;Rewrt0n|E6a8}z@Ro@(;R~>`U>!txU1z}0OWlQ;yO32iyv;wGf6mH; zayn!MFRqKf5*mV|YL$mQr-~xknG$$n==(oDW*sX4HvcYg02V~N{Nj9CU3?F6V1aRQ zyS^CuHHK`rxTUGk0HG~ar9b*m?q^gVdDERSA4jC!=nlaL%xTYIZK-_k(Mj+))y#4l-+~r93I0xNLe6J zAc?xb^CX!f8ns~B^oEzLh;uLfBm3bI?zUy_{fHrM?XPvKEZ=jd*3~=L7i6QVuaFVj zWe<7ecv0f{YZ%%YSMxrdp}J)(ygba6ageMMI6JTd9d3M<+DO_)xn6^5ojOc7h-5Yp z(tAh%&H?G-8Tzx50j}I06S=2{O6nnP{p>Ut`{>Eh*~}i2$2d3UU7V2NesoVR0f%6d zCwXGbCTvIL{}Cx-VN((45i+m#Cmn;VMNE=eyCHXL2{J@#sid&VC*Or*Xs{0|i*ivo zIQxIuci^AGtA^t{%Lm4NuJV@TVlCP6|30-Hj@qj)I)584cX5K_C1#HLpanqzt9Ls} z(AoDr)b^9lybZ3jYCCz~^m_&W#vpR#t7e|6o%|zd7s=|R!JmRPjQ*QzXMdo6gQ_aN zaauLKrsZOqq%#WLMO#1pzQ6iDq#F0jN6IfA{GiR1R`IM{jJIokOOdT#vV33EK|<}orix;;;33ivz3Wv6rYlr@^uMTy5075vq+i^@FNeSryC!H%6zZ3P`iBZo05 z+0^tqm0B(X@Tn@HR|T*Y=STcP9b6loYCEoZ2i!0w?T3)`<0<<2ml-vCrO*+U*b_G! z9oD@}#L2mE;m9yNPCr5|whEFQ2kPES%m>9*6)1KKxLK_OfXx`m=!J5eCE`pR z__6+Gx)V;Wpv)K0%acpIx$l8QFCYkD2vA)jN+VLp9lQyQ7`CahBNzW4V(SlWZbfcx z*>uJn|Fi?&@xXC!rHfe(ZmZ^VCepB_l# Date: Tue, 21 Oct 2025 12:23:56 +0300 Subject: [PATCH 19/40] Update AccessControl UI component --- .../cairo_alpha/AccessControlSection.svelte | 75 ++++++++++++------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/packages/ui/src/cairo_alpha/AccessControlSection.svelte b/packages/ui/src/cairo_alpha/AccessControlSection.svelte index b4a399605..3e0c48969 100644 --- a/packages/ui/src/cairo_alpha/AccessControlSection.svelte +++ b/packages/ui/src/cairo_alpha/AccessControlSection.svelte @@ -1,62 +1,83 @@
-
+ {#if accessType === 'roles-dar'} + + + {/if}
From bb19703b6e04154c31f9c8052de205f5cd974b83 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:24:27 +0300 Subject: [PATCH 20/40] Support AccessControl changes in ERC20Controls --- packages/ui/src/cairo_alpha/ERC20Controls.svelte | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/cairo_alpha/ERC20Controls.svelte b/packages/ui/src/cairo_alpha/ERC20Controls.svelte index 00ef0d5d5..50a41f075 100644 --- a/packages/ui/src/cairo_alpha/ERC20Controls.svelte +++ b/packages/ui/src/cairo_alpha/ERC20Controls.svelte @@ -15,6 +15,7 @@ ...erc20.defaults, premint: '', // default to empty premint in UI instead of 0 info: { ...infoDefaults }, // create new object since Info is nested + access: { ...erc20.defaults.access }, // create new object since Access is nested }; export let errors: undefined | OptionsErrorMessages; @@ -114,6 +115,12 @@ - + From 6e69d56ce704ada3405644774cce8448be8d897e Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:24:36 +0300 Subject: [PATCH 21/40] Support AccessControl changes in ERC721Controls --- packages/ui/src/cairo_alpha/ERC721Controls.svelte | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/cairo_alpha/ERC721Controls.svelte b/packages/ui/src/cairo_alpha/ERC721Controls.svelte index f7a8d1969..81b356ae5 100644 --- a/packages/ui/src/cairo_alpha/ERC721Controls.svelte +++ b/packages/ui/src/cairo_alpha/ERC721Controls.svelte @@ -15,7 +15,8 @@ kind: 'ERC721', ...erc721.defaults, royaltyInfo: { ...erc721.defaults.royaltyInfo }, // copy fields - info: { ...infoDefaults }, // create new object since Info is nested + info: { ...infoDefaults }, // create new object since Info is nested, + access: { ...erc721.defaults.access }, // create new object since Access is nested }; export let errors: undefined | OptionsErrorMessages; @@ -112,6 +113,12 @@ - + From 08e08e727f11e64b8a252c87dd180b2af0317394 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:24:44 +0300 Subject: [PATCH 22/40] Support AccessControl changes in ERC1155Controls --- packages/ui/src/cairo_alpha/ERC1155Controls.svelte | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/cairo_alpha/ERC1155Controls.svelte b/packages/ui/src/cairo_alpha/ERC1155Controls.svelte index 4e259f05c..62f7377fd 100644 --- a/packages/ui/src/cairo_alpha/ERC1155Controls.svelte +++ b/packages/ui/src/cairo_alpha/ERC1155Controls.svelte @@ -14,6 +14,7 @@ ...erc1155.defaults, royaltyInfo: { ...erc1155.defaults.royaltyInfo }, // copy fields info: { ...infoDefaults }, // create new object since Info is nested + access: { ...erc1155.defaults.access }, // create new object since Access is nested }; export let errors: undefined | OptionsErrorMessages; @@ -76,6 +77,12 @@ - + From 2934779b266751cb0bbe58d12464743bf4e64cfe Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:24:55 +0300 Subject: [PATCH 23/40] Support AccessControl changes in CustomControls --- packages/ui/src/cairo_alpha/CustomControls.svelte | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/cairo_alpha/CustomControls.svelte b/packages/ui/src/cairo_alpha/CustomControls.svelte index 213983dbf..865a5a1f8 100644 --- a/packages/ui/src/cairo_alpha/CustomControls.svelte +++ b/packages/ui/src/cairo_alpha/CustomControls.svelte @@ -13,6 +13,7 @@ kind: 'Custom', ...custom.defaults, info: { ...infoDefaults }, // create new object since Info is nested + access: { ...custom.defaults.access }, // create new object since Access is nested }; export let errors: undefined | OptionsErrorMessages; @@ -47,6 +48,12 @@ - + From b816aa3a65ceaf5394ba1b21b1c5d31a435cc50f Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:26:27 +0300 Subject: [PATCH 24/40] Run formatter --- packages/ui/src/cairo_alpha/AccessControlSection.svelte | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/cairo_alpha/AccessControlSection.svelte b/packages/ui/src/cairo_alpha/AccessControlSection.svelte index 3e0c48969..72d149cf9 100644 --- a/packages/ui/src/cairo_alpha/AccessControlSection.svelte +++ b/packages/ui/src/cairo_alpha/AccessControlSection.svelte @@ -26,7 +26,7 @@ } wasRequired = required; - if (accessType !== false) { + if (accessType !== false) { defaultTypeWhenEnabled = accessType; } } @@ -70,14 +70,15 @@ Initial delay The initial delay before the default admin can be assigned. - + {/if} From af2cb099cb870f12434187f4733311168f25190f Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 12:42:56 +0300 Subject: [PATCH 25/40] Add changelog entry --- packages/core/cairo_alpha/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/cairo_alpha/CHANGELOG.md b/packages/core/cairo_alpha/CHANGELOG.md index 49ae1ef43..f87ec5960 100644 --- a/packages/core/cairo_alpha/CHANGELOG.md +++ b/packages/core/cairo_alpha/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Add AccessControlDefaultAdminRules. ([#698](https://github.com/OpenZeppelin/contracts-wizard/pull/698)) + - **Breaking changes**: - Use OpenZeppelin Contracts for Cairo v3.0.0-alpha.3. ([#688](https://github.com/OpenZeppelin/contracts-wizard/pull/688)) - Use OpenZeppelin Contracts for Cairo v3.0.0-alpha.2. ([#663](https://github.com/OpenZeppelin/contracts-wizard/pull/663)) From 356caa8ee99157765cba477ba9990f44e2e98ad4 Mon Sep 17 00:00:00 2001 From: immrsd Date: Tue, 21 Oct 2025 13:30:39 +0300 Subject: [PATCH 26/40] Make review fixes --- packages/core/cairo_alpha/src/custom.test.ts | 4 ++-- packages/core/cairo_alpha/src/erc1155.test.ts | 12 ++++++------ packages/core/cairo_alpha/src/erc20.test.ts | 8 ++++---- packages/core/cairo_alpha/src/erc721.test.ts | 8 ++++---- .../core/cairo_alpha/src/set-access-control.ts | 15 +++++++++++---- packages/core/cairo_alpha/src/set-royalty-info.ts | 2 +- packages/ui/src/cairo_alpha/App.svelte | 3 +-- packages/ui/src/common/languages-types.ts | 4 +++- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/packages/core/cairo_alpha/src/custom.test.ts b/packages/core/cairo_alpha/src/custom.test.ts index cebb355d9..ab6dcf9d9 100644 --- a/packages/core/cairo_alpha/src/custom.test.ts +++ b/packages/core/cairo_alpha/src/custom.test.ts @@ -4,7 +4,7 @@ import { custom } from '.'; import type { CustomOptions } from './custom'; import { buildCustom } from './custom'; import { printContract } from './print'; -import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; +import { AccessControl, darDefaultOpts, darCustomOpts } from './set-access-control'; function testCustom(title: string, opts: Partial) { test(title, t => { @@ -65,7 +65,7 @@ testCustom('access control roles default admin rules (default opts)', { }); testCustom('access control roles default admin rules (custom opts)', { - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testCustom('pausable with access control disabled', { diff --git a/packages/core/cairo_alpha/src/erc1155.test.ts b/packages/core/cairo_alpha/src/erc1155.test.ts index 75ec6e993..097536647 100644 --- a/packages/core/cairo_alpha/src/erc1155.test.ts +++ b/packages/core/cairo_alpha/src/erc1155.test.ts @@ -5,7 +5,7 @@ import type { ERC1155Options } from './erc1155'; import { buildERC1155 } from './erc1155'; import { printContract } from './print'; import { royaltyInfoOptions } from './set-royalty-info'; -import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; +import { AccessControl, darDefaultOpts, darCustomOpts } from './set-access-control'; const NAME = 'MyToken'; const CUSTOM_NAME = 'CustomToken'; @@ -86,7 +86,7 @@ testERC1155('mintable + roles DAR (default opts)', { testERC1155('mintable + roles DAR (custom opts)', { mintable: true, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC1155('royalty info disabled', { @@ -105,7 +105,7 @@ testERC1155('royalty info enabled default + roles', { testERC1155('royalty info enabled default + roles-DAR (custom opts)', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC1155('royalty info enabled custom + ownable', { @@ -125,7 +125,7 @@ testERC1155('royalty info enabled custom + roles-DAR (default opts)', { testERC1155('royalty info enabled custom + roles-DAR (custom opts)', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC1155('full non-upgradeable roles', { @@ -148,7 +148,7 @@ testERC1155('full non-upgradeable roles-DAR (default opts)', { testERC1155('full non-upgradeable roles-DAR (custom opts)', { ...allFeaturesON, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), upgradeable: false, }); @@ -160,7 +160,7 @@ testERC1155('full upgradeable roles-DAR (default opts)', { testERC1155('full upgradeable roles-DAR (custom opts)', { ...allFeaturesON, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), upgradeable: true, }); diff --git a/packages/core/cairo_alpha/src/erc20.test.ts b/packages/core/cairo_alpha/src/erc20.test.ts index 1978635db..43283765f 100644 --- a/packages/core/cairo_alpha/src/erc20.test.ts +++ b/packages/core/cairo_alpha/src/erc20.test.ts @@ -3,7 +3,7 @@ import test from 'ava'; import type { ERC20Options } from './erc20'; import { buildERC20, getInitialSupply } from './erc20'; import { printContract } from './print'; -import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; +import { AccessControl, darDefaultOpts, darCustomOpts } from './set-access-control'; import type { OptionsError } from '.'; import { erc20 } from '.'; @@ -64,7 +64,7 @@ testERC20('erc20 pausable with roles-DAR (default opts)', { testERC20('erc20 pausable with roles-DAR (custom opts)', { pausable: true, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC20('erc20 burnable pausable', { @@ -112,7 +112,7 @@ testERC20('erc20 mintable with roles-DAR (default opts)', { testERC20('erc20 mintable with roles-DAR (custom opts)', { mintable: true, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC20('erc20 votes', { @@ -206,7 +206,7 @@ testERC20('erc20 full upgradeable with roles-DAR (default opts)', { testERC20('erc20 full upgradeable with roles-DAR (custom opts)', { premint: '2000', - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), burnable: true, mintable: true, votes: true, diff --git a/packages/core/cairo_alpha/src/erc721.test.ts b/packages/core/cairo_alpha/src/erc721.test.ts index 1d6c14c9a..ab116d2b7 100644 --- a/packages/core/cairo_alpha/src/erc721.test.ts +++ b/packages/core/cairo_alpha/src/erc721.test.ts @@ -4,7 +4,7 @@ import type { ERC721Options } from './erc721'; import { buildERC721 } from './erc721'; import { printContract } from './print'; import { royaltyInfoOptions } from './set-royalty-info'; -import { AccessControl, darDefaultOpts, darCustomOps } from './set-access-control'; +import { AccessControl, darDefaultOpts, darCustomOpts } from './set-access-control'; import type { OptionsError } from '.'; import { erc721 } from '.'; @@ -101,7 +101,7 @@ testERC721('mintable + roles-DAR (default opts)', { testERC721('mintable + roles-DAR (custom opts)', { mintable: true, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC721('royalty info disabled', { @@ -125,7 +125,7 @@ testERC721('royalty info enabled default + roles-DAR (default opts)', { testERC721('royalty info enabled default + roles-DAR (custom opts)', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC721('royalty info enabled custom + ownable', { @@ -145,7 +145,7 @@ testERC721('royalty info enabled custom + roles-DAR (default opts)', { testERC721('royalty info enabled custom + roles-DAR (custom opts)', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: AccessControl.RolesDefaultAdminRules(darCustomOps), + access: AccessControl.RolesDefaultAdminRules(darCustomOpts), }); testERC721('full non-upgradeable', { diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index 9f84b2361..3f2ef972f 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -23,7 +23,7 @@ export const darDefaultOpts: RolesDefaultAdminRulesOptions = { darDefaultDelayIncrease: '5 days', }; -export const darCustomOps: RolesDefaultAdminRulesOptions = { +export const darCustomOpts: RolesDefaultAdminRulesOptions = { darInitialDelay: '2 days', darDefaultDelayIncrease: '1 week', }; @@ -43,7 +43,7 @@ export const accessOptions = [ AccessControl.Ownable, AccessControl.Roles, AccessControl.RolesDefaultAdminRules(darDefaultOpts), - AccessControl.RolesDefaultAdminRules(darCustomOps), + AccessControl.RolesDefaultAdminRules(darCustomOpts), ] as const; const DEFAULT_ADMIN_DELAY_INCREASE_WAIT = BigInt(5 * 24 * 60 * 60); // 5 days @@ -51,6 +51,9 @@ const DEFAULT_ADMIN_DELAY_INCREASE_WAIT = BigInt(5 * 24 * 60 * 60); // 5 days /// Sets access control for the contract by adding inheritance. export function setAccessControl(c: ContractBuilder, access: Access): void { switch (access.type) { + case false: { + break; + } case 'ownable': { c.addComponent(components.OwnableComponent, [{ lit: 'owner' }], true); c.addUseClause('starknet', 'ContractAddress'); @@ -133,7 +136,7 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { 'darDefaultDelayIncrease', 'u64', ); - if (defaultAdminDelayIncreaseWait == DEFAULT_ADMIN_DELAY_INCREASE_WAIT) { + if (defaultAdminDelayIncreaseWait === DEFAULT_ADMIN_DELAY_INCREASE_WAIT) { c.addUseClause('openzeppelin::access::accesscontrol::extensions', 'DefaultConfig', { alias: 'AccessControlDefaultAdminRulesDefaultConfig', }); @@ -158,6 +161,10 @@ export function setAccessControl(c: ContractBuilder, access: Access): void { } break; } + default: { + const _: never = access.type; + throw new Error('Unknown access type'); + } } } @@ -172,7 +179,7 @@ export function requireAccessControl( roleIdPrefix: string, roleOwner: string | undefined, ): void { - const access = { ...accessObj }; // make a copy to avoid triggering UI updates + const access = { ...accessObj }; // make a copy to avoid mutating caller-supplied object if (access.type === false) { access.type = DEFAULT_ACCESS_CONTROL; } diff --git a/packages/core/cairo_alpha/src/set-royalty-info.ts b/packages/core/cairo_alpha/src/set-royalty-info.ts index b060d8d53..7b19340b8 100644 --- a/packages/core/cairo_alpha/src/set-royalty-info.ts +++ b/packages/core/cairo_alpha/src/set-royalty-info.ts @@ -57,7 +57,7 @@ export function setRoyaltyInfo(c: ContractBuilder, options: RoyaltyInfoOptions, if (!options.enabled) { return; } - const access = { ...accessObj }; // make a copy to avoid triggering UI updates + const access = { ...accessObj }; // make a copy to avoid mutating caller-supplied object if (access.type === false) { access.type = DEFAULT_ACCESS_CONTROL; } diff --git a/packages/ui/src/cairo_alpha/App.svelte b/packages/ui/src/cairo_alpha/App.svelte index 2d52e64bb..eff976d5b 100644 --- a/packages/ui/src/cairo_alpha/App.svelte +++ b/packages/ui/src/cairo_alpha/App.svelte @@ -100,10 +100,9 @@ $: code = printContract(contract); $: highlightedCode = injectHyperlinks(hljs.highlight(code, { language: 'cairo' }).value); - $: hasErrors = errors[tab] !== undefined; - const language = 'cairo'; + const language = 'cairo-alpha'; let copied = false; const copyHandler = async () => { diff --git a/packages/ui/src/common/languages-types.ts b/packages/ui/src/common/languages-types.ts index 086652f11..7bc146de4 100644 --- a/packages/ui/src/common/languages-types.ts +++ b/packages/ui/src/common/languages-types.ts @@ -1,12 +1,14 @@ import type { GenericOptions as SolidityOptions } from '@openzeppelin/wizard'; import type { GenericOptions as CairoOptions } from '@openzeppelin/wizard-cairo'; +import type { GenericOptions as CairoAlphaOptions } from '@openzeppelin/wizard-cairo-alpha'; import type { GenericOptions as StellarOptions } from '@openzeppelin/wizard-stellar'; import type { GenericOptions as StylusOptions } from '@openzeppelin/wizard-stylus'; export type LanguagesOptions = | Required | Required + | Required | Required | Required; -export type Language = 'solidity' | 'cairo' | 'polkadot-solidity' | 'stylus' | 'stellar'; +export type Language = 'solidity' | 'cairo' | 'cairo-alpha' | 'polkadot-solidity' | 'stylus' | 'stellar'; From 0af0f4b2cbbc57ca2f93da1eba73943a3feb75d7 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 11:41:15 +0300 Subject: [PATCH 27/40] Make all AccessControl members function-based, declare its type explicitly --- .../core/cairo_alpha/src/common-options.ts | 2 +- packages/core/cairo_alpha/src/custom.test.ts | 10 +++---- packages/core/cairo_alpha/src/erc1155.test.ts | 18 ++++++------ packages/core/cairo_alpha/src/erc20.test.ts | 16 +++++----- packages/core/cairo_alpha/src/erc721.test.ts | 10 +++---- packages/core/cairo_alpha/src/multisig.ts | 2 +- .../cairo_alpha/src/set-access-control.ts | 29 ++++++++++++------- packages/core/cairo_alpha/src/vesting.ts | 2 +- 8 files changed, 48 insertions(+), 41 deletions(-) diff --git a/packages/core/cairo_alpha/src/common-options.ts b/packages/core/cairo_alpha/src/common-options.ts index c0d6a295a..a179fcffe 100644 --- a/packages/core/cairo_alpha/src/common-options.ts +++ b/packages/core/cairo_alpha/src/common-options.ts @@ -12,7 +12,7 @@ export const defaults: Required = { export const contractDefaults: Required = { ...defaults, - access: { ...AccessControl.None }, + access: AccessControl.None(), } as const; export interface CommonOptions { diff --git a/packages/core/cairo_alpha/src/custom.test.ts b/packages/core/cairo_alpha/src/custom.test.ts index ab6dcf9d9..81037f5b0 100644 --- a/packages/core/cairo_alpha/src/custom.test.ts +++ b/packages/core/cairo_alpha/src/custom.test.ts @@ -49,15 +49,15 @@ testCustom('upgradeable', { testCustom('access control disabled', { upgradeable: false, - access: AccessControl.None, + access: AccessControl.None(), }); testCustom('access control ownable', { - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testCustom('access control roles', { - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testCustom('access control roles default admin rules (default opts)', { @@ -70,7 +70,7 @@ testCustom('access control roles default admin rules (custom opts)', { testCustom('pausable with access control disabled', { // API should override access to true since it is required for pausable - access: AccessControl.None, + access: AccessControl.None(), pausable: true, upgradeable: false, }); @@ -79,7 +79,7 @@ testAPIEquivalence('custom API default'); testAPIEquivalence('custom API full upgradeable', { name: 'CustomContract', - access: AccessControl.Roles, + access: AccessControl.Roles(), pausable: true, upgradeable: true, }); diff --git a/packages/core/cairo_alpha/src/erc1155.test.ts b/packages/core/cairo_alpha/src/erc1155.test.ts index 097536647..96fac1703 100644 --- a/packages/core/cairo_alpha/src/erc1155.test.ts +++ b/packages/core/cairo_alpha/src/erc1155.test.ts @@ -55,7 +55,7 @@ testERC1155('basic non-upgradeable', { testERC1155('basic', {}); testERC1155('basic + roles', { - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC1155('no updatable uri', { @@ -76,7 +76,7 @@ testERC1155('mintable', { testERC1155('mintable + roles', { mintable: true, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC1155('mintable + roles DAR (default opts)', { @@ -95,12 +95,12 @@ testERC1155('royalty info disabled', { testERC1155('royalty info enabled default + ownable', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testERC1155('royalty info enabled default + roles', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC1155('royalty info enabled default + roles-DAR (custom opts)', { @@ -110,12 +110,12 @@ testERC1155('royalty info enabled default + roles-DAR (custom opts)', { testERC1155('royalty info enabled custom + ownable', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testERC1155('royalty info enabled custom + roles', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC1155('royalty info enabled custom + roles-DAR (default opts)', { @@ -130,13 +130,13 @@ testERC1155('royalty info enabled custom + roles-DAR (custom opts)', { testERC1155('full non-upgradeable roles', { ...allFeaturesON, - access: AccessControl.Roles, + access: AccessControl.Roles(), upgradeable: false, }); testERC1155('full upgradeable roles', { ...allFeaturesON, - access: AccessControl.Roles, + access: AccessControl.Roles(), upgradeable: true, }); @@ -172,7 +172,7 @@ testAPIEquivalence('API full upgradeable', { ...allFeaturesON, name: CUSTOM_NAME, baseUri: BASE_URI, - access: AccessControl.Roles, + access: AccessControl.Roles(), upgradeable: true, }); diff --git a/packages/core/cairo_alpha/src/erc20.test.ts b/packages/core/cairo_alpha/src/erc20.test.ts index 43283765f..b7f224ba5 100644 --- a/packages/core/cairo_alpha/src/erc20.test.ts +++ b/packages/core/cairo_alpha/src/erc20.test.ts @@ -49,12 +49,12 @@ testERC20('erc20 burnable', { testERC20('erc20 pausable', { pausable: true, - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testERC20('erc20 pausable with roles', { pausable: true, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC20('erc20 pausable with roles-DAR (default opts)', { @@ -97,12 +97,12 @@ test('erc20 votes, decimals too high', async t => { testERC20('erc20 mintable', { mintable: true, - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testERC20('erc20 mintable with roles', { mintable: true, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC20('erc20 mintable with roles-DAR (default opts)', { @@ -158,7 +158,7 @@ testERC20('erc20 votes, non-upgradeable', { testERC20('erc20 full, non-upgradeable', { premint: '2000', - access: AccessControl.Ownable, + access: AccessControl.Ownable(), burnable: true, mintable: true, votes: true, @@ -170,7 +170,7 @@ testERC20('erc20 full, non-upgradeable', { testERC20('erc20 full upgradeable', { premint: '2000', - access: AccessControl.Ownable, + access: AccessControl.Ownable(), burnable: true, mintable: true, votes: true, @@ -182,7 +182,7 @@ testERC20('erc20 full upgradeable', { testERC20('erc20 full upgradeable with roles', { premint: '2000', - access: AccessControl.Roles, + access: AccessControl.Roles(), burnable: true, mintable: true, votes: true, @@ -225,7 +225,7 @@ testAPIEquivalence('erc20 API full upgradeable', { symbol: 'CTK', decimals: '6', premint: '2000', - access: AccessControl.Roles, + access: AccessControl.Roles(), burnable: true, mintable: true, votes: true, diff --git a/packages/core/cairo_alpha/src/erc721.test.ts b/packages/core/cairo_alpha/src/erc721.test.ts index ab116d2b7..bfd04c49a 100644 --- a/packages/core/cairo_alpha/src/erc721.test.ts +++ b/packages/core/cairo_alpha/src/erc721.test.ts @@ -91,7 +91,7 @@ testERC721('pausable + enumerable', { testERC721('mintable + roles', { mintable: true, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC721('mintable + roles-DAR (default opts)', { @@ -110,12 +110,12 @@ testERC721('royalty info disabled', { testERC721('royalty info enabled default + ownable', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testERC721('royalty info enabled default + roles', { royaltyInfo: royaltyInfoOptions.enabledDefault, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC721('royalty info enabled default + roles-DAR (default opts)', { @@ -130,12 +130,12 @@ testERC721('royalty info enabled default + roles-DAR (custom opts)', { testERC721('royalty info enabled custom + ownable', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: AccessControl.Ownable, + access: AccessControl.Ownable(), }); testERC721('royalty info enabled custom + roles', { royaltyInfo: royaltyInfoOptions.enabledCustom, - access: AccessControl.Roles, + access: AccessControl.Roles(), }); testERC721('royalty info enabled custom + roles-DAR (default opts)', { diff --git a/packages/core/cairo_alpha/src/multisig.ts b/packages/core/cairo_alpha/src/multisig.ts index 416b9bcc4..757ba2b7e 100644 --- a/packages/core/cairo_alpha/src/multisig.ts +++ b/packages/core/cairo_alpha/src/multisig.ts @@ -46,7 +46,7 @@ export function buildMultisig(opts: MultisigOptions): Contract { // A Multisig contract is exclusively governed by its own multisig process. // The collective approval of the designated signers determines all actions. // No other access-control mechanism should override or bypass this process. - setAccessControl(c, AccessControl.None); + setAccessControl(c, AccessControl.None()); return c; } diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index 3f2ef972f..ece9a1cb3 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -28,20 +28,27 @@ export const darCustomOpts: RolesDefaultAdminRulesOptions = { darDefaultDelayIncrease: '1 week', }; +type AccessControlFactory = { + readonly None: () => Readonly<{ type: false } & typeof darDefaultOpts>; + readonly Ownable: () => Readonly<{ type: 'ownable' } & typeof darDefaultOpts>; + readonly Roles: () => Readonly<{ type: 'roles' } & typeof darDefaultOpts>; + readonly RolesDefaultAdminRules: ( + opts: RolesDefaultAdminRulesOptions, + ) => Readonly<{ type: 'roles-dar' } & RolesDefaultAdminRulesOptions>; +}; + export const AccessControl = { - None: { type: false, ...darDefaultOpts } as const, - Ownable: { type: 'ownable', ...darDefaultOpts } as const, - Roles: { type: 'roles', ...darDefaultOpts } as const, - RolesDefaultAdminRules: (opts: RolesDefaultAdminRulesOptions) => { - return { type: 'roles-dar', ...opts } as const; - }, -} as const; + None: () => ({ type: false, ...darDefaultOpts }) as const, + Ownable: () => ({ type: 'ownable', ...darDefaultOpts }) as const, + Roles: () => ({ type: 'roles', ...darDefaultOpts }) as const, + RolesDefaultAdminRules: (opts: RolesDefaultAdminRulesOptions) => ({ type: 'roles-dar', ...opts }) as const, +} as const satisfies AccessControlFactory; export const DEFAULT_ACCESS_CONTROL = 'ownable'; -export const accessOptions = [ - AccessControl.None, - AccessControl.Ownable, - AccessControl.Roles, +export const accessOptions: Access[] = [ + AccessControl.None(), + AccessControl.Ownable(), + AccessControl.Roles(), AccessControl.RolesDefaultAdminRules(darDefaultOpts), AccessControl.RolesDefaultAdminRules(darCustomOpts), ] as const; diff --git a/packages/core/cairo_alpha/src/vesting.ts b/packages/core/cairo_alpha/src/vesting.ts index 2e9c0e0ec..9365aca35 100644 --- a/packages/core/cairo_alpha/src/vesting.ts +++ b/packages/core/cairo_alpha/src/vesting.ts @@ -55,7 +55,7 @@ export function buildVesting(opts: VestingOptions): Contract { setInfo(c, allOpts.info); // Vesting component depends on Ownable component - const access = AccessControl.Ownable; + const access = AccessControl.Ownable(); setAccessControl(c, access); // Must be non-upgradable to guarantee vesting according to the schedule From 24ee5c1e37d125a09f331251bf0d4bb8f1a631e9 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 12:41:53 +0300 Subject: [PATCH 28/40] Introduce AccessControl subset --- .../cairo_alpha/src/set-access-control.ts | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/packages/core/cairo_alpha/src/set-access-control.ts b/packages/core/cairo_alpha/src/set-access-control.ts index ece9a1cb3..fab4b90d7 100644 --- a/packages/core/cairo_alpha/src/set-access-control.ts +++ b/packages/core/cairo_alpha/src/set-access-control.ts @@ -45,13 +45,41 @@ export const AccessControl = { } as const satisfies AccessControlFactory; export const DEFAULT_ACCESS_CONTROL = 'ownable'; -export const accessOptions: Access[] = [ - AccessControl.None(), - AccessControl.Ownable(), - AccessControl.Roles(), - AccessControl.RolesDefaultAdminRules(darDefaultOpts), - AccessControl.RolesDefaultAdminRules(darCustomOpts), -] as const; + +export type AccessSubset = + | 'all' + | 'disabled' + | 'ownable' + | 'roles' + | 'roles-dar-default' + | 'roles-dar-custom'; + +export function resolveAccessControlOptions(subset: AccessSubset): Access[] { + switch (subset) { + case 'all': + return [ + AccessControl.None(), + AccessControl.Ownable(), + AccessControl.Roles(), + AccessControl.RolesDefaultAdminRules(darDefaultOpts), + AccessControl.RolesDefaultAdminRules(darCustomOpts), + ]; + case 'disabled': + return [AccessControl.None()]; + case 'ownable': + return [AccessControl.Ownable()]; + case 'roles': + return [AccessControl.Roles()]; + case 'roles-dar-default': + return [AccessControl.RolesDefaultAdminRules(darDefaultOpts)]; + case 'roles-dar-custom': + return [AccessControl.RolesDefaultAdminRules(darCustomOpts)]; + default: { + const _: never = subset; + throw new Error('Unknown AccessControlSubset'); + } + } +} const DEFAULT_ADMIN_DELAY_INCREASE_WAIT = BigInt(5 * 24 * 60 * 60); // 5 days From 4c8a8bd2d07e295bf2ab0c00d7c16e14f539aa31 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 12:42:30 +0300 Subject: [PATCH 29/40] Support access control subset parsing in test project script --- .../src/scripts/update-scarb-project.ts | 106 ++++++++++++++---- 1 file changed, 86 insertions(+), 20 deletions(-) diff --git a/packages/core/cairo_alpha/src/scripts/update-scarb-project.ts b/packages/core/cairo_alpha/src/scripts/update-scarb-project.ts index ae4db934d..088993820 100644 --- a/packages/core/cairo_alpha/src/scripts/update-scarb-project.ts +++ b/packages/core/cairo_alpha/src/scripts/update-scarb-project.ts @@ -2,33 +2,31 @@ import { promises as fs } from 'fs'; import path from 'path'; import type { KindSubset } from '../generate/sources'; +import type { AccessSubset } from '../set-access-control'; +import type { RoyaltyInfoSubset } from '../set-royalty-info'; import { writeGeneratedSources } from '../generate/sources'; import { contractsVersion, edition, cairoVersion, scarbVersion } from '../utils/version'; -import type { RoyaltyInfoSubset } from '../set-royalty-info'; type Arguments = { kind: KindSubset; + access: AccessSubset; royaltyInfo: RoyaltyInfoSubset; }; +const defaults: Arguments = { + kind: 'all', + access: 'all', + royaltyInfo: 'all', +} as const; + export function resolveArguments(): Arguments { const cliArgs = process.argv.slice(2); - switch (cliArgs.length) { - case 0: - return { kind: 'all', royaltyInfo: 'all' }; - case 1: - return { - kind: parseKindSubset(cliArgs[0]), - royaltyInfo: 'all', - }; - case 2: - return { - kind: parseKindSubset(cliArgs[0]), - royaltyInfo: parseRoyaltyInfoSubset(cliArgs[1]), - }; - default: - throw new Error(`Too many CLI arguments provided: ${cliArgs.length}.`); - } + const args = parseCliArgs(cliArgs); + return { + kind: parseKindSubset(args.kind ?? defaults.kind), + access: parseAccessSubset(args.access ?? defaults.access), + royaltyInfo: parseRoyaltyInfoSubset(args.royalty ?? defaults.royaltyInfo), + }; } export async function updateScarbProject() { @@ -36,12 +34,13 @@ export async function updateScarbProject() { await fs.rm(generatedSourcesPath, { force: true, recursive: true }); // Generate the contracts source code - const { kind, royaltyInfo } = resolveArguments(); + const { kind, access, royaltyInfo } = resolveArguments(); const contractNames = await writeGeneratedSources({ dir: generatedSourcesPath, subset: 'all', uniqueName: true, kind, + access, royaltyInfo, logsEnabled: true, }); @@ -107,6 +106,69 @@ function parseKindSubset(value: string | undefined): KindSubset { } } +function parseCliArgs(args: string[]): Record { + const result: Record = {}; + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (!arg) continue; + + if (arg.startsWith('--')) { + const argName = arg.slice(2); + if (argName.includes('=')) { + // Handle --arg=value format + const parts = argName.split('=', 2); + const key = parts[0]; + const value = parts[1]; + if (key && value !== undefined) { + result[key] = value; + } else { + throw new Error(`Invalid argument format: ${arg}`); + } + } else if (i + 1 < args.length) { + // Handle --arg value format + const nextArg = args[i + 1]; + if (nextArg && !nextArg.startsWith('--')) { + result[argName] = nextArg; + i++; // Skip the next argument since we've used it as a value + } else { + throw new Error(`No value provided for argument: ${arg}`); + } + } else { + throw new Error(`No value provided for argument: ${arg}`); + } + } else { + throw new Error(`Invalid argument format: ${arg}. Expected --key=value or --key value`); + } + } + return result; +} + +function parseAccessSubset(value: string | undefined): AccessSubset { + if (value === undefined) { + throw new Error(`Failed to resolve access subset from 'undefined'.`); + } + switch (value.toLowerCase()) { + case 'all': + return 'all'; + case 'disabled': + case 'none': + case 'no': + return 'disabled'; + case 'ownable': + return 'ownable'; + case 'roles': + return 'roles'; + case 'roles-dar-default': + case 'roles_dar_default': + return 'roles-dar-default'; + case 'roles-dar-custom': + case 'roles_dar_custom': + return 'roles-dar-custom'; + default: + throw new Error(`Failed to resolve access subset from '${value}' value.`); + } +} + function parseRoyaltyInfoSubset(value: string | undefined): RoyaltyInfoSubset { if (value === undefined) { throw new Error(`Failed to resolve royalty info subset from 'undefined'.`); @@ -115,11 +177,15 @@ function parseRoyaltyInfoSubset(value: string | undefined): RoyaltyInfoSubset { case 'all': return 'all'; case 'disabled': + case 'none': + case 'no': return 'disabled'; + case 'enabled-default': case 'enabled_default': - return 'enabled_default'; + return 'enabled-default'; + case 'enabled-custom': case 'enabled_custom': - return 'enabled_custom'; + return 'enabled-custom'; default: throw new Error(`Failed to resolve royalty info subset from '${value}' value.`); } From 691d5a4db7e9575ba620edb1ca752bc60e063851 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 12:43:55 +0300 Subject: [PATCH 30/40] Add access control subset to ERC20, ERC721, ERC1155, and Custom contracts --- .../core/cairo_alpha/src/generate/custom.ts | 24 +++++++---- .../core/cairo_alpha/src/generate/erc1155.ts | 6 ++- .../core/cairo_alpha/src/generate/erc20.ts | 40 +++++++++++-------- .../core/cairo_alpha/src/generate/erc721.ts | 6 ++- .../core/cairo_alpha/src/set-royalty-info.ts | 6 +-- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/packages/core/cairo_alpha/src/generate/custom.ts b/packages/core/cairo_alpha/src/generate/custom.ts index 40207666a..9e7772503 100644 --- a/packages/core/cairo_alpha/src/generate/custom.ts +++ b/packages/core/cairo_alpha/src/generate/custom.ts @@ -1,19 +1,27 @@ import type { CustomOptions } from '../custom'; -import { accessOptions } from '../set-access-control'; +import type { AccessSubset } from '../set-access-control'; +import { resolveAccessControlOptions } from '../set-access-control'; import { infoOptions } from '../set-info'; import { upgradeableOptions } from '../set-upgradeable'; import { generateAlternatives } from './alternatives'; const booleans = [true, false]; -const blueprint = { - name: ['MyContract'], - pausable: booleans, - access: accessOptions, - upgradeable: upgradeableOptions, - info: infoOptions, +type GeneratorOptions = { + access: AccessSubset; }; -export function* generateCustomOptions(): Generator> { +function prepareBlueprint(opts: GeneratorOptions) { + return { + name: ['MyContract'], + pausable: booleans, + access: resolveAccessControlOptions(opts.access), + upgradeable: upgradeableOptions, + info: infoOptions, + }; +} + +export function* generateCustomOptions(opts: GeneratorOptions): Generator> { + const blueprint = prepareBlueprint(opts); yield* generateAlternatives(blueprint); } diff --git a/packages/core/cairo_alpha/src/generate/erc1155.ts b/packages/core/cairo_alpha/src/generate/erc1155.ts index bc2d3dcd9..74cc016a3 100644 --- a/packages/core/cairo_alpha/src/generate/erc1155.ts +++ b/packages/core/cairo_alpha/src/generate/erc1155.ts @@ -1,5 +1,6 @@ import type { ERC1155Options } from '../erc1155'; -import { accessOptions } from '../set-access-control'; +import type { AccessSubset } from '../set-access-control'; +import { resolveAccessControlOptions } from '../set-access-control'; import { infoOptions } from '../set-info'; import { upgradeableOptions } from '../set-upgradeable'; import type { RoyaltyInfoSubset } from '../set-royalty-info'; @@ -9,6 +10,7 @@ import { generateAlternatives } from './alternatives'; const booleans = [true, false]; type GeneratorOptions = { + access: AccessSubset; royaltyInfo: RoyaltyInfoSubset; }; @@ -23,7 +25,7 @@ function prepareBlueprint(opts: GeneratorOptions) { updatableUri: booleans, upgradeable: upgradeableOptions, royaltyInfo, - access: accessOptions, + access: resolveAccessControlOptions(opts.access), info: infoOptions, }; } diff --git a/packages/core/cairo_alpha/src/generate/erc20.ts b/packages/core/cairo_alpha/src/generate/erc20.ts index 6d73a7e9d..c652aaf27 100644 --- a/packages/core/cairo_alpha/src/generate/erc20.ts +++ b/packages/core/cairo_alpha/src/generate/erc20.ts @@ -1,27 +1,35 @@ import type { ERC20Options } from '../erc20'; -import { accessOptions } from '../set-access-control'; +import type { AccessSubset } from '../set-access-control'; +import { resolveAccessControlOptions } from '../set-access-control'; import { infoOptions } from '../set-info'; import { upgradeableOptions } from '../set-upgradeable'; import { generateAlternatives } from './alternatives'; const booleans = [true, false]; -const blueprint = { - name: ['MyToken'], - symbol: ['MTK'], - decimals: ['6', '18'], - burnable: booleans, - pausable: booleans, - mintable: booleans, - premint: ['1'], - votes: booleans, - appName: ['MyApp'], - appVersion: ['v1'], - access: accessOptions, - upgradeable: upgradeableOptions, - info: infoOptions, +type GeneratorOptions = { + access: AccessSubset; }; -export function* generateERC20Options(): Generator> { +function prepareBlueprint(opts: GeneratorOptions) { + return { + name: ['MyToken'], + symbol: ['MTK'], + decimals: ['6', '18'], + burnable: booleans, + pausable: booleans, + mintable: booleans, + premint: ['1'], + votes: booleans, + appName: ['MyApp'], + appVersion: ['v1'], + access: resolveAccessControlOptions(opts.access), + upgradeable: upgradeableOptions, + info: infoOptions, + }; +} + +export function* generateERC20Options(opts: GeneratorOptions): Generator> { + const blueprint = prepareBlueprint(opts); yield* generateAlternatives(blueprint); } diff --git a/packages/core/cairo_alpha/src/generate/erc721.ts b/packages/core/cairo_alpha/src/generate/erc721.ts index 2911e642d..461fe0e09 100644 --- a/packages/core/cairo_alpha/src/generate/erc721.ts +++ b/packages/core/cairo_alpha/src/generate/erc721.ts @@ -1,5 +1,6 @@ import type { ERC721Options } from '../erc721'; -import { accessOptions } from '../set-access-control'; +import type { AccessSubset } from '../set-access-control'; +import { resolveAccessControlOptions } from '../set-access-control'; import { defaults as infoDefaults } from '../set-info'; import { upgradeableOptions } from '../set-upgradeable'; import type { RoyaltyInfoSubset } from '../set-royalty-info'; @@ -9,6 +10,7 @@ import { generateAlternatives } from './alternatives'; const booleans = [true, false]; type GeneratorOptions = { + access: AccessSubset; royaltyInfo: RoyaltyInfoSubset; }; @@ -26,7 +28,7 @@ function prepareBlueprint(opts: GeneratorOptions) { pausable: booleans, mintable: booleans, royaltyInfo, - access: accessOptions, + access: resolveAccessControlOptions(opts.access), upgradeable: upgradeableOptions, info: [infoDefaults], }; diff --git a/packages/core/cairo_alpha/src/set-royalty-info.ts b/packages/core/cairo_alpha/src/set-royalty-info.ts index 7b19340b8..c6024aa8e 100644 --- a/packages/core/cairo_alpha/src/set-royalty-info.ts +++ b/packages/core/cairo_alpha/src/set-royalty-info.ts @@ -13,7 +13,7 @@ export const defaults: RoyaltyInfoOptions = { feeDenominator: DEFAULT_FEE_DENOMINATOR.toString(), }; -export type RoyaltyInfoSubset = 'all' | 'disabled' | 'enabled_default' | 'enabled_custom'; +export type RoyaltyInfoSubset = 'all' | 'disabled' | 'enabled-default' | 'enabled-custom'; export const royaltyInfoOptions = { disabled: defaults, @@ -36,9 +36,9 @@ export function resolveRoyaltyOptionsSubset(subset: RoyaltyInfoSubset): RoyaltyI return [disabled, enabledDefault, enabledCustom]; case 'disabled': return [disabled]; - case 'enabled_default': + case 'enabled-default': return [enabledDefault]; - case 'enabled_custom': + case 'enabled-custom': return [enabledCustom]; default: { const _: never = subset; From 34b7b185e1b87abf920e29c3008ea18756056d93 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 12:44:39 +0300 Subject: [PATCH 31/40] Support access control subset options in contract generation logic --- .../core/cairo_alpha/src/generate/sources.ts | 92 +++++++++++++++---- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/packages/core/cairo_alpha/src/generate/sources.ts b/packages/core/cairo_alpha/src/generate/sources.ts index 756315225..5b42a452d 100644 --- a/packages/core/cairo_alpha/src/generate/sources.ts +++ b/packages/core/cairo_alpha/src/generate/sources.ts @@ -17,6 +17,7 @@ import { OptionsError } from '../error'; import { findCover } from '../utils/find-cover'; import type { Contract } from '../contract'; import type { RoyaltyInfoSubset } from '../set-royalty-info'; +import type { AccessSubset } from '../set-access-control'; export type Subset = 'all' | 'minimal-cover'; @@ -24,23 +25,24 @@ export type KindSubset = 'all' | keyof KindedOptions; export function* generateOptions(params: { kind: KindSubset; + access: AccessSubset; royaltyInfo: RoyaltyInfoSubset; }): Generator { - const { kind, royaltyInfo } = params; + const { kind, access, royaltyInfo } = params; if (kind === 'all' || kind === 'ERC20') { - for (const kindOpts of generateERC20Options()) { + for (const kindOpts of generateERC20Options({ access })) { yield { kind: 'ERC20', ...kindOpts }; } } if (kind === 'all' || kind === 'ERC721') { - for (const kindOpts of generateERC721Options({ royaltyInfo })) { + for (const kindOpts of generateERC721Options({ access,royaltyInfo })) { yield { kind: 'ERC721', ...kindOpts }; } } if (kind === 'all' || kind === 'ERC1155') { - for (const kindOpts of generateERC1155Options({ royaltyInfo })) { + for (const kindOpts of generateERC1155Options({ access, royaltyInfo })) { yield { kind: 'ERC1155', ...kindOpts }; } } @@ -70,7 +72,7 @@ export function* generateOptions(params: { } if (kind === 'all' || kind === 'Custom') { - for (const kindOpts of generateCustomOptions()) { + for (const kindOpts of generateCustomOptions({ access })) { yield { kind: 'Custom', ...kindOpts }; } } @@ -89,12 +91,13 @@ interface GeneratedSource extends GeneratedContract { function generateContractSubset(params: { subset: Subset; kind: KindSubset; + access: AccessSubset; royaltyInfo: RoyaltyInfoSubset; }): GeneratedContract[] { - const { subset, kind, royaltyInfo } = params; + const { subset, kind, access,royaltyInfo } = params; const contracts = []; - for (const options of generateOptions({ kind, royaltyInfo })) { + for (const options of generateOptions({ kind, access, royaltyInfo })) { const id = crypto.createHash('sha1').update(JSON.stringify(options)).digest().toString('hex'); try { const contract = buildGeneric(options); @@ -143,11 +146,12 @@ export function* generateSources(params: { subset: Subset; uniqueName: boolean; kind: KindSubset; + access: AccessSubset, royaltyInfo: RoyaltyInfoSubset; }): Generator { - const { subset, uniqueName, kind, royaltyInfo } = params; + const { subset, uniqueName, kind, access, royaltyInfo } = params; let counter = 1; - for (const c of generateContractSubset({ subset, kind, royaltyInfo })) { + for (const c of generateContractSubset({ subset, kind, access, royaltyInfo })) { if (uniqueName) { c.contract.name = `Contract${counter++}`; } @@ -161,41 +165,95 @@ export async function writeGeneratedSources(params: { subset: Subset; uniqueName: boolean; kind: KindSubset; + access: AccessSubset; royaltyInfo: RoyaltyInfoSubset; logsEnabled: boolean; }): Promise { - const { dir, subset, uniqueName, kind, royaltyInfo, logsEnabled } = params; + const { dir, subset, uniqueName, kind, access, royaltyInfo, logsEnabled } = params; await fs.mkdir(dir, { recursive: true }); const contractNames = []; - for (const { id, contract, source } of generateSources({ subset, uniqueName, kind, royaltyInfo })) { + for (const { id, contract, source } of generateSources({ subset, uniqueName, kind, access, royaltyInfo })) { const name = uniqueName ? contract.name : id; await fs.writeFile(path.format({ dir, name, ext: '.cairo' }), source); contractNames.push(name); } if (logsEnabled) { - const sourceLabel = resolveSourceLabel({ kind, royaltyInfo }); + const sourceLabel = resolveSourceLabel({ kind, access, royaltyInfo }); console.log(`Generated ${contractNames.length} contracts for ${sourceLabel}`); } return contractNames; } -function resolveSourceLabel(params: { kind: KindSubset; royaltyInfo: RoyaltyInfoSubset }): string { - const { kind, royaltyInfo } = params; +function resolveSourceLabel(params: { + kind: KindSubset; + access: AccessSubset; + royaltyInfo: RoyaltyInfoSubset +}): string { + const { kind, access, royaltyInfo } = params; + return [ + resolveKindLabel(kind), + resolveAccessLabel(kind, access), + resolveRoyaltyInfoLabel(kind, royaltyInfo) + ] + .filter(elem => elem !== undefined) + .join(', '); +} + +function resolveKindLabel(kind: KindSubset): string { switch (kind) { + case 'all': + return 'All kinds'; + case 'ERC20': case 'ERC721': case 'ERC1155': - return `${kind} (royaltyInfo: ${royaltyInfo})`; + case 'Account': + case 'Multisig': + case 'Governor': + case 'Vesting': + case 'Custom': + return kind; + default: { + const _: never = kind; + throw new Error('Unknown kind'); + } + } +} + +function resolveAccessLabel(kind: KindSubset, access: AccessSubset): string | undefined { + switch (kind) { case 'all': - return 'All contract kinds'; + case 'Custom': case 'ERC20': + case 'ERC721': + case 'ERC1155': + return `access: ${access}`; case 'Account': case 'Multisig': case 'Governor': case 'Vesting': + return undefined; + default: { + const _: never = kind; + throw new Error('Unknown kind'); + } + } +} + +function resolveRoyaltyInfoLabel(kind: KindSubset, royaltyInfo: RoyaltyInfoSubset): string | undefined { + switch (kind) { + case 'all': + case 'ERC721': + case 'ERC1155': + return `royalty: ${royaltyInfo}`; + case 'ERC20': + case 'Account': case 'Custom': - return kind; + case 'Multisig': + case 'Governor': + case 'Vesting': + return undefined; default: { const _: never = kind; throw new Error('Unknown kind'); From cd7a93db5ac0152fab955e57a084946132e67393 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 12:44:56 +0300 Subject: [PATCH 32/40] Support access control subset in tests --- packages/core/cairo_alpha/src/test.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/core/cairo_alpha/src/test.ts b/packages/core/cairo_alpha/src/test.ts index 30ad85d75..7eb96152b 100644 --- a/packages/core/cairo_alpha/src/test.ts +++ b/packages/core/cairo_alpha/src/test.ts @@ -5,10 +5,11 @@ import _test from 'ava'; import path from 'path'; import type { KindSubset } from './generate/sources'; -import { generateSources, writeGeneratedSources } from './generate/sources'; +import type { AccessSubset } from './set-access-control'; +import type { RoyaltyInfoSubset } from './set-royalty-info'; import type { GenericOptions } from './build-generic'; +import { generateSources, writeGeneratedSources } from './generate/sources'; import { custom, erc20, erc721, erc1155 } from './api'; -import type { RoyaltyInfoSubset } from './set-royalty-info'; interface Context { generatedSourcesPath: string; @@ -17,15 +18,15 @@ interface Context { const test = _test as TestFn; test.serial('erc20 results generated', async ctx => { - await testGenerate({ ctx, kind: 'ERC20' }); + await testGenerate({ ctx, kind: 'ERC20', access: 'all' }); }); test.serial('erc721 results generated', async ctx => { - await testGenerate({ ctx, kind: 'ERC721', royaltyInfo: 'all' }); + await testGenerate({ ctx, kind: 'ERC721', access: 'all', royaltyInfo: 'all' }); }); test.serial('erc1155 results generated', async ctx => { - await testGenerate({ ctx, kind: 'ERC1155', royaltyInfo: 'all' }); + await testGenerate({ ctx, kind: 'ERC1155', access: 'all', royaltyInfo: 'all' }); }); test.serial('account results generated', async ctx => { @@ -45,15 +46,16 @@ test.serial('vesting results generated', async ctx => { }); test.serial('custom results generated', async ctx => { - await testGenerate({ ctx, kind: 'Custom' }); + await testGenerate({ ctx, kind: 'Custom', access: 'all' }); }); async function testGenerate(params: { ctx: ExecutionContext; kind: KindSubset; + access?: AccessSubset; royaltyInfo?: RoyaltyInfoSubset; }) { - const { ctx, kind, royaltyInfo } = params; + const { ctx, kind, access, royaltyInfo } = params; const generatedSourcesPath = path.join(os.tmpdir(), 'oz-wizard-cairo-alpha'); await fs.rm(generatedSourcesPath, { force: true, recursive: true }); await writeGeneratedSources({ @@ -61,6 +63,7 @@ async function testGenerate(params: { subset: 'all', uniqueName: true, kind, + access: access || 'all', royaltyInfo: royaltyInfo || 'all', logsEnabled: false, }); @@ -96,6 +99,7 @@ test('is access control required', async t => { subset: 'all', uniqueName: false, kind: 'all', + access: 'all', royaltyInfo: 'all', }); for (const contract of allSources) { From 83726460175a57931574177d72a2e8f1475d1685 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 12:45:34 +0300 Subject: [PATCH 33/40] Update Cairo-alpha CI test project workflow to support access control subset for ERC20, ERC721, ERC1155, and Custom contracts --- .../workflows/compile-cairo-alpha-project.yml | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile-cairo-alpha-project.yml b/.github/workflows/compile-cairo-alpha-project.yml index 09cf419cd..d62cacd4c 100644 --- a/.github/workflows/compile-cairo-alpha-project.yml +++ b/.github/workflows/compile-cairo-alpha-project.yml @@ -47,15 +47,31 @@ jobs: set -e declare -a all_kinds=("ERC20" "ERC721" "ERC1155" "Account" "Multisig" "Governor" "Vesting" "Custom") - declare -a all_royalty_info_options=("disabled" "enabled_default" "enabled_custom") + declare -a all_access_options=("disabled" "ownable" "roles" "roles-dar-default" "roles-dar-custom") + declare -a all_royalty_options=("disabled" "enabled-default" "enabled-custom") for kind in "${all_kinds[@]}"; do scarb clean if [[ "$kind" == "ERC721" || "$kind" == "ERC1155" ]]; then - for royalty_info_option in "${all_royalty_info_options[@]}"; do - proj_name="'$kind (royalty info: $royalty_info_option)' test project" + for access_option in "${all_access_options[@]}"; do + for royalty_option in "${all_royalty_options[@]}"; do + proj_name="'$kind, access: $access_option, royalty: $royalty_option' test project" + echo "Generating $proj_name..." + yarn run update_scarb_project --kind=$kind --access=$access_option --royalty=$royalty_option + + echo "Compiling $proj_name..." + scarb build + + echo "✅ Compiled $proj_name!" + echo "---------------------------------" + done + done + + elif [[ "$kind" == "ERC20" || "$kind" == "Custom" ]]; then + for access_option in "${all_access_options[@]}"; do + proj_name="'$kind, access: $access_option' test project" echo "Generating $proj_name..." - yarn run update_scarb_project $kind $royalty_info_option + yarn run update_scarb_project --kind=$kind --access=$access_option echo "Compiling $proj_name..." scarb build From 755ffef0b2c9f7cf05c2a2fde6e74f1507b413d6 Mon Sep 17 00:00:00 2001 From: immrsd Date: Fri, 24 Oct 2025 13:51:54 +0300 Subject: [PATCH 34/40] Update links to Cairo-alpha docs in AccountControls.svelte --- packages/ui/src/cairo_alpha/AccessControlSection.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/cairo_alpha/AccessControlSection.svelte b/packages/ui/src/cairo_alpha/AccessControlSection.svelte index 72d149cf9..d00956434 100644 --- a/packages/ui/src/cairo_alpha/AccessControlSection.svelte +++ b/packages/ui/src/cairo_alpha/AccessControlSection.svelte @@ -37,28 +37,28 @@ bind:value={accessType} defaultValue="ownable" helpContent="Restrict who can access the functions of a contract or when they can do it." - helpLink="https://docs.openzeppelin.com/contracts-cairo/access" + helpLink="https://docs.openzeppelin.com/contracts-cairo/alpha/access" {required} >