diff --git a/packages/core-cairo/CHANGELOG.md b/packages/core-cairo/CHANGELOG.md index 78d1614cb..19f093ab2 100644 --- a/packages/core-cairo/CHANGELOG.md +++ b/packages/core-cairo/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.13.0 (2024-05-22) + +- **Breaking changes**: + - Use OpenZeppelin Contracts for Cairo v0.13.0. ([#359](https://github.com/OpenZeppelin/contracts-wizard/pull/359)) + - Use Hooks with ERC721 and ERC1155. + - Use Hooks for Pausable. + ## 0.12.0 (2024-05-01) - Add `votes` option to ERC20. ([#355](https://github.com/OpenZeppelin/contracts-wizard/pull/355)) diff --git a/packages/core-cairo/package.json b/packages/core-cairo/package.json index c692fae64..c650a2102 100644 --- a/packages/core-cairo/package.json +++ b/packages/core-cairo/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/wizard-cairo", - "version": "0.12.0", + "version": "0.13.0", "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/add-pausable.ts b/packages/core-cairo/src/add-pausable.ts index e6f1e0f2a..7dec045f6 100644 --- a/packages/core-cairo/src/add-pausable.ts +++ b/packages/core-cairo/src/add-pausable.ts @@ -1,5 +1,5 @@ import { getSelfArg } from './common-options'; -import type { BaseImplementedTrait, ContractBuilder, ContractFunction } from './contract'; +import type { ContractBuilder } from './contract'; import { Access, requireAccessControl } from './set-access-control'; import { defineFunctions } from './utils/define-functions'; import { defineComponents } from './utils/define-components'; @@ -57,6 +57,3 @@ const functions = defineFunctions({ }, }); -export function setPausable(c: ContractBuilder, t: BaseImplementedTrait, fn: ContractFunction) { - c.addFunctionCodeBefore(t, fn, 'self.pausable.assert_not_paused()'); -} diff --git a/packages/core-cairo/src/contract.test.ts.md b/packages/core-cairo/src/contract.test.ts.md index 93aac45a4..30ca51d4f 100644 --- a/packages/core-cairo/src/contract.test.ts.md +++ b/packages/core-cairo/src/contract.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -24,7 +24,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -44,7 +44,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -64,7 +64,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -89,7 +89,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -114,7 +114,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -152,7 +152,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ diff --git a/packages/core-cairo/src/contract.test.ts.snap b/packages/core-cairo/src/contract.test.ts.snap index bf56c387b..0201cf73f 100644 Binary files a/packages/core-cairo/src/contract.test.ts.snap and b/packages/core-cairo/src/contract.test.ts.snap differ diff --git a/packages/core-cairo/src/custom.test.ts.md b/packages/core-cairo/src/custom.test.ts.md index a1aac28e1..c391f504c 100644 --- a/packages/core-cairo/src/custom.test.ts.md +++ b/packages/core-cairo/src/custom.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -24,7 +24,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -80,7 +80,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -161,7 +161,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -217,7 +217,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -232,7 +232,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -288,7 +288,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ ␊ @@ -361,7 +361,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ diff --git a/packages/core-cairo/src/custom.test.ts.snap b/packages/core-cairo/src/custom.test.ts.snap index 875f971fb..5da6f9977 100644 Binary files a/packages/core-cairo/src/custom.test.ts.snap and b/packages/core-cairo/src/custom.test.ts.snap differ diff --git a/packages/core-cairo/src/erc1155.test.ts.md b/packages/core-cairo/src/erc1155.test.ts.md index 1609e0485..341e6a263 100644 --- a/packages/core-cairo/src/erc1155.test.ts.md +++ b/packages/core-cairo/src/erc1155.test.ts.md @@ -9,13 +9,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use starknet::ContractAddress;␊ ␊ component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);␊ @@ -79,13 +80,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -166,7 +168,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ @@ -177,6 +179,7 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -269,13 +272,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -341,13 +345,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -462,7 +467,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -470,7 +475,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ - use openzeppelin::token::erc1155::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -483,9 +487,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC1155MetadataURIImpl = ERC1155Component::ERC1155MetadataURIImpl;␊ - #[abi(embed_v0)]␊ - impl SRC5Impl = SRC5Component::SRC5Impl;␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -531,88 +533,25 @@ Generated by [AVA](https://avajs.dev). self.ownable.initializer(owner);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC1155CamelImpl of interface::IERC1155Camel {␊ - fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 {␊ - self.balance_of(account, tokenId)␊ - }␊ - ␊ - fn balanceOfBatch(self: @ContractState, accounts: Span, tokenIds: Span) -> Span {␊ - self.balance_of_batch(accounts, tokenIds)␊ - }␊ - ␊ - fn safeTransferFrom(␊ - ref self: ContractState,␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ from: ContractAddress,␊ to: ContractAddress,␊ - tokenId: u256,␊ - value: u256,␊ - data: Span,␊ - ) {␊ - self.safe_transfer_from(from, to, tokenId, value, data);␊ - }␊ - ␊ - fn safeBatchTransferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenIds: Span,␊ + token_ids: Span,␊ values: Span,␊ - data: Span,␊ - ) {␊ - self.safe_batch_transfer_from(from, to, tokenIds, values, data);␊ - }␊ - ␊ - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.is_approved_for_all(owner, operator)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC1155Impl of interface::IERC1155 {␊ - fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 {␊ - self.erc1155.balance_of(account, token_id)␊ - }␊ - ␊ - fn balance_of_batch(self: @ContractState, accounts: Span, token_ids: Span) -> Span {␊ - self.erc1155.balance_of_batch(accounts, token_ids)␊ - }␊ - ␊ - fn safe_transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - token_id: u256,␊ - value: u256,␊ - data: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.safe_transfer_from(from, to, token_id, value, data);␊ + let contract_state = ERC1155Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn safe_batch_transfer_from(␊ - ref self: ContractState,␊ + fn after_update(␊ + ref self: ERC1155Component::ComponentState,␊ from: ContractAddress,␊ to: ContractAddress,␊ token_ids: Span,␊ values: Span,␊ - data: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.safe_batch_transfer_from(from, to, token_ids, values, data);␊ - }␊ - ␊ - fn set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.erc1155.is_approved_for_all(owner, operator)␊ }␊ }␊ ␊ @@ -658,13 +597,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -780,7 +720,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ const URI_SETTER_ROLE: felt252 = selector!("URI_SETTER_ROLE");␊ @@ -792,6 +732,7 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ + use openzeppelin::token::erc1155::ERC1155HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -921,7 +862,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ @@ -934,7 +875,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ - use openzeppelin::token::erc1155::interface;␊ use starknet::ContractAddress;␊ use starknet::get_caller_address;␊ use super::{PAUSER_ROLE, MINTER_ROLE, URI_SETTER_ROLE};␊ @@ -945,9 +885,7 @@ Generated by [AVA](https://avajs.dev). component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC1155MetadataURIImpl = ERC1155Component::ERC1155MetadataURIImpl;␊ - #[abi(embed_v0)]␊ - impl SRC5Impl = SRC5Component::SRC5Impl;␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -1001,88 +939,25 @@ Generated by [AVA](https://avajs.dev). self.accesscontrol._grant_role(URI_SETTER_ROLE, uri_setter);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC1155CamelImpl of interface::IERC1155Camel {␊ - fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 {␊ - self.balance_of(account, tokenId)␊ - }␊ - ␊ - fn balanceOfBatch(self: @ContractState, accounts: Span, tokenIds: Span) -> Span {␊ - self.balance_of_batch(accounts, tokenIds)␊ - }␊ - ␊ - fn safeTransferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - value: u256,␊ - data: Span,␊ - ) {␊ - self.safe_transfer_from(from, to, tokenId, value, data);␊ - }␊ - ␊ - fn safeBatchTransferFrom(␊ - ref self: ContractState,␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ from: ContractAddress,␊ to: ContractAddress,␊ - tokenIds: Span,␊ + token_ids: Span,␊ values: Span,␊ - data: Span,␊ - ) {␊ - self.safe_batch_transfer_from(from, to, tokenIds, values, data);␊ - }␊ - ␊ - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.is_approved_for_all(owner, operator)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC1155Impl of interface::IERC1155 {␊ - fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 {␊ - self.erc1155.balance_of(account, token_id)␊ - }␊ - ␊ - fn balance_of_batch(self: @ContractState, accounts: Span, token_ids: Span) -> Span {␊ - self.erc1155.balance_of_batch(accounts, token_ids)␊ - }␊ - ␊ - fn safe_transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - token_id: u256,␊ - value: u256,␊ - data: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.safe_transfer_from(from, to, token_id, value, data);␊ + let contract_state = ERC1155Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn safe_batch_transfer_from(␊ - ref self: ContractState,␊ + fn after_update(␊ + ref self: ERC1155Component::ComponentState,␊ from: ContractAddress,␊ to: ContractAddress,␊ token_ids: Span,␊ values: Span,␊ - data: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.safe_batch_transfer_from(from, to, token_ids, values, data);␊ - }␊ - ␊ - fn set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.erc1155.is_approved_for_all(owner, operator)␊ }␊ }␊ ␊ @@ -1103,7 +978,6 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, account: ContractAddress, token_id: u256, value: u256) {␊ - self.pausable.assert_not_paused();␊ let caller = get_caller_address();␊ if account != caller {␊ assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ @@ -1118,7 +992,6 @@ Generated by [AVA](https://avajs.dev). token_ids: Span,␊ values: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ let caller = get_caller_address();␊ if account != caller {␊ assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ @@ -1145,7 +1018,6 @@ Generated by [AVA](https://avajs.dev). data: Span,␊ ) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ - self.pausable.assert_not_paused();␊ self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ }␊ ␊ @@ -1158,7 +1030,6 @@ Generated by [AVA](https://avajs.dev). data: Span,␊ ) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ - self.pausable.assert_not_paused();␊ self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ }␊ ␊ @@ -1192,7 +1063,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ @@ -1206,7 +1077,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc1155::ERC1155Component;␊ - use openzeppelin::token::erc1155::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -1221,9 +1091,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC1155MetadataURIImpl = ERC1155Component::ERC1155MetadataURIImpl;␊ - #[abi(embed_v0)]␊ - impl SRC5Impl = SRC5Component::SRC5Impl;␊ + impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -1284,88 +1152,25 @@ Generated by [AVA](https://avajs.dev). self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC1155CamelImpl of interface::IERC1155Camel {␊ - fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 {␊ - self.balance_of(account, tokenId)␊ - }␊ - ␊ - fn balanceOfBatch(self: @ContractState, accounts: Span, tokenIds: Span) -> Span {␊ - self.balance_of_batch(accounts, tokenIds)␊ - }␊ - ␊ - fn safeTransferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - value: u256,␊ - data: Span,␊ - ) {␊ - self.safe_transfer_from(from, to, tokenId, value, data);␊ - }␊ - ␊ - fn safeBatchTransferFrom(␊ - ref self: ContractState,␊ + impl ERC1155HooksImpl of ERC1155Component::ERC1155HooksTrait {␊ + fn before_update(␊ + ref self: ERC1155Component::ComponentState,␊ from: ContractAddress,␊ to: ContractAddress,␊ - tokenIds: Span,␊ + token_ids: Span,␊ values: Span,␊ - data: Span,␊ ) {␊ - self.safe_batch_transfer_from(from, to, tokenIds, values, data);␊ + let contract_state = ERC1155Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.is_approved_for_all(owner, operator)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC1155Impl of interface::IERC1155 {␊ - fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 {␊ - self.erc1155.balance_of(account, token_id)␊ - }␊ - ␊ - fn balance_of_batch(self: @ContractState, accounts: Span, token_ids: Span) -> Span {␊ - self.erc1155.balance_of_batch(accounts, token_ids)␊ - }␊ - ␊ - fn safe_transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - token_id: u256,␊ - value: u256,␊ - data: Span,␊ - ) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.safe_transfer_from(from, to, token_id, value, data);␊ - }␊ - ␊ - fn safe_batch_transfer_from(␊ - ref self: ContractState,␊ + fn after_update(␊ + ref self: ERC1155Component::ComponentState,␊ from: ContractAddress,␊ to: ContractAddress,␊ token_ids: Span,␊ values: Span,␊ - data: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.safe_batch_transfer_from(from, to, token_ids, values, data);␊ - }␊ - ␊ - fn set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.pausable.assert_not_paused();␊ - self.erc1155.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.erc1155.is_approved_for_all(owner, operator)␊ }␊ }␊ ␊ @@ -1394,7 +1199,6 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, account: ContractAddress, token_id: u256, value: u256) {␊ - self.pausable.assert_not_paused();␊ let caller = get_caller_address();␊ if account != caller {␊ assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ @@ -1409,7 +1213,6 @@ Generated by [AVA](https://avajs.dev). token_ids: Span,␊ values: Span,␊ ) {␊ - self.pausable.assert_not_paused();␊ let caller = get_caller_address();␊ if account != caller {␊ assert(self.erc1155.is_approved_for_all(account, caller), ERC1155Component::Errors::UNAUTHORIZED);␊ @@ -1436,7 +1239,6 @@ Generated by [AVA](https://avajs.dev). data: Span,␊ ) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ - self.pausable.assert_not_paused();␊ self.erc1155.mint_with_acceptance_check(account, token_id, value, data);␊ }␊ ␊ @@ -1449,7 +1251,6 @@ Generated by [AVA](https://avajs.dev). data: Span,␊ ) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ - self.pausable.assert_not_paused();␊ self.erc1155.batch_mint_with_acceptance_check(account, token_ids, values, data);␊ }␊ ␊ diff --git a/packages/core-cairo/src/erc1155.test.ts.snap b/packages/core-cairo/src/erc1155.test.ts.snap index a0e814c05..3df4d9cd0 100644 Binary files a/packages/core-cairo/src/erc1155.test.ts.snap and b/packages/core-cairo/src/erc1155.test.ts.snap differ diff --git a/packages/core-cairo/src/erc1155.ts b/packages/core-cairo/src/erc1155.ts index 78595c700..529f4a35e 100644 --- a/packages/core-cairo/src/erc1155.ts +++ b/packages/core-cairo/src/erc1155.ts @@ -1,6 +1,6 @@ import { BaseImplementedTrait, Contract, ContractBuilder } from './contract'; import { Access, requireAccessControl, setAccessControl } from './set-access-control'; -import { addPausable, setPausable } from './add-pausable'; +import { addPausable } from './add-pausable'; import { defineFunctions } from './utils/define-functions'; import { CommonOptions, withCommonDefaults, getSelfArg } from './common-options'; import { setUpgradeable } from './set-upgradeable'; @@ -58,27 +58,21 @@ export function buildERC1155(opts: ERC1155Options): Contract { const allOpts = withDefaults(opts); addBase(c, toByteArray(allOpts.baseUri)); - addERC1155MixinOrImpls(c, allOpts.pausable); - addSRC5Component(c); + addERC1155Mixin(c); if (allOpts.pausable) { addPausable(c, allOpts.access); + addPausableHook(c); + } else { + c.addStandaloneImport('openzeppelin::token::erc1155::ERC1155HooksEmptyImpl'); } if (allOpts.burnable) { addBurnable(c); - if (allOpts.pausable) { - setPausable(c, externalTrait, functions.burn); - setPausable(c, externalTrait, functions.batch_burn); - } } if (allOpts.mintable) { addMintable(c, allOpts.access); - if (allOpts.pausable) { - setPausable(c, externalTrait, functions.mint); - setPausable(c, externalTrait, functions.batch_mint); - } } if (allOpts.updatableUri) { @@ -92,54 +86,52 @@ export function buildERC1155(opts: ERC1155Options): Contract { return c; } -function addERC1155Interface(c: ContractBuilder) { - c.addStandaloneImport('openzeppelin::token::erc1155::interface'); -} +function addPausableHook(c: ContractBuilder) { + const ERC1155HooksTrait: BaseImplementedTrait = { + name: `ERC1155HooksImpl`, + of: 'ERC1155Component::ERC1155HooksTrait', + tags: [], + priority: 0, + }; + c.addImplementedTrait(ERC1155HooksTrait); -function addERC1155MixinOrImpls(c: ContractBuilder, pausable: boolean) { - if (pausable) { - addERC1155Interface(c); + c.addStandaloneImport('starknet::ContractAddress'); - c.addImplToComponent(components.ERC1155Component, { - name: 'ERC1155MetadataURIImpl', - value: 'ERC1155Component::ERC1155MetadataURIImpl', - }); + c.addFunction(ERC1155HooksTrait, { + name: 'before_update', + args: [ + { name: 'ref self', type: `ERC1155Component::ComponentState` }, + { name: 'from', type: 'ContractAddress' }, + { name: 'to', type: 'ContractAddress' }, + { name: 'token_ids', type: 'Span' }, + { name: 'values', type: 'Span' }, + ], + code: [ + 'let contract_state = ERC1155Component::HasComponent::get_contract(@self)', + 'contract_state.pausable.assert_not_paused()', + ], + }); - const ERC1155Impl: BaseImplementedTrait = { - name: 'ERC1155Impl', - of: 'interface::IERC1155', - tags: [ - 'abi(embed_v0)' - ], - } - c.addFunction(ERC1155Impl, functions.balance_of); - c.addFunction(ERC1155Impl, functions.balance_of_batch); - setPausable(c, ERC1155Impl, functions.safe_transfer_from); - setPausable(c, ERC1155Impl, functions.safe_batch_transfer_from); - setPausable(c, ERC1155Impl, functions.set_approval_for_all); - c.addFunction(ERC1155Impl, functions.is_approved_for_all); + c.addFunction(ERC1155HooksTrait, { + name: 'after_update', + args: [ + { name: 'ref self', type: `ERC1155Component::ComponentState` }, + { name: 'from', type: 'ContractAddress' }, + { name: 'to', type: 'ContractAddress' }, + { name: 'token_ids', type: 'Span' }, + { name: 'values', type: 'Span' }, + ], + code: [], + }); +} - const ERC1155CamelImpl: BaseImplementedTrait = { - name: 'ERC1155CamelImpl', - of: 'interface::IERC1155Camel', - tags: [ - 'abi(embed_v0)' - ], - } - // Camel case versions of the functions above. Pausable is already set above. - c.addFunction(ERC1155CamelImpl, functions.balanceOf); - c.addFunction(ERC1155CamelImpl, functions.balanceOfBatch); - c.addFunction(ERC1155CamelImpl, functions.safeTransferFrom); - c.addFunction(ERC1155CamelImpl, functions.safeBatchTransferFrom); - c.addFunction(ERC1155CamelImpl, functions.setApprovalForAll); - c.addFunction(ERC1155CamelImpl, functions.isApprovedForAll); - } else { - c.addImplToComponent(components.ERC1155Component, { - name: 'ERC1155MixinImpl', - value: 'ERC1155Component::ERC1155MixinImpl', - }); - c.addInterfaceFlag('ISRC5'); - } +function addERC1155Mixin(c: ContractBuilder) { + c.addImplToComponent(components.ERC1155Component, { + name: 'ERC1155MixinImpl', + value: 'ERC1155Component::ERC1155MixinImpl', + }); + c.addInterfaceFlag('ISRC5'); + addSRC5Component(c); } function addBase(c: ContractBuilder, baseUri: string) { @@ -290,147 +282,4 @@ const functions = defineFunctions({ 'self.set_base_uri(baseUri);' ] }, - - // Re-implements ERC1155Impl - balance_of: { - args: [ - getSelfArg('view'), - { name: 'account', type: 'ContractAddress' }, - { name: 'token_id', type: 'u256' }, - ], - returns: 'u256', - code: [ - 'self.erc1155.balance_of(account, token_id)' - ] - }, - balance_of_batch: { - args: [ - getSelfArg('view'), - { name: 'accounts', type: 'Span' }, - { name: 'token_ids', type: 'Span' }, - ], - returns: 'Span', - code: [ - 'self.erc1155.balance_of_batch(accounts, token_ids)' - ] - }, - safe_transfer_from: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'token_id', type: 'u256' }, - { name: 'value', type: 'u256' }, - { name: 'data', type: 'Span' }, - ], - code: [ - 'self.erc1155.safe_transfer_from(from, to, token_id, value, data)' - ] - }, - safe_batch_transfer_from: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'token_ids', type: 'Span' }, - { name: 'values', type: 'Span' }, - { name: 'data', type: 'Span' }, - ], - code: [ - 'self.erc1155.safe_batch_transfer_from(from, to, token_ids, values, data)' - ] - }, - set_approval_for_all: { - args: [ - getSelfArg(), - { name: 'operator', type: 'ContractAddress' }, - { name: 'approved', type: 'bool' }, - ], - code: [ - 'self.erc1155.set_approval_for_all(operator, approved)' - ] - }, - is_approved_for_all: { - args: [ - getSelfArg('view'), - { name: 'owner', type: 'ContractAddress' }, - { name: 'operator', type: 'ContractAddress' }, - ], - returns: 'bool', - code: [ - 'self.erc1155.is_approved_for_all(owner, operator)' - ] - }, - - // Re-implements ERC1155CamelImpl - - balanceOf: { - args: [ - getSelfArg('view'), - { name: 'account', type: 'ContractAddress' }, - { name: 'tokenId', type: 'u256' }, - ], - returns: 'u256', - code: [ - 'self.balance_of(account, tokenId)' - ] - }, - balanceOfBatch: { - args: [ - getSelfArg('view'), - { name: 'accounts', type: 'Span' }, - { name: 'tokenIds', type: 'Span' }, - ], - returns: 'Span', - code: [ - 'self.balance_of_batch(accounts, tokenIds)' - ] - }, - safeTransferFrom: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'tokenId', type: 'u256' }, - { name: 'value', type: 'u256' }, - { name: 'data', type: 'Span' }, - ], - code: [ - 'self.safe_transfer_from(from, to, tokenId, value, data)' - ] - }, - safeBatchTransferFrom: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'tokenIds', type: 'Span' }, - { name: 'values', type: 'Span' }, - { name: 'data', type: 'Span' }, - ], - code: [ - 'self.safe_batch_transfer_from(from, to, tokenIds, values, data)' - ] - }, - setApprovalForAll: { - args: [ - getSelfArg(), - { name: 'operator', type: 'ContractAddress' }, - { name: 'approved', type: 'bool' }, - ], - code: [ - 'self.set_approval_for_all(operator, approved)' - ] - }, - isApprovedForAll: { - args: [ - getSelfArg('view'), - { name: 'owner', type: 'ContractAddress' }, - { name: 'operator', type: 'ContractAddress' }, - ], - returns: 'bool', - code: [ - 'self.is_approved_for_all(owner, operator)' - ] - }, }); diff --git a/packages/core-cairo/src/erc20.test.ts.md b/packages/core-cairo/src/erc20.test.ts.md index 64e17789a..cf5fb11ff 100644 --- a/packages/core-cairo/src/erc20.test.ts.md +++ b/packages/core-cairo/src/erc20.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -48,7 +48,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -115,7 +115,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -181,8 +181,7 @@ Generated by [AVA](https://avajs.dev). impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ - let caller = get_caller_address();␊ - self.erc20._burn(caller, value);␊ + self.erc20._burn(get_caller_address(), value);␊ }␊ }␊ }␊ @@ -193,15 +192,13 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::ERC20Component;␊ - use openzeppelin::token::erc20::ERC20HooksEmptyImpl;␊ - use openzeppelin::token::erc20::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -213,7 +210,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl;␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -255,58 +252,23 @@ Generated by [AVA](https://avajs.dev). self.ownable.initializer(owner);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC20CamelOnlyImpl of interface::IERC20CamelOnly {␊ - fn totalSupply(self: @ContractState) -> u256 {␊ - self.total_supply()␊ - }␊ - ␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ - ) -> bool {␊ - self.transfer_from(sender, recipient, amount)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20Impl of interface::IERC20 {␊ - fn total_supply(self: @ContractState) -> u256 {␊ - self.erc20.total_supply()␊ - }␊ - ␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc20.balance_of(account)␊ - }␊ - ␊ - fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress) -> u256 {␊ - self.erc20.allowance(owner, spender)␊ - }␊ - ␊ - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer(recipient, amount)␊ + ) {␊ + let contract_state = ERC20Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ + fn after_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ - ) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer_from(sender, recipient, amount)␊ - }␊ - ␊ - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.approve(spender, amount)␊ + ) {␊ }␊ }␊ ␊ @@ -341,7 +303,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ @@ -353,8 +315,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::ERC20Component;␊ - use openzeppelin::token::erc20::ERC20HooksEmptyImpl;␊ - use openzeppelin::token::erc20::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -368,7 +328,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl;␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -423,58 +383,23 @@ Generated by [AVA](https://avajs.dev). self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC20CamelOnlyImpl of interface::IERC20CamelOnly {␊ - fn totalSupply(self: @ContractState) -> u256 {␊ - self.total_supply()␊ - }␊ - ␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ - ) -> bool {␊ - self.transfer_from(sender, recipient, amount)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20Impl of interface::IERC20 {␊ - fn total_supply(self: @ContractState) -> u256 {␊ - self.erc20.total_supply()␊ - }␊ - ␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc20.balance_of(account)␊ - }␊ - ␊ - fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress) -> u256 {␊ - self.erc20.allowance(owner, spender)␊ - }␊ - ␊ - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer(recipient, amount)␊ + ) {␊ + let contract_state = ERC20Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ + fn after_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ - ) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer_from(sender, recipient, amount)␊ - }␊ - ␊ - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.approve(spender, amount)␊ + ) {␊ }␊ }␊ ␊ @@ -509,15 +434,13 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::ERC20Component;␊ - use openzeppelin::token::erc20::ERC20HooksEmptyImpl;␊ - use openzeppelin::token::erc20::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -530,7 +453,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl;␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -572,58 +495,23 @@ Generated by [AVA](https://avajs.dev). self.ownable.initializer(owner);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC20CamelOnlyImpl of interface::IERC20CamelOnly {␊ - fn totalSupply(self: @ContractState) -> u256 {␊ - self.total_supply()␊ - }␊ - ␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ + fn before_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ - ) -> bool {␊ - self.transfer_from(sender, recipient, amount)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20Impl of interface::IERC20 {␊ - fn total_supply(self: @ContractState) -> u256 {␊ - self.erc20.total_supply()␊ - }␊ - ␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc20.balance_of(account)␊ - }␊ - ␊ - fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress) -> u256 {␊ - self.erc20.allowance(owner, spender)␊ - }␊ - ␊ - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer(recipient, amount)␊ + ) {␊ + let contract_state = ERC20Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ + fn after_update(␊ + ref self: ERC20Component::ComponentState,␊ + from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ - ) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer_from(sender, recipient, amount)␊ - }␊ - ␊ - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.approve(spender, amount)␊ + ) {␊ }␊ }␊ ␊ @@ -652,9 +540,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ - self.pausable.assert_not_paused();␊ - let caller = get_caller_address();␊ - self.erc20._burn(caller, value);␊ + self.erc20._burn(get_caller_address(), value);␊ }␊ }␊ }␊ @@ -665,7 +551,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -734,7 +620,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -801,7 +687,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -878,7 +764,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ @@ -975,7 +861,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -1054,15 +940,9 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ - impl ERC20VotesHooksImpl<␊ - TContractState,␊ - impl ERC20Votes: ERC20VotesComponent::HasComponent,␊ - impl HasComponent: ERC20Component::HasComponent,␊ - +NoncesComponent::HasComponent,␊ - +Drop␊ - > of ERC20Component::ERC20HooksTrait {␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ fn before_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ @@ -1070,13 +950,13 @@ Generated by [AVA](https://avajs.dev). }␊ ␊ fn after_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);␊ - erc20_votes_component.transfer_voting_units(from, recipient, amount);␊ + let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);␊ + contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ @@ -1095,7 +975,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -1174,15 +1054,9 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ - impl ERC20VotesHooksImpl<␊ - TContractState,␊ - impl ERC20Votes: ERC20VotesComponent::HasComponent,␊ - impl HasComponent: ERC20Component::HasComponent,␊ - +NoncesComponent::HasComponent,␊ - +Drop␊ - > of ERC20Component::ERC20HooksTrait {␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ fn before_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ @@ -1190,13 +1064,13 @@ Generated by [AVA](https://avajs.dev). }␊ ␊ fn after_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);␊ - erc20_votes_component.transfer_voting_units(from, recipient, amount);␊ + let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);␊ + contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ @@ -1215,7 +1089,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -1275,15 +1149,9 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ - impl ERC20VotesHooksImpl<␊ - TContractState,␊ - impl ERC20Votes: ERC20VotesComponent::HasComponent,␊ - impl HasComponent: ERC20Component::HasComponent,␊ - +NoncesComponent::HasComponent,␊ - +Drop␊ - > of ERC20Component::ERC20HooksTrait {␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ fn before_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ @@ -1291,13 +1159,13 @@ Generated by [AVA](https://avajs.dev). }␊ ␊ fn after_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);␊ - erc20_votes_component.transfer_voting_units(from, recipient, amount);␊ + let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);␊ + contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ }␊ @@ -1308,7 +1176,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -1317,7 +1185,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::token::erc20::ERC20Component;␊ use openzeppelin::token::erc20::extensions::ERC20VotesComponent;␊ use openzeppelin::token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait;␊ - use openzeppelin::token::erc20::interface;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::ContractAddress;␊ @@ -1330,7 +1197,7 @@ Generated by [AVA](https://avajs.dev). component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl;␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -1391,84 +1258,25 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ - impl ERC20VotesHooksImpl<␊ - TContractState,␊ - impl ERC20Votes: ERC20VotesComponent::HasComponent,␊ - impl HasComponent: ERC20Component::HasComponent,␊ - +NoncesComponent::HasComponent,␊ - +Drop␊ - > of ERC20Component::ERC20HooksTrait {␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ fn before_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ + let contract_state = ERC20Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ fn after_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);␊ - erc20_votes_component.transfer_voting_units(from, recipient, amount);␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20CamelOnlyImpl of interface::IERC20CamelOnly {␊ - fn totalSupply(self: @ContractState) -> u256 {␊ - self.total_supply()␊ - }␊ - ␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ - recipient: ContractAddress,␊ - amount: u256,␊ - ) -> bool {␊ - self.transfer_from(sender, recipient, amount)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20Impl of interface::IERC20 {␊ - fn total_supply(self: @ContractState) -> u256 {␊ - self.erc20.total_supply()␊ - }␊ - ␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc20.balance_of(account)␊ - }␊ - ␊ - fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress) -> u256 {␊ - self.erc20.allowance(owner, spender)␊ - }␊ - ␊ - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer(recipient, amount)␊ - }␊ - ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ - recipient: ContractAddress,␊ - amount: u256,␊ - ) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer_from(sender, recipient, amount)␊ - }␊ - ␊ - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.approve(spender, amount)␊ + let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);␊ + contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ @@ -1489,15 +1297,12 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ - self.pausable.assert_not_paused();␊ - let caller = get_caller_address();␊ - self.erc20._burn(caller, value);␊ + self.erc20._burn(get_caller_address(), value);␊ }␊ ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.ownable.assert_only_owner();␊ - self.pausable.assert_not_paused();␊ self.erc20._mint(recipient, amount);␊ }␊ }␊ @@ -1509,7 +1314,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -1518,7 +1323,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::token::erc20::ERC20Component;␊ use openzeppelin::token::erc20::extensions::ERC20VotesComponent;␊ use openzeppelin::token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait;␊ - use openzeppelin::token::erc20::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ @@ -1535,7 +1339,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl;␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -1601,84 +1405,25 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ - impl ERC20VotesHooksImpl<␊ - TContractState,␊ - impl ERC20Votes: ERC20VotesComponent::HasComponent,␊ - impl HasComponent: ERC20Component::HasComponent,␊ - +NoncesComponent::HasComponent,␊ - +Drop␊ - > of ERC20Component::ERC20HooksTrait {␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ fn before_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ + let contract_state = ERC20Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ fn after_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);␊ - erc20_votes_component.transfer_voting_units(from, recipient, amount);␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20CamelOnlyImpl of interface::IERC20CamelOnly {␊ - fn totalSupply(self: @ContractState) -> u256 {␊ - self.total_supply()␊ - }␊ - ␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ - recipient: ContractAddress,␊ - amount: u256,␊ - ) -> bool {␊ - self.transfer_from(sender, recipient, amount)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20Impl of interface::IERC20 {␊ - fn total_supply(self: @ContractState) -> u256 {␊ - self.erc20.total_supply()␊ - }␊ - ␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc20.balance_of(account)␊ - }␊ - ␊ - fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress) -> u256 {␊ - self.erc20.allowance(owner, spender)␊ - }␊ - ␊ - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer(recipient, amount)␊ - }␊ - ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ - recipient: ContractAddress,␊ - amount: u256,␊ - ) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer_from(sender, recipient, amount)␊ - }␊ - ␊ - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.approve(spender, amount)␊ + let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);␊ + contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ @@ -1707,15 +1452,12 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ - self.pausable.assert_not_paused();␊ - let caller = get_caller_address();␊ - self.erc20._burn(caller, value);␊ + self.erc20._burn(get_caller_address(), value);␊ }␊ ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.ownable.assert_only_owner();␊ - self.pausable.assert_not_paused();␊ self.erc20._mint(recipient, amount);␊ }␊ }␊ @@ -1727,7 +1469,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ @@ -1742,7 +1484,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::token::erc20::ERC20Component;␊ use openzeppelin::token::erc20::extensions::ERC20VotesComponent;␊ use openzeppelin::token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait;␊ - use openzeppelin::token::erc20::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ @@ -1761,7 +1502,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl;␊ + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -1842,84 +1583,25 @@ Generated by [AVA](https://avajs.dev). }␊ }␊ ␊ - impl ERC20VotesHooksImpl<␊ - TContractState,␊ - impl ERC20Votes: ERC20VotesComponent::HasComponent,␊ - impl HasComponent: ERC20Component::HasComponent,␊ - +NoncesComponent::HasComponent,␊ - +Drop␊ - > of ERC20Component::ERC20HooksTrait {␊ + impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait {␊ fn before_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ + let contract_state = ERC20Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ fn after_update(␊ - ref self: ERC20Component::ComponentState,␊ + ref self: ERC20Component::ComponentState,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);␊ - erc20_votes_component.transfer_voting_units(from, recipient, amount);␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20CamelOnlyImpl of interface::IERC20CamelOnly {␊ - fn totalSupply(self: @ContractState) -> u256 {␊ - self.total_supply()␊ - }␊ - ␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ - recipient: ContractAddress,␊ - amount: u256,␊ - ) -> bool {␊ - self.transfer_from(sender, recipient, amount)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC20Impl of interface::IERC20 {␊ - fn total_supply(self: @ContractState) -> u256 {␊ - self.erc20.total_supply()␊ - }␊ - ␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc20.balance_of(account)␊ - }␊ - ␊ - fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress) -> u256 {␊ - self.erc20.allowance(owner, spender)␊ - }␊ - ␊ - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer(recipient, amount)␊ - }␊ - ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - sender: ContractAddress,␊ - recipient: ContractAddress,␊ - amount: u256,␊ - ) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.transfer_from(sender, recipient, amount)␊ - }␊ - ␊ - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {␊ - self.pausable.assert_not_paused();␊ - self.erc20.approve(spender, amount)␊ + let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);␊ + contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ @@ -1948,15 +1630,12 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ - self.pausable.assert_not_paused();␊ - let caller = get_caller_address();␊ - self.erc20._burn(caller, value);␊ + self.erc20._burn(get_caller_address(), value);␊ }␊ ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ - self.pausable.assert_not_paused();␊ self.erc20._mint(recipient, amount);␊ }␊ }␊ diff --git a/packages/core-cairo/src/erc20.test.ts.snap b/packages/core-cairo/src/erc20.test.ts.snap index a347d7880..5211ab234 100644 Binary files a/packages/core-cairo/src/erc20.test.ts.snap and b/packages/core-cairo/src/erc20.test.ts.snap differ diff --git a/packages/core-cairo/src/erc20.ts b/packages/core-cairo/src/erc20.ts index 21a4dd8fa..76e49e5fb 100644 --- a/packages/core-cairo/src/erc20.ts +++ b/packages/core-cairo/src/erc20.ts @@ -1,6 +1,6 @@ import { BaseImplementedTrait, Contract, ContractBuilder } from './contract'; import { Access, requireAccessControl, setAccessControl } from './set-access-control'; -import { addPausable, setPausable } from './add-pausable'; +import { addPausable } from './add-pausable'; import { defineFunctions } from './utils/define-functions'; import { CommonOptions, withCommonDefaults, getSelfArg } from './common-options'; import { setUpgradeable } from './set-upgradeable'; @@ -67,7 +67,7 @@ export function buildERC20(opts: ERC20Options): Contract { const allOpts = withDefaults(opts); addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol)); - addERC20MixinOrImpls(c, allOpts.pausable); + addERC20Mixin(c); if (allOpts.premint) { addPremint(c, allOpts.premint); @@ -79,35 +79,13 @@ export function buildERC20(opts: ERC20Options): Contract { if (allOpts.burnable) { addBurnable(c); - if (allOpts.pausable) { - setPausable(c, externalTrait, functions.burn); - } } if (allOpts.mintable) { addMintable(c, allOpts.access); - if (allOpts.pausable) { - setPausable(c, externalTrait, functions.mint); - } } - if (allOpts.votes) { - if (!allOpts.appName) { - throw new OptionsError({ - appName: 'Application Name is required when Votes are enabled', - }); - } - - if (!allOpts.appVersion) { - throw new OptionsError({ - appVersion: 'Application Version is required when Votes are enabled', - }); - } - - addVotes(c, toFelt252(allOpts.appName, 'appName'), toFelt252(allOpts.appVersion, 'appVersion')); - } else { - c.addStandaloneImport('openzeppelin::token::erc20::ERC20HooksEmptyImpl'); - } + addHooks(c, allOpts); setAccessControl(c, allOpts.access); setUpgradeable(c, allOpts.upgradeable, allOpts.access); @@ -116,52 +94,77 @@ export function buildERC20(opts: ERC20Options): Contract { return c; } -function addERC20Interface(c: ContractBuilder) { - c.addStandaloneImport('openzeppelin::token::erc20::interface'); -} - -function addERC20MixinOrImpls(c: ContractBuilder, pausable: boolean) { - if (pausable) { - addERC20Interface(c); - - c.addImplToComponent(components.ERC20Component, { - name: 'ERC20MetadataImpl', - value: 'ERC20Component::ERC20MetadataImpl', +function addHooks(c: ContractBuilder, allOpts: Required) { + if (allOpts.votes || allOpts.pausable) { + const hooksTrait = { + name: 'ERC20HooksImpl', + of: 'ERC20Component::ERC20HooksTrait', + tags: [], + priority: 1, + }; + c.addImplementedTrait(hooksTrait); + + const beforeUpdateFn = c.addFunction(hooksTrait, { + name: 'before_update', + args: [ + { name: 'ref self', type: 'ERC20Component::ComponentState' }, + { name: 'from', type: 'ContractAddress' }, + { name: 'recipient', type: 'ContractAddress' }, + { name: 'amount', type: 'u256' }, + ], + code: [], }); - const ERC20Impl: BaseImplementedTrait = { - name: 'ERC20Impl', - of: 'interface::IERC20', - tags: [ - 'abi(embed_v0)' + const afterUpdateFn = c.addFunction(hooksTrait, { + name: 'after_update', + args: [ + { name: 'ref self', type: 'ERC20Component::ComponentState' }, + { name: 'from', type: 'ContractAddress' }, + { name: 'recipient', type: 'ContractAddress' }, + { name: 'amount', type: 'u256' }, ], + code: [], + }); + + if (allOpts.pausable) { + beforeUpdateFn.code.push( + 'let contract_state = ERC20Component::HasComponent::get_contract(@self);', + 'contract_state.pausable.assert_not_paused();', + ); } - c.addFunction(ERC20Impl, functions.total_supply); - c.addFunction(ERC20Impl, functions.balance_of); - c.addFunction(ERC20Impl, functions.allowance); - setPausable(c, ERC20Impl, functions.transfer); - setPausable(c, ERC20Impl, functions.transfer_from); - setPausable(c, ERC20Impl, functions.approve); - - const ERC20CamelOnlyImpl: BaseImplementedTrait = { - name: 'ERC20CamelOnlyImpl', - of: 'interface::IERC20CamelOnly', - tags: [ - 'abi(embed_v0)' - ], + + if (allOpts.votes) { + if (!allOpts.appName) { + throw new OptionsError({ + appName: 'Application Name is required when Votes are enabled', + }); + } + + if (!allOpts.appVersion) { + throw new OptionsError({ + appVersion: 'Application Version is required when Votes are enabled', + }); + } + + addVotesComponent(c, toFelt252(allOpts.appName, 'appName'), toFelt252(allOpts.appVersion, 'appVersion')); + + afterUpdateFn.code.push( + 'let mut contract_state = ERC20Component::HasComponent::get_contract_mut(ref self);', + 'contract_state.erc20_votes.transfer_voting_units(from, recipient, amount);', + ); } - // Camel case versions of the functions above. Pausable is already set above. - c.addFunction(ERC20CamelOnlyImpl, functions.totalSupply); - c.addFunction(ERC20CamelOnlyImpl, functions.balanceOf); - c.addFunction(ERC20CamelOnlyImpl, functions.transferFrom); } else { - c.addImplToComponent(components.ERC20Component, { - name: 'ERC20MixinImpl', - value: 'ERC20Component::ERC20MixinImpl', - }); + c.addStandaloneImport('openzeppelin::token::erc20::ERC20HooksEmptyImpl'); } } +function addERC20Mixin(c: ContractBuilder) { + c.addImplToComponent(components.ERC20Component, { + name: 'ERC20MixinImpl', + value: 'ERC20Component::ERC20MixinImpl', + }); +} + function addBase(c: ContractBuilder, name: string, symbol: string) { c.addComponent( components.ERC20Component, @@ -241,10 +244,9 @@ function addMintable(c: ContractBuilder, access: Access) { requireAccessControl(c, externalTrait, functions.mint, access, 'MINTER', 'minter'); } -function addVotes(c: ContractBuilder, name: string, version: string) { +function addVotesComponent(c: ContractBuilder, name: string, version: string) { c.addComponent(components.ERC20VotesComponent, [], false); c.addComponent(components.NoncesComponent, [], false); - c.addStandaloneImport('openzeppelin::token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait'); c.addStandaloneImport('openzeppelin::utils::cryptography::snip12::SNIP12Metadata'); c.addStandaloneImport('starknet::ContractAddress'); @@ -274,45 +276,6 @@ function addVotes(c: ContractBuilder, name: string, version: string) { `'${version}'`, ], }); - - const ERC20HooksTrait: BaseImplementedTrait = { - name: `ERC20VotesHooksImpl< - TContractState, - impl ERC20Votes: ERC20VotesComponent::HasComponent, - impl HasComponent: ERC20Component::HasComponent, - +NoncesComponent::HasComponent, - +Drop - >`, - of: 'ERC20Component::ERC20HooksTrait', - tags: [], - priority: 1, - }; - c.addImplementedTrait(ERC20HooksTrait); - - c.addFunction(ERC20HooksTrait, { - name: 'before_update', - args: [ - { name: 'ref self', type: 'ERC20Component::ComponentState' }, - { name: 'from', type: 'ContractAddress' }, - { name: 'recipient', type: 'ContractAddress' }, - { name: 'amount', type: 'u256' }, - ], - code: [], - }); - - c.addFunction(ERC20HooksTrait, { - name: 'after_update', - args: [ - { name: 'ref self', type: 'ERC20Component::ComponentState' }, - { name: 'from', type: 'ContractAddress' }, - { name: 'recipient', type: 'ContractAddress' }, - { name: 'amount', type: 'u256' }, - ], - code: [ - 'let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes);', - 'erc20_votes_component.transfer_voting_units(from, recipient, amount);', - ], - }); } const components = defineComponents( { @@ -375,8 +338,7 @@ const functions = defineFunctions({ { name: 'value', type: 'u256' } ], code: [ - 'let caller = get_caller_address();', - 'self.erc20._burn(caller, value);' + 'self.erc20._burn(get_caller_address(), value);' ] }, mint: { @@ -389,103 +351,4 @@ const functions = defineFunctions({ 'self.erc20._mint(recipient, amount);' ] }, - - // Re-implements ERC20Impl - total_supply: { - args: [ - getSelfArg('view') - ], - code: [ - 'self.erc20.total_supply()' - ], - returns : 'u256', - }, - balance_of: { - args: [ - getSelfArg('view'), - { name: 'account', type: 'ContractAddress' }, - ], - code: [ - 'self.erc20.balance_of(account)' - ], - returns : 'u256', - }, - allowance: { - args: [ - getSelfArg('view'), - { name: 'owner', type: 'ContractAddress' }, - { name: 'spender', type: 'ContractAddress' }, - ], - code: [ - 'self.erc20.allowance(owner, spender)' - ], - returns : 'u256', - }, - transfer: { - args: [ - getSelfArg(), - { name: 'recipient', type: 'ContractAddress' }, - { name: 'amount', type: 'u256' }, - ], - code: [ - 'self.erc20.transfer(recipient, amount)', - ], - returns : 'bool', - }, - transfer_from: { - args: [ - getSelfArg(), - { name: 'sender', type: 'ContractAddress' }, - { name: 'recipient', type: 'ContractAddress' }, - { name: 'amount', type: 'u256' }, - ], - code: [ - 'self.erc20.transfer_from(sender, recipient, amount)', - ], - returns : 'bool', - }, - approve: { - args: [ - getSelfArg(), - { name: 'spender', type: 'ContractAddress' }, - { name: 'amount', type: 'u256' }, - ], - code: [ - 'self.erc20.approve(spender, amount)', - ], - returns : 'bool', - }, - - // Re-implements ERC20CamelOnlyImpl - totalSupply: { - args: [ - getSelfArg('view') - ], - code: [ - 'self.total_supply()' - ], - returns : 'u256', - }, - balanceOf: { - args: [ - getSelfArg('view'), - { name: 'account', type: 'ContractAddress' }, - ], - code: [ - 'self.balance_of(account)' - ], - returns : 'u256', - }, - transferFrom: { - args: [ - getSelfArg(), - { name: 'sender', type: 'ContractAddress' }, - { name: 'recipient', type: 'ContractAddress' }, - { name: 'amount', type: 'u256' }, - ], - code: [ - 'self.transfer_from(sender, recipient, amount)', - ], - returns : 'bool', - }, }); diff --git a/packages/core-cairo/src/erc721.test.ts.md b/packages/core-cairo/src/erc721.test.ts.md index 3716f65e5..2c7eb15a6 100644 --- a/packages/core-cairo/src/erc721.test.ts.md +++ b/packages/core-cairo/src/erc721.test.ts.md @@ -9,12 +9,13 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::token::erc721::ERC721HooksEmptyImpl;␊ ␊ component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ @@ -53,13 +54,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::token::erc721::ERC721HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -125,13 +127,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::token::erc721::ERC721HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -197,13 +200,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::token::erc721::ERC721HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -268,9 +272,7 @@ Generated by [AVA](https://avajs.dev). impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn burn(ref self: ContractState, token_id: u256) {␊ - let caller = get_caller_address();␊ - assert(self.erc721._is_approved_or_owner(caller, token_id), ERC721Component::Errors::UNAUTHORIZED);␊ - self.erc721._burn(token_id);␊ + self.erc721._update(Zeroable::zero(), token_id, get_caller_address());␊ }␊ }␊ }␊ @@ -281,7 +283,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -289,7 +291,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc721::ERC721Component;␊ - use openzeppelin::token::erc721::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -302,11 +303,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl;␊ - #[abi(embed_v0)]␊ - impl ERC721MetadataCamelOnly = ERC721Component::ERC721MetadataCamelOnlyImpl;␊ - #[abi(embed_v0)]␊ - impl SRC5Impl = SRC5Component::SRC5Impl;␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -352,95 +349,23 @@ Generated by [AVA](https://avajs.dev). self.ownable.initializer(owner);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC721CamelOnlyImpl of interface::IERC721CamelOnly {␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress {␊ - self.owner_of(tokenId)␊ - }␊ - ␊ - fn safeTransferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - data: Span,␊ - ) {␊ - self.safe_transfer_from(from, to, tokenId, data);␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - ) {␊ - self.transfer_from(from, to, tokenId);␊ - }␊ - ␊ - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress {␊ - self.get_approved(tokenId)␊ - }␊ - ␊ - fn isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.is_approved_for_all(owner, operator)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC721Impl of interface::IERC721 {␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc721.balance_of(account)␊ - }␊ - ␊ - fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress {␊ - self.erc721.owner_of(token_id)␊ - }␊ - ␊ - fn safe_transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ + impl ERC721HooksImpl of ERC721Component::ERC721HooksTrait {␊ + fn before_update(␊ + ref self: ERC721Component::ComponentState,␊ to: ContractAddress,␊ token_id: u256,␊ - data: Span,␊ + auth: ContractAddress,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.safe_transfer_from(from, to, token_id, data);␊ + let contract_state = ERC721Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ + fn after_update(␊ + ref self: ERC721Component::ComponentState,␊ to: ContractAddress,␊ token_id: u256,␊ + auth: ContractAddress,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.transfer_from(from, to, token_id);␊ - }␊ - ␊ - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.approve(to, token_id);␊ - }␊ - ␊ - fn set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress {␊ - self.erc721.get_approved(token_id)␊ - }␊ - ␊ - fn is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.erc721.is_approved_for_all(owner, operator)␊ }␊ }␊ ␊ @@ -475,13 +400,14 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::token::erc721::ERC721HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -572,7 +498,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ @@ -583,6 +509,7 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::token::erc721::ERC721HooksEmptyImpl;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -685,7 +612,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -693,7 +620,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc721::ERC721Component;␊ - use openzeppelin::token::erc721::interface;␊ use starknet::ContractAddress;␊ use starknet::get_caller_address;␊ ␊ @@ -703,11 +629,7 @@ Generated by [AVA](https://avajs.dev). component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl;␊ - #[abi(embed_v0)]␊ - impl ERC721MetadataCamelOnly = ERC721Component::ERC721MetadataCamelOnlyImpl;␊ - #[abi(embed_v0)]␊ - impl SRC5Impl = SRC5Component::SRC5Impl;␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -748,95 +670,23 @@ Generated by [AVA](https://avajs.dev). self.ownable.initializer(owner);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC721CamelOnlyImpl of interface::IERC721CamelOnly {␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress {␊ - self.owner_of(tokenId)␊ - }␊ - ␊ - fn safeTransferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - data: Span,␊ - ) {␊ - self.safe_transfer_from(from, to, tokenId, data);␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - ) {␊ - self.transfer_from(from, to, tokenId);␊ - }␊ - ␊ - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress {␊ - self.get_approved(tokenId)␊ - }␊ - ␊ - fn isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.is_approved_for_all(owner, operator)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC721Impl of interface::IERC721 {␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc721.balance_of(account)␊ - }␊ - ␊ - fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress {␊ - self.erc721.owner_of(token_id)␊ - }␊ - ␊ - fn safe_transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ + impl ERC721HooksImpl of ERC721Component::ERC721HooksTrait {␊ + fn before_update(␊ + ref self: ERC721Component::ComponentState,␊ to: ContractAddress,␊ token_id: u256,␊ - data: Span,␊ + auth: ContractAddress,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.safe_transfer_from(from, to, token_id, data);␊ + let contract_state = ERC721Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ + fn after_update(␊ + ref self: ERC721Component::ComponentState,␊ to: ContractAddress,␊ token_id: u256,␊ + auth: ContractAddress,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.transfer_from(from, to, token_id);␊ - }␊ - ␊ - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.approve(to, token_id);␊ - }␊ - ␊ - fn set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress {␊ - self.erc721.get_approved(token_id)␊ - }␊ - ␊ - fn is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.erc721.is_approved_for_all(owner, operator)␊ }␊ }␊ ␊ @@ -857,10 +707,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, token_id: u256) {␊ - self.pausable.assert_not_paused();␊ - let caller = get_caller_address();␊ - assert(self.erc721._is_approved_or_owner(caller, token_id), ERC721Component::Errors::UNAUTHORIZED);␊ - self.erc721._burn(token_id);␊ + self.erc721._update(Zeroable::zero(), token_id, get_caller_address());␊ }␊ ␊ #[external(v0)]␊ @@ -871,7 +718,6 @@ Generated by [AVA](https://avajs.dev). data: Span,␊ ) {␊ self.ownable.assert_only_owner();␊ - self.pausable.assert_not_paused();␊ self.erc721._safe_mint(recipient, token_id, data);␊ }␊ ␊ @@ -893,7 +739,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.12.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.13.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -901,7 +747,6 @@ Generated by [AVA](https://avajs.dev). use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc721::ERC721Component;␊ - use openzeppelin::token::erc721::interface;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use starknet::ClassHash;␊ @@ -915,11 +760,7 @@ Generated by [AVA](https://avajs.dev). component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ #[abi(embed_v0)]␊ - impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl;␊ - #[abi(embed_v0)]␊ - impl ERC721MetadataCamelOnly = ERC721Component::ERC721MetadataCamelOnlyImpl;␊ - #[abi(embed_v0)]␊ - impl SRC5Impl = SRC5Component::SRC5Impl;␊ + impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl;␊ #[abi(embed_v0)]␊ @@ -965,95 +806,23 @@ Generated by [AVA](https://avajs.dev). self.ownable.initializer(owner);␊ }␊ ␊ - #[abi(embed_v0)]␊ - impl ERC721CamelOnlyImpl of interface::IERC721CamelOnly {␊ - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.balance_of(account)␊ - }␊ - ␊ - fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress {␊ - self.owner_of(tokenId)␊ - }␊ - ␊ - fn safeTransferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - data: Span,␊ - ) {␊ - self.safe_transfer_from(from, to, tokenId, data);␊ - }␊ - ␊ - fn transferFrom(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ - to: ContractAddress,␊ - tokenId: u256,␊ - ) {␊ - self.transfer_from(from, to, tokenId);␊ - }␊ - ␊ - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress {␊ - self.get_approved(tokenId)␊ - }␊ - ␊ - fn isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.is_approved_for_all(owner, operator)␊ - }␊ - }␊ - ␊ - #[abi(embed_v0)]␊ - impl ERC721Impl of interface::IERC721 {␊ - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {␊ - self.erc721.balance_of(account)␊ - }␊ - ␊ - fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress {␊ - self.erc721.owner_of(token_id)␊ - }␊ - ␊ - fn safe_transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ + impl ERC721HooksImpl of ERC721Component::ERC721HooksTrait {␊ + fn before_update(␊ + ref self: ERC721Component::ComponentState,␊ to: ContractAddress,␊ token_id: u256,␊ - data: Span,␊ + auth: ContractAddress,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.safe_transfer_from(from, to, token_id, data);␊ + let contract_state = ERC721Component::HasComponent::get_contract(@self);␊ + contract_state.pausable.assert_not_paused();␊ }␊ ␊ - fn transfer_from(␊ - ref self: ContractState,␊ - from: ContractAddress,␊ + fn after_update(␊ + ref self: ERC721Component::ComponentState,␊ to: ContractAddress,␊ token_id: u256,␊ + auth: ContractAddress,␊ ) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.transfer_from(from, to, token_id);␊ - }␊ - ␊ - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.approve(to, token_id);␊ - }␊ - ␊ - fn set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool) {␊ - self.pausable.assert_not_paused();␊ - self.erc721.set_approval_for_all(operator, approved);␊ - }␊ - ␊ - fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress {␊ - self.erc721.get_approved(token_id)␊ - }␊ - ␊ - fn is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool {␊ - self.erc721.is_approved_for_all(owner, operator)␊ }␊ }␊ ␊ @@ -1082,10 +851,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[external(v0)]␊ fn burn(ref self: ContractState, token_id: u256) {␊ - self.pausable.assert_not_paused();␊ - let caller = get_caller_address();␊ - assert(self.erc721._is_approved_or_owner(caller, token_id), ERC721Component::Errors::UNAUTHORIZED);␊ - self.erc721._burn(token_id);␊ + self.erc721._update(Zeroable::zero(), token_id, get_caller_address());␊ }␊ ␊ #[external(v0)]␊ @@ -1096,7 +862,6 @@ Generated by [AVA](https://avajs.dev). data: Span,␊ ) {␊ self.ownable.assert_only_owner();␊ - self.pausable.assert_not_paused();␊ self.erc721._safe_mint(recipient, token_id, data);␊ }␊ ␊ diff --git a/packages/core-cairo/src/erc721.test.ts.snap b/packages/core-cairo/src/erc721.test.ts.snap index b16976b46..f4485c906 100644 Binary files a/packages/core-cairo/src/erc721.test.ts.snap and b/packages/core-cairo/src/erc721.test.ts.snap differ diff --git a/packages/core-cairo/src/erc721.ts b/packages/core-cairo/src/erc721.ts index d599ada13..a309a4a88 100644 --- a/packages/core-cairo/src/erc721.ts +++ b/packages/core-cairo/src/erc721.ts @@ -1,6 +1,6 @@ import { BaseImplementedTrait, Contract, ContractBuilder } from './contract'; import { Access, requireAccessControl, setAccessControl } from './set-access-control'; -import { addPausable, setPausable } from './add-pausable'; +import { addPausable } from './add-pausable'; import { defineFunctions } from './utils/define-functions'; import { CommonOptions, withCommonDefaults, getSelfArg } from './common-options'; import { setUpgradeable } from './set-upgradeable'; @@ -58,25 +58,21 @@ export function buildERC721(opts: ERC721Options): Contract { const allOpts = withDefaults(opts); addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), toByteArray(allOpts.baseUri)); - addERC721MixinOrImpls(c, allOpts.pausable); - addSRC5Component(c); + addERC721Mixin(c); if (allOpts.pausable) { addPausable(c, allOpts.access); + addPausableHook(c); + } else { + c.addStandaloneImport('openzeppelin::token::erc721::ERC721HooksEmptyImpl'); } if (allOpts.burnable) { addBurnable(c); - if (allOpts.pausable) { - setPausable(c, externalTrait, functions.burn); - } } if (allOpts.mintable) { addMintable(c, allOpts.access); - if (allOpts.pausable) { - setPausable(c, externalTrait, functions.safe_mint); - } } setAccessControl(c, allOpts.access); @@ -86,61 +82,50 @@ export function buildERC721(opts: ERC721Options): Contract { return c; } -function addERC721Interface(c: ContractBuilder) { - c.addStandaloneImport('openzeppelin::token::erc721::interface'); -} +function addPausableHook(c: ContractBuilder) { + const ERC721HooksTrait: BaseImplementedTrait = { + name: `ERC721HooksImpl`, + of: 'ERC721Component::ERC721HooksTrait', + tags: [], + priority: 0, + }; + c.addImplementedTrait(ERC721HooksTrait); -function addERC721MixinOrImpls(c: ContractBuilder, pausable: boolean) { - if (pausable) { - addERC721Interface(c); + c.addStandaloneImport('starknet::ContractAddress'); - c.addImplToComponent(components.ERC721Component, { - name: 'ERC721MetadataImpl', - value: 'ERC721Component::ERC721MetadataImpl', - }); - c.addImplToComponent(components.ERC721Component, { - name: 'ERC721MetadataCamelOnly', - value: 'ERC721Component::ERC721MetadataCamelOnlyImpl', - }); + c.addFunction(ERC721HooksTrait, { + name: 'before_update', + args: [ + { name: 'ref self', type: `ERC721Component::ComponentState` }, + { name: 'to', type: 'ContractAddress' }, + { name: 'token_id', type: 'u256' }, + { name: 'auth', type: 'ContractAddress' }, + ], + code: [ + 'let contract_state = ERC721Component::HasComponent::get_contract(@self)', + 'contract_state.pausable.assert_not_paused()', + ], + }); - const ERC721Impl: BaseImplementedTrait = { - name: 'ERC721Impl', - of: 'interface::IERC721', - tags: [ - 'abi(embed_v0)' - ], - } - c.addFunction(ERC721Impl, functions.balance_of); - c.addFunction(ERC721Impl, functions.owner_of); - setPausable(c, ERC721Impl, functions.safe_transfer_from); - setPausable(c, ERC721Impl, functions.transfer_from); - setPausable(c, ERC721Impl, functions.approve); - setPausable(c, ERC721Impl, functions.set_approval_for_all); - c.addFunction(ERC721Impl, functions.get_approved); - c.addFunction(ERC721Impl, functions.is_approved_for_all); + c.addFunction(ERC721HooksTrait, { + name: 'after_update', + args: [ + { name: 'ref self', type: `ERC721Component::ComponentState` }, + { name: 'to', type: 'ContractAddress' }, + { name: 'token_id', type: 'u256' }, + { name: 'auth', type: 'ContractAddress' }, + ], + code: [], + }); +} - const ERC721CamelOnlyImpl: BaseImplementedTrait = { - name: 'ERC721CamelOnlyImpl', - of: 'interface::IERC721CamelOnly', - tags: [ - 'abi(embed_v0)' - ], - } - // Camel case versions of the functions above. Pausable is already set above. - c.addFunction(ERC721CamelOnlyImpl, functions.balanceOf); - c.addFunction(ERC721CamelOnlyImpl, functions.ownerOf); - c.addFunction(ERC721CamelOnlyImpl, functions.safeTransferFrom); - c.addFunction(ERC721CamelOnlyImpl, functions.transferFrom); - c.addFunction(ERC721CamelOnlyImpl, functions.setApprovalForAll); - c.addFunction(ERC721CamelOnlyImpl, functions.getApproved); - c.addFunction(ERC721CamelOnlyImpl, functions.isApprovedForAll); - } else { - c.addImplToComponent(components.ERC721Component, { - name: 'ERC721MixinImpl', - value: 'ERC721Component::ERC721MixinImpl', - }); - c.addInterfaceFlag('ISRC5'); - } +function addERC721Mixin(c: ContractBuilder) { + c.addImplToComponent(components.ERC721Component, { + name: 'ERC721MixinImpl', + value: 'ERC721Component::ERC721MixinImpl', + }); + c.addInterfaceFlag('ISRC5'); + addSRC5Component(c); } function addBase(c: ContractBuilder, name: string, symbol: string, baseUri: string) { @@ -192,9 +177,7 @@ const functions = defineFunctions({ { name: 'token_id', type: 'u256' } ], code: [ - 'let caller = get_caller_address();', - 'assert(self.erc721._is_approved_or_owner(caller, token_id), ERC721Component::Errors::UNAUTHORIZED)', - 'self.erc721._burn(token_id);' + 'self.erc721._update(Zeroable::zero(), token_id, get_caller_address());', ] }, safe_mint: { @@ -219,167 +202,4 @@ const functions = defineFunctions({ 'self.safe_mint(recipient, tokenId, data);', ] }, - - // Re-implements ERC721Impl - balance_of: { - args: [ - getSelfArg('view'), - { name: 'account', type: 'ContractAddress' }, - ], - returns: 'u256', - code: [ - 'self.erc721.balance_of(account)' - ] - }, - owner_of: { - args: [ - getSelfArg('view'), - { name: 'token_id', type: 'u256' }, - ], - returns: 'ContractAddress', - code: [ - 'self.erc721.owner_of(token_id)' - ] - }, - safe_transfer_from: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'token_id', type: 'u256' }, - { name: 'data', type: 'Span' }, - ], - code: [ - 'self.erc721.safe_transfer_from(from, to, token_id, data)' - ] - }, - transfer_from: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'token_id', type: 'u256' }, - ], - code: [ - 'self.erc721.transfer_from(from, to, token_id)' - ] - }, - approve: { - args: [ - getSelfArg(), - { name: 'to', type: 'ContractAddress' }, - { name: 'token_id', type: 'u256' }, - ], - code: [ - 'self.erc721.approve(to, token_id)' - ] - }, - set_approval_for_all: { - args: [ - getSelfArg(), - { name: 'operator', type: 'ContractAddress' }, - { name: 'approved', type: 'bool' }, - ], - code: [ - 'self.erc721.set_approval_for_all(operator, approved)' - ] - }, - get_approved: { - args: [ - getSelfArg('view'), - { name: 'token_id', type: 'u256' }, - ], - returns: 'ContractAddress', - code: [ - 'self.erc721.get_approved(token_id)' - ] - }, - is_approved_for_all: { - args: [ - getSelfArg('view'), - { name: 'owner', type: 'ContractAddress' }, - { name: 'operator', type: 'ContractAddress' }, - ], - returns: 'bool', - code: [ - 'self.erc721.is_approved_for_all(owner, operator)' - ] - }, - - // Re-implements ERC721CamelOnlyImpl - - balanceOf: { - args: [ - getSelfArg('view'), - { name: 'account', type: 'ContractAddress' }, - ], - returns: 'u256', - code: [ - 'self.balance_of(account)' - ] - }, - ownerOf: { - args: [ - getSelfArg('view'), - { name: 'tokenId', type: 'u256' }, - ], - returns: 'ContractAddress', - code: [ - 'self.owner_of(tokenId)' - ] - }, - safeTransferFrom: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'tokenId', type: 'u256' }, - { name: 'data', type: 'Span' }, - ], - code: [ - 'self.safe_transfer_from(from, to, tokenId, data)' - ] - }, - transferFrom: { - args: [ - getSelfArg(), - { name: 'from', type: 'ContractAddress' }, - { name: 'to', type: 'ContractAddress' }, - { name: 'tokenId', type: 'u256' }, - ], - code: [ - 'self.transfer_from(from, to, tokenId)' - ] - }, - setApprovalForAll: { - args: [ - getSelfArg(), - { name: 'operator', type: 'ContractAddress' }, - { name: 'approved', type: 'bool' }, - ], - code: [ - 'self.set_approval_for_all(operator, approved)' - ] - }, - getApproved: { - args: [ - getSelfArg('view'), - { name: 'tokenId', type: 'u256' }, - ], - returns: 'ContractAddress', - code: [ - 'self.get_approved(tokenId)' - ] - }, - isApprovedForAll: { - args: [ - getSelfArg('view'), - { name: 'owner', type: 'ContractAddress' }, - { name: 'operator', type: 'ContractAddress' }, - ], - returns: 'bool', - code: [ - 'self.is_approved_for_all(owner, operator)' - ] - }, }); diff --git a/packages/core-cairo/src/utils/version.ts b/packages/core-cairo/src/utils/version.ts index 06b204669..c3df2ba75 100644 --- a/packages/core-cairo/src/utils/version.ts +++ b/packages/core-cairo/src/utils/version.ts @@ -1,10 +1,10 @@ /** * The actual latest version to use in links. */ -export const contractsVersion = '0.12.0'; +export const contractsVersion = '0.13.0'; export const contractsVersionTag = `v${contractsVersion}`; /** * Semantic version string representing of the minimum compatible version of Contracts to display in output. */ -export const compatibleContractsSemver = '^0.12.0'; +export const compatibleContractsSemver = '^0.13.0';