diff --git a/packages/core-cairo/CHANGELOG.md b/packages/core-cairo/CHANGELOG.md index 5690a838..8553198c 100644 --- a/packages/core-cairo/CHANGELOG.md +++ b/packages/core-cairo/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.20.1 (2024-12-17) + +- Add OutsideExecution to accounts. ([#422](https://github.com/OpenZeppelin/contracts-wizard/pull/422)) + ## 0.20.0 (2024-12-10) - Add Governor tab. ([#417](https://github.com/OpenZeppelin/contracts-wizard/pull/417)) @@ -9,7 +13,7 @@ ## 0.19.0 (2024-11-27) -- Add ERC2981 (RoyaltyInfo) for ERC721 and ERC1155 ([#413](https://github.com/OpenZeppelin/contracts-wizard/pull/413)) +- Add ERC2981 (RoyaltyInfo) for ERC721 and ERC1155. ([#413](https://github.com/OpenZeppelin/contracts-wizard/pull/413)) ## 0.18.0 (2024-11-15) diff --git a/packages/core-cairo/package.json b/packages/core-cairo/package.json index ad0e12cb..decaeb1d 100644 --- a/packages/core-cairo/package.json +++ b/packages/core-cairo/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/wizard-cairo", - "version": "0.20.0", + "version": "0.20.1", "description": "A boilerplate generator to get started with OpenZeppelin Contracts for Cairo", "license": "MIT", "repository": "github:OpenZeppelin/contracts-wizard", diff --git a/packages/core-cairo/src/account.test.ts b/packages/core-cairo/src/account.test.ts index e6771d00..217e1d81 100644 --- a/packages/core-cairo/src/account.test.ts +++ b/packages/core-cairo/src/account.test.ts @@ -38,6 +38,7 @@ function testAPIEquivalence(title: string, opts?: AccountOptions) { declare: true, deploy: true, pubkey: true, + outsideExecution: true, ...opts, }))); }); @@ -55,6 +56,7 @@ testAccount('explicit full account, mixin + upgradeable', { declare: true, deploy: true, pubkey: true, + outsideExecution: true, upgradeable: true }); @@ -64,47 +66,62 @@ testAccount('explicit full account, mixin + non-upgradeable', { declare: true, deploy: true, pubkey: true, + outsideExecution: true, upgradeable: false }); testAccount('basic account, upgradeable', { declare: false, deploy: false, - pubkey: false + pubkey: false, + outsideExecution: false, }); testAccount('basic account, non-upgradeable', { declare: false, deploy: false, pubkey: false, + outsideExecution: false, upgradeable: false }); +testAccount('account outside execution', { + deploy: false, + pubkey: false, + declare: false, +}); + testAccount('account declarer', { deploy: false, - pubkey: false + pubkey: false, + outsideExecution: false, }); testAccount('account deployable', { declare: false, - pubkey: false + pubkey: false, + outsideExecution: false, }); testAccount('account public key', { declare: false, deploy: false, + outsideExecution: false, }); testAccount('account declarer, deployable', { - pubkey: false + pubkey: false, + outsideExecution: false, }); testAccount('account declarer, public key', { - deploy: false + deploy: false, + outsideExecution: false, }); testAccount('account deployable, public key', { - declare: false + declare: false, + outsideExecution: false, }); testEthAccount('default full ethAccount, mixin + upgradeable', {}); @@ -119,6 +136,7 @@ testEthAccount('explicit full ethAccount, mixin + upgradeable', { declare: true, deploy: true, pubkey: true, + outsideExecution: true, upgradeable: true }); @@ -128,47 +146,62 @@ testEthAccount('explicit full ethAccount, mixin + non-upgradeable', { declare: true, deploy: true, pubkey: true, + outsideExecution: true, upgradeable: false }); testEthAccount('basic ethAccount, upgradeable', { declare: false, deploy: false, - pubkey: false + pubkey: false, + outsideExecution: false, }); testEthAccount('basic ethAccount, non-upgradeable', { declare: false, deploy: false, pubkey: false, + outsideExecution: false, upgradeable: false }); +testEthAccount('ethAccount outside execution', { + deploy: false, + pubkey: false, + declare: false, +}); + testEthAccount('ethAccount declarer', { deploy: false, - pubkey: false + pubkey: false, + outsideExecution: false, }); testEthAccount('ethAccount deployable', { declare: false, - pubkey: false + pubkey: false, + outsideExecution: false, }); testEthAccount('ethAccount public key', { declare: false, deploy: false, + outsideExecution: false, }); testEthAccount('ethAccount declarer, deployable', { - pubkey: false + pubkey: false, + outsideExecution: false, }); testEthAccount('ethAccount declarer, public key', { - deploy: false + deploy: false, + outsideExecution: false, }); testEthAccount('ethAccount deployable, public key', { - declare: false + declare: false, + outsideExecution: false, }); testAPIEquivalence('account API default'); @@ -179,6 +212,7 @@ testAPIEquivalence('account API basic', { declare: false, deploy: false, pubkey: false, + outsideExecution: false, upgradeable: false, }); @@ -188,6 +222,7 @@ testAPIEquivalence('account API full upgradeable', { declare: true, deploy: true, pubkey: true, + outsideExecution: true, upgradeable: true, }); diff --git a/packages/core-cairo/src/account.test.ts.md b/packages/core-cairo/src/account.test.ts.md index 3896b7e2..a62ea81f 100644 --- a/packages/core-cairo/src/account.test.ts.md +++ b/packages/core-cairo/src/account.test.ts.md @@ -14,6 +14,7 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::AccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ @@ -21,14 +22,18 @@ Generated by [AVA](https://avajs.dev). ␊ component!(path: AccountComponent, storage: account, event: AccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl AccountMixinImpl = AccountComponent::AccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl AccountInternalImpl = AccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ @@ -38,6 +43,8 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ + #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ @@ -49,12 +56,15 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ + SRC9Event: SRC9Component::Event,␊ + #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: felt252) {␊ self.account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ ␊ //␊ @@ -81,17 +91,22 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::AccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::introspection::src5::SRC5Component;␊ ␊ component!(path: AccountComponent, storage: account, event: AccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl AccountMixinImpl = AccountComponent::AccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl AccountInternalImpl = AccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -99,6 +114,8 @@ Generated by [AVA](https://avajs.dev). account: AccountComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ }␊ ␊ #[event]␊ @@ -108,11 +125,14 @@ Generated by [AVA](https://avajs.dev). AccountEvent: AccountComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + SRC9Event: SRC9Component::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: felt252) {␊ self.account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ }␊ ` @@ -127,6 +147,7 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::AccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ @@ -134,14 +155,18 @@ Generated by [AVA](https://avajs.dev). ␊ component!(path: AccountComponent, storage: account, event: AccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl AccountMixinImpl = AccountComponent::AccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl AccountInternalImpl = AccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ @@ -151,6 +176,8 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ + #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ @@ -162,12 +189,15 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ + SRC9Event: SRC9Component::Event,␊ + #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: felt252) {␊ self.account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ ␊ //␊ @@ -194,17 +224,22 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::AccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::introspection::src5::SRC5Component;␊ ␊ component!(path: AccountComponent, storage: account, event: AccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl AccountMixinImpl = AccountComponent::AccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl AccountInternalImpl = AccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -212,6 +247,8 @@ Generated by [AVA](https://avajs.dev). account: AccountComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ }␊ ␊ #[event]␊ @@ -221,11 +258,14 @@ Generated by [AVA](https://avajs.dev). AccountEvent: AccountComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + SRC9Event: SRC9Component::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: felt252) {␊ self.account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ }␊ ` @@ -351,6 +391,87 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## account outside execution + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.20.0␊ + ␊ + #[starknet::contract(account)]␊ + mod MyAccount {␊ + use openzeppelin::account::AccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::upgrades::interface::IUpgradeable;␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::ClassHash;␊ + ␊ + component!(path: AccountComponent, storage: account, event: AccountEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl SRC6Impl = AccountComponent::SRC6Impl;␊ + #[abi(embed_v0)]␊ + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl;␊ + #[abi(embed_v0)]␊ + impl SRC5Impl = SRC5Component::SRC5Impl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ + ␊ + // Internal␊ + impl AccountInternalImpl = AccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + account: AccountComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + AccountEvent: AccountComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + SRC9Event: SRC9Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(ref self: ContractState, public_key: felt252) {␊ + self.account.initializer(public_key);␊ + self.src9.initializer();␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.account.assert_only_self();␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + ## account declarer > Snapshot 1 @@ -811,6 +932,7 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::eth_account::EthAccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::account::interface::EthPublicKey;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ @@ -819,14 +941,18 @@ Generated by [AVA](https://avajs.dev). ␊ component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl EthAccountMixinImpl = EthAccountComponent::EthAccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl EthAccountInternalImpl = EthAccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ @@ -836,6 +962,8 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ + #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ @@ -847,12 +975,15 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ + SRC9Event: SRC9Component::Event,␊ + #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: EthPublicKey) {␊ self.eth_account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ ␊ //␊ @@ -879,18 +1010,23 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::eth_account::EthAccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::account::interface::EthPublicKey;␊ use openzeppelin::introspection::src5::SRC5Component;␊ ␊ component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl EthAccountMixinImpl = EthAccountComponent::EthAccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl EthAccountInternalImpl = EthAccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -898,6 +1034,8 @@ Generated by [AVA](https://avajs.dev). eth_account: EthAccountComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ }␊ ␊ #[event]␊ @@ -907,11 +1045,14 @@ Generated by [AVA](https://avajs.dev). EthAccountEvent: EthAccountComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + SRC9Event: SRC9Component::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: EthPublicKey) {␊ self.eth_account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ }␊ ` @@ -926,6 +1067,7 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::eth_account::EthAccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::account::interface::EthPublicKey;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ @@ -934,14 +1076,18 @@ Generated by [AVA](https://avajs.dev). ␊ component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl EthAccountMixinImpl = EthAccountComponent::EthAccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl EthAccountInternalImpl = EthAccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ ␊ #[storage]␊ @@ -951,6 +1097,8 @@ Generated by [AVA](https://avajs.dev). #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ + #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ @@ -962,12 +1110,15 @@ Generated by [AVA](https://avajs.dev). #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ + SRC9Event: SRC9Component::Event,␊ + #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: EthPublicKey) {␊ self.eth_account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ ␊ //␊ @@ -994,18 +1145,23 @@ Generated by [AVA](https://avajs.dev). #[starknet::contract(account)]␊ mod MyAccount {␊ use openzeppelin::account::eth_account::EthAccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ use openzeppelin::account::interface::EthPublicKey;␊ use openzeppelin::introspection::src5::SRC5Component;␊ ␊ component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl EthAccountMixinImpl = EthAccountComponent::EthAccountMixinImpl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ ␊ // Internal␊ impl EthAccountInternalImpl = EthAccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ ␊ #[storage]␊ struct Storage {␊ @@ -1013,6 +1169,8 @@ Generated by [AVA](https://avajs.dev). eth_account: EthAccountComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ }␊ ␊ #[event]␊ @@ -1022,11 +1180,14 @@ Generated by [AVA](https://avajs.dev). EthAccountEvent: EthAccountComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + SRC9Event: SRC9Component::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, public_key: EthPublicKey) {␊ self.eth_account.initializer(public_key);␊ + self.src9.initializer();␊ }␊ }␊ ` @@ -1154,6 +1315,88 @@ Generated by [AVA](https://avajs.dev). }␊ ` +## ethAccount outside execution + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.20.0␊ + ␊ + #[starknet::contract(account)]␊ + mod MyAccount {␊ + use openzeppelin::account::eth_account::EthAccountComponent;␊ + use openzeppelin::account::extensions::SRC9Component;␊ + use openzeppelin::account::interface::EthPublicKey;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + use openzeppelin::upgrades::interface::IUpgradeable;␊ + use openzeppelin::upgrades::UpgradeableComponent;␊ + use starknet::ClassHash;␊ + ␊ + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + component!(path: SRC9Component, storage: src9, event: SRC9Event);␊ + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ + ␊ + // External␊ + #[abi(embed_v0)]␊ + impl SRC6Impl = EthAccountComponent::SRC6Impl;␊ + #[abi(embed_v0)]␊ + impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl;␊ + #[abi(embed_v0)]␊ + impl SRC5Impl = SRC5Component::SRC5Impl;␊ + #[abi(embed_v0)]␊ + impl OutsideExecutionV2Impl = SRC9Component::OutsideExecutionV2Impl;␊ + ␊ + // Internal␊ + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl;␊ + impl OutsideExecutionInternalImpl = SRC9Component::InternalImpl;␊ + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + eth_account: EthAccountComponent::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + #[substorage(v0)]␊ + src9: SRC9Component::Storage,␊ + #[substorage(v0)]␊ + upgradeable: UpgradeableComponent::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + EthAccountEvent: EthAccountComponent::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + #[flat]␊ + SRC9Event: SRC9Component::Event,␊ + #[flat]␊ + UpgradeableEvent: UpgradeableComponent::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(ref self: ContractState, public_key: EthPublicKey) {␊ + self.eth_account.initializer(public_key);␊ + self.src9.initializer();␊ + }␊ + ␊ + //␊ + // Upgradeable␊ + //␊ + ␊ + #[abi(embed_v0)]␊ + impl UpgradeableImpl of IUpgradeable {␊ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ + self.eth_account.assert_only_self();␊ + self.upgradeable.upgrade(new_class_hash);␊ + }␊ + }␊ + }␊ + ` + ## ethAccount declarer > Snapshot 1 diff --git a/packages/core-cairo/src/account.test.ts.snap b/packages/core-cairo/src/account.test.ts.snap index a013fa64..f3ee3b89 100644 Binary files a/packages/core-cairo/src/account.test.ts.snap and b/packages/core-cairo/src/account.test.ts.snap differ diff --git a/packages/core-cairo/src/account.ts b/packages/core-cairo/src/account.ts index bfbeaca2..68914729 100644 --- a/packages/core-cairo/src/account.ts +++ b/packages/core-cairo/src/account.ts @@ -17,6 +17,7 @@ export const defaults: Required = { declare: true, deploy: true, pubkey: true, + outsideExecution: true, upgradeable: commonDefaults.upgradeable, info: commonDefaults.info } as const; @@ -31,6 +32,7 @@ export interface AccountOptions extends CommonOptions { declare?: boolean; deploy?: boolean; pubkey?: boolean; + outsideExecution?: boolean; } function withDefaults(opts: AccountOptions): Required { @@ -39,7 +41,8 @@ function withDefaults(opts: AccountOptions): Required { ...withCommonDefaults(opts), declare: opts.declare ?? defaults.declare, deploy: opts.deploy ?? defaults.deploy, - pubkey: opts.pubkey ?? defaults.pubkey + pubkey: opts.pubkey ?? defaults.pubkey, + outsideExecution: opts.outsideExecution ?? defaults.outsideExecution } } @@ -79,6 +82,10 @@ export function buildAccount(opts: AccountOptions): Contract { } } + if (allOpts.outsideExecution) { + addOutsideExecution(c); + } + setAccountUpgradeable(c, allOpts.upgradeable, allOpts.type); setInfo(c, allOpts.info); @@ -131,6 +138,11 @@ function addPublicKey(c: ContractBuilder, accountType: Account) { }); } +function addOutsideExecution(c: ContractBuilder) { + c.addUseClause('openzeppelin::account::extensions', 'SRC9Component'); + c.addComponent(components.SRC9Component, [], true); +} + function addAccountMixin(c: ContractBuilder, accountType: Account) { const accountMixinImpl = accountType === 'stark' ? 'AccountMixinImpl' : 'EthAccountMixinImpl'; const [baseComponent, componentType] = getBaseCompAndCompType(accountType); @@ -182,4 +194,23 @@ const components = defineComponents( { value: 'EthAccountComponent::InternalImpl', }] }, + SRC9Component: { + path: 'openzeppelin::account::extensions', + substorage: { + name: 'src9', + type: 'SRC9Component::Storage', + }, + event: { + name: 'SRC9Event', + type: 'SRC9Component::Event', + }, + impls: [{ + name: 'OutsideExecutionV2Impl', + value: 'SRC9Component::OutsideExecutionV2Impl', + }, { + name: 'OutsideExecutionInternalImpl', + embed: false, + value: 'SRC9Component::InternalImpl', + }] + } }); diff --git a/packages/core-cairo/src/generate/account.ts b/packages/core-cairo/src/generate/account.ts index aeca5c76..175ba8df 100644 --- a/packages/core-cairo/src/generate/account.ts +++ b/packages/core-cairo/src/generate/account.ts @@ -11,6 +11,7 @@ const blueprint = { declare: booleans, deploy: booleans, pubkey: booleans, + outsideExecution: booleans, upgradeable: upgradeableOptions, info: infoOptions, }; diff --git a/packages/ui/src/cairo/AccountControls.svelte b/packages/ui/src/cairo/AccountControls.svelte index faf3d829..c5aaa7db 100644 --- a/packages/ui/src/cairo/AccountControls.svelte +++ b/packages/ui/src/cairo/AccountControls.svelte @@ -51,6 +51,14 @@

Features

+ +