Issue with component! Macro Usage for ReentrancyGuard in Cairo

Hello OpenZeppelin Community,

I'm currently working on a Cairo smart contract and have run into an issue with implementing the ReentrancyGuard component from the OpenZeppelin library for Cairo. I'm using OpenZeppelin Contracts for Cairo version 0.8.0-beta.0.

Problem Description:

When trying to declare the ReentrancyGuard component in my contract using the component! macro, I encounter the following error during compilation with scarb build:

error: Plugin diagnostic: Invalid component macro, expected `component!(name: "<component_name>", storage: "<storage_name>", event: "<event_name>");`
 --> [file path]:[line number]
    component!(name: ReentrancyGuard, storage: ReentrancyGuard);

The ReentrancyGuard component is imported and defined as follows:

#[starknet::component]
mod ReentrancyGuard {
    // ... (definition)
}

I've tried using the component! macro in various ways, including:

  • component!(name: ReentrancyGuard, storage: ReentrancyGuard);
  • component!(name: ReentrancyGuard, storage: Storage);

None of these variations resolve the issue. The error message suggests that an event parameter is also expected in the macro, which seems unusual for a ReentrancyGuard component.

Here is how I am using the component and declaring it in the contract:

use openzeppelin::security::reentrancyguard::ReentrancyGuard;
// Declare the ReentrancyGuard component
component!(path: ReentrancyGuard, storage: Storage);
...

Questions:

  1. How should the component! macro be correctly used for declaring the ReentrancyGuard component in this context?
  2. Why does the error message indicate the need for an event parameter in the component! macro?
  3. I've noticed there's no specific documentation for the ReentrancyGuard in the current version (0.8.0-beta.0) of OpenZeppelin Contracts for Cairo. Is there any available documentation or example that could guide me in the correct implementation of this component?

Any assistance or guidance on this matter would be greatly appreciated. Here is a link to the contract with the issue:
https://github.com/henryf10h/reflect_cairo/blob/main/src/contracts/ERC20wrapper_V0.cairo

Thank you in advance for your help!

Hey @henryf10h,

  1. The component! macro should also include event. Even if there’s no event (like in ReentrancyGuardComponent), the compiler is still going to create an event enum inside the component module.
  2. As stated above, integrating a component requires this.
  3. We have documentation for our Security components which includes ReentrancyGuardComponent, we just haven’t released it yet. The current version is beta because we’re missing some components and documentation. To get a better understanding of components, I recommend reading the Starknet Shamans post on components: https://community.starknet.io/t/cairo-components/101136

Here's a template that might help you with your contract. I hope this helps!

#[starknet::contract]
mod MyContract {
    use openzeppelin::security::reentrancyguard::ReentrancyGuard as ReentrancyGuardComponent;
    // `ReentrancyGuard` will change to `ReentrancyGuardComponent` in the next release

    component!(
        path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent
    );

    impl ReentrancyGuardInternalImpl = ReentrancyGuardComponent::InternalImpl<ContractState>;

    #[storage]
    struct Storage {
        #[substorage(v0)]
        reentrancy_guard: ReentrancyGuardComponent::Storage
    }

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

    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.reentrancy_guard.start();

        // function body

        self.reentrancy_guard.end();
    }
}
3 Likes

Thank you @andrewfleming. It worked!

2 Likes

Excellent to hear! My pleasure :slight_smile:

1 Like