Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/macros/src/attribute/with_components/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum AllowedComponents {
ReentrancyGuard,
ERC20,
ERC721,
ERC721Consecutive,
ERC721Enumerable,
ERC721Receiver,
ERC721URIStorage,
Expand Down Expand Up @@ -63,6 +64,7 @@ impl AllowedComponents {
"ReentrancyGuard" => Ok(AllowedComponents::ReentrancyGuard),
"ERC20" => Ok(AllowedComponents::ERC20),
"ERC721" => Ok(AllowedComponents::ERC721),
"ERC721Consecutive" => Ok(AllowedComponents::ERC721Consecutive),
"ERC721Enumerable" => Ok(AllowedComponents::ERC721Enumerable),
"ERC721Receiver" => Ok(AllowedComponents::ERC721Receiver),
"ERC721URIStorage" => Ok(AllowedComponents::ERC721URIStorage),
Expand Down Expand Up @@ -213,6 +215,15 @@ impl AllowedComponents {
has_immutable_config: false,
internal_impls: vec!["InternalImpl"],
},
AllowedComponents::ERC721Consecutive => ComponentInfo {
name: "ERC721ConsecutiveComponent",
path: "openzeppelin_token::erc721::extensions::ERC721ConsecutiveComponent",
storage: "erc721_consecutive",
event: "ERC721ConsecutiveEvent",
has_initializer: false,
has_immutable_config: true,
internal_impls: vec!["InternalImpl"],
},
AllowedComponents::ERC721Enumerable => ComponentInfo {
name: "ERC721EnumerableComponent",
path: "openzeppelin_token::erc721::extensions::ERC721EnumerableComponent",
Expand Down
11 changes: 11 additions & 0 deletions packages/macros/src/attribute/with_components/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ pub mod warnings {
"
};

/// Warning when the ERC721Consecutive hook calls are missing.
pub const ERC721_CONSECUTIVE_HOOKS_MISSING: &str = indoc! {
"The ERC721Consecutive component requires calling both
`self.erc721_consecutive.before_update(...)` in `ERC721HooksTrait::before_update`
and `self.erc721_consecutive.after_update(...)` in `ERC721HooksTrait::after_update`,
and it looks like one or both are missing.

This may lead to incorrect ownership or burn tracking for consecutively minted tokens.
"
};

/// Warning when the ERC4626 component is missing an implementation of the ERC4626HooksTrait.
pub const ERC4626_HOOKS_IMPL_MISSING: &str = indoc! {
"The ERC4626 component requires an implementation of the ERC4626HooksTrait in scope and
Expand Down
20 changes: 17 additions & 3 deletions packages/macros/src/attribute/with_components/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,12 @@ fn validate_contract_module(
// 4. Disallow ERC721Enumerable and ERC721Consecutive being used together (error)
let uses_erc721_enumerable = components_info
.iter()
.any(|c| matches!(c.kind(), AllowedComponents::ERC721Enumerable));
let uses_erc721_consecutive = body_code.contains("ERC721Consecutive");
.any(|c| matches!(c.kind(), AllowedComponents::ERC721Enumerable))
|| body_code.contains("ERC721Enumerable");
let uses_erc721_consecutive = components_info
.iter()
.any(|c| matches!(c.kind(), AllowedComponents::ERC721Consecutive))
|| body_code.contains("ERC721Consecutive");
if uses_erc721_enumerable && uses_erc721_consecutive {
let error = Diagnostic::error(errors::ERC721_BALANCE_OF_INCOPATIBILITY);
return (vec![error], vec![]);
Expand Down Expand Up @@ -198,7 +202,7 @@ fn validate_contract_module(
}
}

// 6. Check that the contract has the corresponding immutable configs
// 6. Check that the contract has the corresponding immutable configs (warning)
for component in components_info.iter().filter(|c| c.has_immutable_config) {
// Case 1: DefaultConfig is imported and used
let component_parent_path = component
Expand Down Expand Up @@ -386,6 +390,16 @@ fn add_per_component_warnings(code: &str, component_info: &ComponentInfo) -> Vec
warnings.push(warning);
}
}
AllowedComponents::ERC721Consecutive => {
let before_update_called = code.contains("erc721_consecutive.before_update(")
|| code.contains("ERC721ConsecutiveInternalImpl::before_update(");
let after_update_called = code.contains("erc721_consecutive.after_update(")
|| code.contains("ERC721ConsecutiveInternalImpl::after_update(");
if !before_update_called || !after_update_called {
let warning = Diagnostic::warn(warnings::ERC721_CONSECUTIVE_HOOKS_MISSING);
warnings.push(warning);
}
}
_ => {}
}
warnings
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: src/tests/test_with_components.rs
expression: result
snapshot_kind: text
---
TokenStream:

None

Diagnostics:

====
Error: ERC721Enumerable and ERC721Consecutive interfere with each other in token ownership tracking and should not be used together.
====

AuxData:

None
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: src/tests/test_with_components.rs
expression: result
snapshot_kind: text
---
TokenStream:

None

Diagnostics:

====
Error: ERC721Enumerable and ERC721Consecutive interfere with each other in token ownership tracking and should not be used together.
====

AuxData:

None
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
source: src/tests/test_with_components.rs
expression: result
snapshot_kind: text
---
TokenStream:

#[starknet::contract]
pub mod MyContract {
use openzeppelin_token::erc721::extensions::DefaultConfig;
#[storage]
pub struct Storage {
#[substorage(v0)]
pub erc721_consecutive: ERC721ConsecutiveComponent::Storage,
}
use openzeppelin_token::erc721::extensions::ERC721ConsecutiveComponent;

component!(
path: ERC721ConsecutiveComponent,
storage: erc721_consecutive,
event: ERC721ConsecutiveEvent,
);

impl ERC721ConsecutiveInternalImpl = ERC721ConsecutiveComponent::InternalImpl<ContractState>;

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC721ConsecutiveEvent: ERC721ConsecutiveComponent::Event,
}
}


Diagnostics:

====
Warning: The ERC721Consecutive component requires calling both
`self.erc721_consecutive.before_update(...)` in `ERC721HooksTrait::before_update`
and `self.erc721_consecutive.after_update(...)` in `ERC721HooksTrait::after_update`,
and it looks like one or both are missing.

This may lead to incorrect ownership or burn tracking for consecutively minted tokens.
====

AuxData:

None
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
source: src/tests/test_with_components.rs
expression: result
snapshot_kind: text
---
TokenStream:

#[starknet::contract]
pub mod MyContract {
use openzeppelin_token::erc721::extensions::ERC721ConsecutiveComponent;
pub impl ERC721ConsecutiveConfig of ERC721ConsecutiveComponent::ImmutableConfig {
const MAX_BATCH_SIZE: u64 = 4200;
const FIRST_CONSECUTIVE_ID: u64 = 42;
}
#[storage]
pub struct Storage {
#[substorage(v0)]
pub erc721_consecutive: ERC721ConsecutiveComponent::Storage,
}
use openzeppelin_token::erc721::extensions::ERC721ConsecutiveComponent;

component!(
path: ERC721ConsecutiveComponent,
storage: erc721_consecutive,
event: ERC721ConsecutiveEvent,
);

impl ERC721ConsecutiveInternalImpl = ERC721ConsecutiveComponent::InternalImpl<ContractState>;

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC721ConsecutiveEvent: ERC721ConsecutiveComponent::Event,
}
}


Diagnostics:

====
Warning: The ERC721Consecutive component requires calling both
`self.erc721_consecutive.before_update(...)` in `ERC721HooksTrait::before_update`
and `self.erc721_consecutive.after_update(...)` in `ERC721HooksTrait::after_update`,
and it looks like one or both are missing.

This may lead to incorrect ownership or burn tracking for consecutively minted tokens.
====

AuxData:

None
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
source: src/tests/test_with_components.rs
expression: result
snapshot_kind: text
---
TokenStream:

#[starknet::contract]
pub mod MyContract {
#[storage]
pub struct Storage {
#[substorage(v0)]
pub erc721_consecutive: ERC721ConsecutiveComponent::Storage,
}
use openzeppelin_token::erc721::extensions::ERC721ConsecutiveComponent;

component!(
path: ERC721ConsecutiveComponent,
storage: erc721_consecutive,
event: ERC721ConsecutiveEvent,
);

impl ERC721ConsecutiveInternalImpl = ERC721ConsecutiveComponent::InternalImpl<ContractState>;

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC721ConsecutiveEvent: ERC721ConsecutiveComponent::Event,
}
}


Diagnostics:

====
Warning: The ERC721Consecutive component requires an ImmutableConfig implementation in scope and
it looks like it is missing.

You can use the default implementation by importing it:

`use openzeppelin_token::erc721::extensions::DefaultConfig;`
========
Warning: The ERC721Consecutive component requires calling both
`self.erc721_consecutive.before_update(...)` in `ERC721HooksTrait::before_update`
and `self.erc721_consecutive.after_update(...)` in `ERC721HooksTrait::after_update`,
and it looks like one or both are missing.

This may lead to incorrect ownership or burn tracking for consecutively minted tokens.
====

AuxData:

None
Loading