Skip to content
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
45219c8
Cairo: Update Stable directory (#755)
immrsd Jan 6, 2026
28d7b0d
Cairo: support v3.0.0 audit fixes (#756)
immrsd Jan 6, 2026
f982263
Add changelog for Cairo-stable v3.0.0
immrsd Jan 6, 2026
39eb4dc
Revert wizard-cairo version bump
immrsd Jan 6, 2026
b466665
Add changeset
immrsd Jan 6, 2026
5f718b2
Update changeset description
immrsd Jan 7, 2026
163dbd2
Fix Cairo-stable and Cairo-alpha test project scripts
immrsd Jan 7, 2026
399c385
Revert changes to Cairo-stable package.json
immrsd Jan 7, 2026
920c36f
Fix test project path for Cairo-stable
immrsd Jan 7, 2026
f66a5d2
Fix defaults object usage in tests for Cairo-stable
immrsd Jan 7, 2026
043fb11
Fix defaults object usage in tests for Cairo-alpha
immrsd Jan 7, 2026
5034ceb
Merge master
immrsd Jan 8, 2026
6bcc2b6
Remove Cairo legacy access AI description
immrsd Jan 8, 2026
01785b0
Add minor bump to contracts-mcp to changeset
immrsd Jan 8, 2026
4baf9eb
Update schemas in contracts-mcp to support Cairo v3.0.0
immrsd Jan 8, 2026
e6a9e62
Revert changes to Cairo-stable changelog
immrsd Jan 8, 2026
ab36fa0
Add expected Changelog changes for Cairo-alpha
immrsd Jan 8, 2026
a0b2980
Set Cairo-alpha version equal to stable
immrsd Jan 8, 2026
20f6b7a
Set Cairo-alpha version in utils equal to stable version
immrsd Jan 8, 2026
5a4b7a0
Update Cairo-alpha test project dependencies to match stable
immrsd Jan 8, 2026
6cbe726
Include Cairo-stable audit fixes updates into Cairo-alpha
immrsd Jan 8, 2026
8186cfa
Update Cairo-alpha AI description for access
immrsd Jan 8, 2026
d33fd73
Support Cairo v3.0.0 audit fixes in Cairo-alpha UI
immrsd Jan 8, 2026
0a5dc29
Update Cairo-alpha snapshots
immrsd Jan 8, 2026
f4e0da2
Fix Cairo AI description for access property
immrsd Jan 8, 2026
2fd3fa9
Format files
immrsd Jan 8, 2026
20f889b
Update .changeset/brown-bugs-start.md
immrsd Jan 9, 2026
9134c88
Update .changeset/brown-bugs-start.md
immrsd Jan 9, 2026
59fe1ed
Update Cairo-alpha changelog
immrsd Jan 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/brown-bugs-start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@openzeppelin/wizard-cairo': major
'@openzeppelin/contracts-mcp': minor
'@openzeppelin/wizard-common': patch
---

- Add support for `with_components` macro. ([#703](https://github.com/OpenZeppelin/contracts-wizard/pull/703))
- 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))
- Use OpenZeppelin Contracts for Cairo v3.0.0-alpha.1. ([#638](https://github.com/OpenZeppelin/contracts-wizard/pull/638))
- Use OpenZeppelin Contracts for Cairo v3.0.0-alpha.0. ([#623](https://github.com/OpenZeppelin/contracts-wizard/pull/623))
11 changes: 7 additions & 4 deletions .github/workflows/compile-cairo-alpha-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
yarn run update_scarb_project --kind=$kind --macros=$macros_option --access=$access_option --royalty=$royalty_option

echo "Compiling $proj_name..."
scarb clean
scarb build

echo "✅ Compiled $proj_name!"
Expand All @@ -70,24 +71,26 @@ jobs:

elif [[ "$kind" == "ERC20" || "$kind" == "Custom" ]]; then
for access_option in "${all_access_options[@]}"; do
proj_name="'$kind, access: $access_option' test project"
proj_name="'$kind, macros: $macros_option, access: $access_option' test project"
echo "Generating $proj_name..."
yarn run update_scarb_project --kind=$kind --access=$access_option
yarn run update_scarb_project --kind=$kind --macros=$macros_option --access=$access_option

echo "Compiling $proj_name..."
scarb clean
scarb build

echo "✅ Compiled $proj_name!"
echo "---------------------------------"
done

else
proj_name="'$kind' test project"
proj_name="'$kind, macros: $macros_option' test project"

echo "Generating $proj_name..."
yarn run update_scarb_project --kind=$kind
yarn run update_scarb_project --kind=$kind --macros=$macros_option

echo "Compiling $proj_name..."
scarb clean
scarb build

echo "✅ Compiled $proj_name!"
Expand Down
63 changes: 42 additions & 21 deletions .github/workflows/compile-cairo-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,55 @@ 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")
for kind in "${all_kinds[@]}"; do
scarb clean
declare -a all_macros_options=("none" "with_components")
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 macros_option in "${all_macros_options[@]}"; do
for kind in "${all_kinds[@]}"; do
if [[ "$kind" == "ERC721" || "$kind" == "ERC1155" ]]; then
for access_option in "${all_access_options[@]}"; do
for royalty_option in "${all_royalty_options[@]}"; do
proj_name="'$kind, macros: $macros_option, access: $access_option, royalty: $royalty_option' test project"
echo "Generating $proj_name..."
yarn run update_scarb_project --kind=$kind --macros=$macros_option --access=$access_option --royalty=$royalty_option

echo "Compiling $proj_name..."
scarb clean
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, macros: $macros_option, access: $access_option' test project"
echo "Generating $proj_name..."
yarn run update_scarb_project --kind=$kind --macros=$macros_option --access=$access_option

echo "Compiling $proj_name..."
scarb clean
scarb build

echo "✅ Compiled $proj_name!"
echo "---------------------------------"
done

else
proj_name="'$kind, macros: $macros_option' test project"

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"
echo "Generating $proj_name..."
yarn run update_scarb_project $kind $royalty_info_option
yarn run update_scarb_project --kind=$kind --macros=$macros_option

echo "Compiling $proj_name..."
scarb clean
scarb build

echo "✅ Compiled $proj_name!"
echo "---------------------------------"
done

else
proj_name="'$kind' test project"

echo "Generating $proj_name..."
yarn run update_scarb_project $kind

echo "Compiling $proj_name..."
scarb build

echo "✅ Compiled $proj_name!"
echo "---------------------------------"
fi
fi
done

done
8 changes: 4 additions & 4 deletions packages/common/src/ai/descriptions/cairo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ export const cairoPrompts = {
};

export const cairoCommonDescriptions = {
access:
'The type of access control to provision. Ownable is a simple mechanism with a single account authorized for all privileged actions. Roles is a flexible mechanism with a separate role for each privileged action. A role can have many authorized accounts.',
upgradeable: 'Whether the smart contract is upgradeable.',
appName:
'Required when votes is enabled, for hashing and signing typed structured data. Name for domain separator implementing SNIP12Metadata trait. Prevents two applications from producing the same hash.',
Expand All @@ -32,12 +30,14 @@ export const cairoMacrosDescriptions = {
withComponents: 'Whether to use the "with_components" macro for simplified contract structure.',
};

export const cairoAlphaAccessDescriptions = {
export const cairoAccessDescriptions = {
accessType:
'The type of access control to provision. Ownable is a simple mechanism with a single account authorized for all privileged actions. Roles is a flexible mechanism with a separate role for each privileged action. A role can have many authorized accounts. Roles (Default Admin Rules) provides additional enforced security measures on top of standard Roles mechanism for managing the most privileged role: default admin.',
darInitialDelay: 'The initial delay for the default admin role (in case Roles (Default Admin Rules) is used).',
darDefaultDelayIncrease:
'The default delay increase for the default admin role (in case Roles (Default Admin Rules) is used).',
'The default delay increase in seconds for the default admin role (in case Roles (Default Admin Rules) is used).',
darMaxTransferDelay:
'The maximum delay in seconds for a default admin transfer (in case Roles (Default Admin Rules) is used).',
};

export const cairoRoyaltyInfoDescriptions = {
Expand Down
1 change: 0 additions & 1 deletion packages/core/cairo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Changelog


## 2.1.0 (2025-09-16)

- Support decimals customization for ERC20 Cairo contracts ([#654](https://github.com/OpenZeppelin/contracts-wizard/pull/654))
Expand Down
2 changes: 1 addition & 1 deletion packages/core/cairo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ The following contract types are supported:
- `erc721`
- `erc1155`
- `account`
- `governor`
- `multisig`
- `governor`
- `vesting`
- `custom`

Expand Down
1 change: 1 addition & 0 deletions packages/core/cairo/ava.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
watchmode: {
ignoreChanges: ['contracts', 'artifacts', 'cache'],
},
snapshotDir: '.',
timeout: '10m',
workerThreads: false,
};
Binary file removed packages/core/cairo/src/account.test.ts.snap
Binary file not shown.
21 changes: 14 additions & 7 deletions packages/core/cairo/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const defaults: Required<AccountOptions> = {
outsideExecution: true,
upgradeable: commonDefaults.upgradeable,
info: commonDefaults.info,
macros: commonDefaults.macros,
} as const;

export function printAccount(opts: AccountOptions = defaults): string {
Expand Down Expand Up @@ -49,17 +50,16 @@ function withDefaults(opts: AccountOptions): Required<AccountOptions> {

export function buildAccount(opts: AccountOptions): Contract {
const isAccount = true;
const c = new ContractBuilder(opts.name, isAccount);

const allOpts = withDefaults(opts);
const c = new ContractBuilder(allOpts.name, allOpts.macros, isAccount);

switch (allOpts.type) {
case 'stark':
c.addConstructorArgument({ name: 'public_key', type: 'felt252' });
c.addComponent(components.AccountComponent, [{ lit: 'public_key' }], true);
break;
case 'eth':
c.addUseClause('openzeppelin::account::interface', 'EthPublicKey');
c.addUseClause('openzeppelin_interfaces::accounts', 'EthPublicKey');
c.addConstructorArgument({ name: 'public_key', type: 'EthPublicKey' });
c.addComponent(components.EthAccountComponent, [{ lit: 'public_key' }], true);
break;
Expand Down Expand Up @@ -98,10 +98,12 @@ function addSRC6(c: ContractBuilder, accountType: Account) {

c.addImplToComponent(componentType, {
name: 'SRC6Impl',
embed: true,
value: `${baseComponent}::SRC6Impl<ContractState>`,
});
c.addImplToComponent(componentType, {
name: 'SRC6CamelOnlyImpl',
embed: true,
value: `${baseComponent}::SRC6CamelOnlyImpl<ContractState>`,
});

Expand All @@ -113,6 +115,7 @@ function addDeclarer(c: ContractBuilder, accountType: Account) {

c.addImplToComponent(componentType, {
name: 'DeclarerImpl',
embed: true,
value: `${baseComponent}::DeclarerImpl<ContractState>`,
});
}
Expand All @@ -122,6 +125,7 @@ function addDeployer(c: ContractBuilder, accountType: Account) {

c.addImplToComponent(componentType, {
name: 'DeployableImpl',
embed: true,
value: `${baseComponent}::DeployableImpl<ContractState>`,
});
}
Expand All @@ -131,16 +135,17 @@ function addPublicKey(c: ContractBuilder, accountType: Account) {

c.addImplToComponent(componentType, {
name: 'PublicKeyImpl',
embed: true,
value: `${baseComponent}::PublicKeyImpl<ContractState>`,
});
c.addImplToComponent(componentType, {
name: 'PublicKeyCamelImpl',
embed: true,
value: `${baseComponent}::PublicKeyCamelImpl<ContractState>`,
});
}

function addOutsideExecution(c: ContractBuilder) {
c.addUseClause('openzeppelin::account::extensions', 'SRC9Component');
c.addComponent(components.SRC9Component, [], true);
}

Expand All @@ -151,6 +156,7 @@ function addAccountMixin(c: ContractBuilder, accountType: Account) {
c.addImplToComponent(componentType, {
name: `${accountMixinImpl}`,
value: `${baseComponent}::${accountMixinImpl}<ContractState>`,
embed: true,
});

c.addInterfaceFlag('ISRC5');
Expand All @@ -167,7 +173,7 @@ function getBaseCompAndCompType(accountType: Account): [string, typeof component

const components = defineComponents({
AccountComponent: {
path: 'openzeppelin::account',
path: 'openzeppelin_account',
substorage: {
name: 'account',
type: 'AccountComponent::Storage',
Expand All @@ -185,7 +191,7 @@ const components = defineComponents({
],
},
EthAccountComponent: {
path: 'openzeppelin::account::eth_account',
path: 'openzeppelin_account::eth_account',
substorage: {
name: 'eth_account',
type: 'EthAccountComponent::Storage',
Expand All @@ -203,7 +209,7 @@ const components = defineComponents({
],
},
SRC9Component: {
path: 'openzeppelin::account::extensions',
path: 'openzeppelin_account::extensions',
substorage: {
name: 'src9',
type: 'SRC9Component::Storage',
Expand All @@ -215,6 +221,7 @@ const components = defineComponents({
impls: [
{
name: 'OutsideExecutionV2Impl',
embed: true,
value: 'SRC9Component::OutsideExecutionV2Impl<ContractState>',
},
{
Expand Down
3 changes: 2 additions & 1 deletion packages/core/cairo/src/add-pausable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function addPausable(c: ContractBuilder, access: Access) {

const components = defineComponents({
PausableComponent: {
path: 'openzeppelin::security::pausable',
path: 'openzeppelin_security::pausable',
substorage: {
name: 'pausable',
type: 'PausableComponent::Storage',
Expand All @@ -29,6 +29,7 @@ const components = defineComponents({
impls: [
{
name: 'PausableImpl',
embed: true,
value: 'PausableComponent::PausableImpl<ContractState>',
},
{
Expand Down
12 changes: 8 additions & 4 deletions packages/core/cairo/src/common-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type Token = (typeof tokenTypes)[number];

const components = defineComponents({
SRC5Component: {
path: 'openzeppelin::introspection::src5',
path: 'openzeppelin_introspection::src5',
substorage: {
name: 'src5',
type: 'SRC5Component::Storage',
Expand All @@ -19,7 +19,7 @@ const components = defineComponents({
},

VotesComponent: {
path: 'openzeppelin::governance::votes',
path: 'openzeppelin_governance::votes',
substorage: {
name: 'votes',
type: 'VotesComponent::Storage',
Expand All @@ -38,7 +38,7 @@ const components = defineComponents({
},

NoncesComponent: {
path: 'openzeppelin::utils::cryptography::nonces',
path: 'openzeppelin_utils::cryptography::nonces',
substorage: {
name: 'nonces',
type: 'NoncesComponent::Storage',
Expand All @@ -50,6 +50,7 @@ const components = defineComponents({
impls: [
{
name: 'NoncesImpl',
embed: true,
value: 'NoncesComponent::NoncesImpl<ContractState>',
},
],
Expand All @@ -62,6 +63,7 @@ export function addSRC5Component(c: ContractBuilder, section?: string) {
if (!c.interfaceFlags.has('ISRC5')) {
c.addImplToComponent(components.SRC5Component, {
name: 'SRC5Impl',
embed: true,
value: 'SRC5Component::SRC5Impl<ContractState>',
section,
});
Expand All @@ -75,12 +77,14 @@ export function addVotesComponent(c: ContractBuilder, name: string, version: str
c.addComponent(components.VotesComponent, [], false);
c.addImplToComponent(components.VotesComponent, {
name: 'VotesImpl',
embed: true,
value: `VotesComponent::VotesImpl<ContractState>`,
});
c.addUseClause('openzeppelin_utils::contract_clock', 'ERC6372TimestampClock');
}

export function addSNIP12Metadata(c: ContractBuilder, name: string, version: string, section?: string) {
c.addUseClause('openzeppelin::utils::cryptography::snip12', 'SNIP12Metadata');
c.addUseClause('openzeppelin_utils::cryptography::snip12', 'SNIP12Metadata');

const SNIP12Metadata: BaseImplementedTrait = {
name: 'SNIP12MetadataImpl',
Expand Down
Loading
Loading