Extending Contracts - OpenZeppelin Docs       

Extending Contracts
===================

Most of the OpenZeppelin Contracts are expected to be used via [inheritance](https://solidity.readthedocs.io/en/latest/contracts.html#inheritance)
: you will _inherit_ from them when writing your own contracts.

This is the commonly found `is` syntax, like in `contract MyToken is ERC20`.

|     |     |
| --- | --- |
|     | Unlike `contract`s, Solidity `library`s are not inherited from and instead rely on the [`using for`](https://solidity.readthedocs.io/en/latest/contracts.html#using-for)<br> syntax.<br><br>OpenZeppelin Contracts has some `library`s: most are in the [Utils](api/utils)<br> directory. |

[](#overriding)
Overriding
--------------------------

Inheritance is often used to add the parent contract’s functionality to your own contract, but that’s not all it can do. You can also _change_ how some parts of the parent behave using _overrides_.

For example, imagine you want to change [`AccessControl`](api/access#AccessControl)
 so that [`revokeRole`](api/access#AccessControl-revokeRole-bytes32-address-)
 can no longer be called. This can be achieved using overrides:

    // contracts/ModifiedAccessControl.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/access/AccessControl.sol";
    
    contract ModifiedAccessControl is AccessControl {
        // Override the revokeRole function
        function revokeRole(bytes32, address) public override {
            revert("ModifiedAccessControl: cannot revoke roles");
        }
    }

The old `revokeRole` is then replaced by our override, and any calls to it will immediately revert. We cannot _remove_ the function from the contract, but reverting on all calls is good enough.

### [](#calling_super)
Calling `super`

Sometimes you want to _extend_ a parent’s behavior, instead of outright changing it to something else. This is where `super` comes in.

The `super` keyword will let you call functions defined in a parent contract, even if they are overridden. This mechanism can be used to add additional checks to a function, emit events, or otherwise add functionality as you see fit.

|     |     |
| --- | --- |
|     | For more information on how overrides work, head over to the [official Solidity documentation](https://solidity.readthedocs.io/en/latest/contracts.html#index-17)<br>. |

Here is a modified version of [`AccessControl`](api/access#AccessControl)
 where [`revokeRole`](api/access#AccessControl-revokeRole-bytes32-address-)
 cannot be used to revoke the `DEFAULT_ADMIN_ROLE`:

    // contracts/ModifiedAccessControl.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/access/AccessControl.sol";
    
    contract ModifiedAccessControl is AccessControl {
        function revokeRole(bytes32 role, address account) public override {
            require(
                role != DEFAULT_ADMIN_ROLE,
                "ModifiedAccessControl: cannot revoke default admin role"
            );
    
            super.revokeRole(role, account);
        }
    }

The `super.revokeRole` statement at the end will invoke `AccessControl`'s original version of `revokeRole`, the same code that would’ve run if there were no overrides in place.

|     |     |
| --- | --- |
|     | As of v3.0.0, `view` functions are not `virtual` in OpenZeppelin, and therefore cannot be overridden. We’re considering [lifting this restriction](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2154)<br> in an upcoming release. Let us know if this is something you care about! |

[](#using-hooks)
Using Hooks
----------------------------

Sometimes, in order to extend a parent contract you will need to override multiple related functions, which leads to code duplication and increased likelihood of bugs.

For example, consider implementing safe [`ERC20`](api/token/ERC20#ERC20)
 transfers in the style of [`IERC721Receiver`](api/token/ERC721#IERC721Receiver)
. You may think overriding [`transfer`](api/token/ERC20#ERC20-transfer-address-uint256-)
 and [`transferFrom`](api/token/ERC20#ERC20-transferFrom-address-address-uint256-)
 would be enough, but what about [`_transfer`](api/token/ERC20#ERC20-_transfer-address-address-uint256-)
 and [`_mint`](api/token/ERC20#ERC20-_mint-address-uint256-)
? To prevent you from having to deal with these details, we introduced **hooks**.

Hooks are simply functions that are called before or after some action takes place. They provide a centralized point to _hook into_ and extend the original behavior.

Here’s how you would implement the `IERC721Receiver` pattern in `ERC20`, using the [`_beforeTokenTransfer`](api/token/ERC20#ERC20-_beforeTokenTransfer-address-address-uint256-)
 hook:

    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    
    contract ERC20WithSafeTransfer is ERC20 {
        function _beforeTokenTransfer(address from, address to, uint256 amount)
            internal virtual override
        {
            super._beforeTokenTransfer(from, to, amount);
    
            require(_validRecipient(to), "ERC20WithSafeTransfer: invalid recipient");
        }
    
        function _validRecipient(address to) private view returns (bool) {
            ...
        }
    
        ...
    }

Using hooks this way leads to cleaner and safer code, without having to rely on a deep understanding of the parent’s internals.

|     |     |
| --- | --- |
|     | Hooks are a new feature of OpenZeppelin Contracts v3.0.0, and we’re eager to learn how you plan to use them!<br><br>So far, the only available hook is `_beforeTransferHook`, in all of [`ERC20`](api/token/ERC20#ERC20-_beforeTokenTransfer-address-address-uint256-)<br>, [`ERC721`](api/token/ERC721#ERC721-_beforeTokenTransfer-address-address-uint256-)<br>, [`ERC777`](api/token/ERC777#ERC777-_beforeTokenTransfer-address-address-address-uint256-)<br> and [`ERC1155`](api/token/ERC1155#ERC1155-_beforeTokenTransfer-address-address-address-uint256---uint256---bytes-)<br>. If you have ideas for new hooks, let us know! |

### [](#rules_of_hooks)
Rules of Hooks

There’s a few guidelines you should follow when writing code that uses hooks in order to prevent issues. They are very simple, but do make sure you follow them:

1.  Whenever you override a parent’s hook, re-apply the `virtual` attribute to the hook. That will allow child contracts to add more functionality to the hook.
    
2.  **Always** call the parent’s hook in your override using `super`. This will make sure all hooks in the inheritance tree are called: contracts like [`ERC20Pausable`](api/token/ERC20#ERC20Pausable)
     rely on this behavior.
    

    contract MyToken is ERC20 {
        function _beforeTokenTransfer(address from, address to, uint256 amount)
            internal virtual override // Add virtual here!
        {
            super._beforeTokenTransfer(from, to, amount); // Call parent hook
            ...
        }
    }

That’s it! Enjoy simpler code using hooks!

[← Overview](/contracts/3.x/)

[Using with Upgrades →](/contracts/3.x/upgradeable)




 Extensibility - OpenZeppelin Docs       

Extensibility
=============

|     |     |
| --- | --- |
|     | Expect this pattern to evolve (as it has already done) or even disappear if [proper extensibility features](https://community.starknet.io/t/contract-extensibility-pattern/210/11?u=martriay)<br> are implemented into Cairo. |

*   [The extensibility problem](#the_extensibility_problem)
    
*   [The pattern ™️](#the_pattern)
    
    *   [Libraries](#libraries)
        
    *   [Contracts](#contracts)
        
    
*   [Presets](#presets)
    
*   [Function names and coding style](#function_names_and_coding_style)
    
*   [Emulating hooks](#emulating_hooks)
    

[](#the_extensibility_problem)
The extensibility problem
--------------------------------------------------------

Smart contract development is a critical task. As with all software development, it is error prone; but unlike most scenarios, a bug can result in major losses for organizations as well as individuals. Therefore writing complex smart contracts is a delicate task.

One of the best approaches to minimize introducing bugs is to reuse existing, battle-tested code, a.k.a. using libraries. But code reutilization in StarkNet’s smart contracts is not easy:

*   Cairo has no explicit smart contract extension mechanisms such as inheritance or composability
    
*   Using imports for modularity can result in clashes (more so given that arguments are not part of the selector), and lack of overrides or aliasing leaves no way to resolve them
    
*   Any `@external` function defined in an imported module will be automatically re-exposed by the importer (i.e. the smart contract)
    

To overcome these problems, this project builds on the following guidelines™.

[](#the_pattern)
The pattern
----------------------------

The idea is to have two types of Cairo modules: libraries and contracts. Libraries define reusable logic and storage variables which can then be extended and exposed by contracts. Contracts can be deployed, libraries cannot.

To minimize risk, boilerplate, and avoid function naming clashes, we follow these rules:

### [](#libraries)
Libraries

Considering the following types of functions:

*   `private`: private to a library, not meant to be used outside the module or imported
    
*   `public`: part of the public API of a library
    
*   `internal`: subset of `public` that is either discouraged or potentially unsafe (e.g. `_transfer` on ERC20)
    
*   `external`: subset of `public` that is ready to be exported as-is by contracts (e.g. `transfer` on ERC20)
    
*   `storage`: storage variable functions
    

Then:

*   Must implement `public` and `external` functions under a namespace
    
*   Must implement `private` functions outside the namespace to avoid exposing them
    
*   Must prefix `internal` functions with an underscore (e.g. `ERC20._mint`)
    
*   Must not prefix `external` functions with an underscore (e.g. `ERC20.transfer`)
    
*   Must prefix `storage` functions with the name of the namespace to prevent clashing with other libraries (e.g. `ERC20balances`)
    
*   Must not implement any `@external`, `@view`, or `@constructor` functions
    
*   Can implement initializers (never as `@constructor` or `@external`)
    
*   Must not call initializers on any function
    

### [](#contracts)
Contracts

*   Can import from libraries
    
*   Should implement `@external` functions if needed
    
*   Should implement a `@constructor` function that calls initializers
    
*   Must not call initializers in any function beside the constructor
    

Note that since initializers will never be marked as `@external` and they won’t be called from anywhere but the constructor, there’s no risk of re-initialization after deployment. It’s up to the library developers not to make initializers interdependent to avoid weird dependency paths that may lead to double construction of libraries.

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets are:

*   [Account](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/Account.cairo)
    
*   [ERC165](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ERC165.cairo)
    
*   [ERC20Mintable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
    
*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   [ERC20](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
    
*   [ERC721MintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    
*   [ERC721EnumerableMintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/enumerable/presets/ERC721EnumerableMintableBurnable.cairo)
    

[](#function_names_and_coding_style)
Function names and coding style
--------------------------------------------------------------------

*   Following Cairo’s programming style, we use `snake_case` for library APIs (e.g. `ERC20.transfer_from`, `ERC721.safe_transfer_from`).
    
*   But for standard EVM ecosystem compatibility, we implement external functions in contracts using `camelCase` (e.g. `transferFrom` in a ERC20 contract).
    
*   Guard functions such as the so-called "only owner" are prefixed with `assert_` (e.g. `Ownable.assert_only_owner`).
    

[](#emulating_hooks)
Emulating hooks
------------------------------------

Unlike the Solidity version of [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts)
, this library does not implement [hooks](https://docs.openzeppelin.com/contracts/4.x/extending-contracts#using-hooks)
. The main reason being that Cairo does not support overriding functions.

This is what a hook looks like in Solidity:

    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }

Instead, the extensibility pattern allows us to simply extend the library implementation of a function (namely `transfer`) by adding lines before or after calling it. This way, we can get away with:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()
        ERC20.transfer(recipient, amount)
        return (TRUE)
    end

[← Overview](/contracts-cairo/0.3.0/)

[Proxies and Upgrades →](/contracts-cairo/0.3.0/proxies)




 Access Control - OpenZeppelin Docs       

Access Control
==============

Access control—that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore **critical** to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7)
.

[](#ownership-and-ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of _ownership_: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin provides [`Ownable`](api/access#Ownable)
 for implementing ownership in your contracts.

    // contracts/MyContract.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/access/Ownable.sol";
    
    contract MyContract is Ownable {
        function normalThing() public {
            // anyone can call this normalThing()
        }
    
        function specialThing() public onlyOwner {
            // only the owner can call specialThing()!
        }
    }

By default, the [`owner`](api/access#Ownable-owner--)
 of an `Ownable` contract is the account that deployed it, which is usually exactly what you want.

Ownable also lets you:

*   [`transferOwnership`](api/access#Ownable-transferOwnership-address-)
     from the owner account to a new one, and
    
*   [`renounceOwnership`](api/access#Ownable-renounceOwnership--)
     for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `onlyOwner` will no longer be callable! |

Note that **a contract can also be the owner of another one**! This opens the door to using, for example, a [Gnosis Multisig](https://github.com/gnosis/MultiSigWallet)
 or [Gnosis Safe](https://safe.gnosis.io)
, an [Aragon DAO](https://aragon.org)
, an [ERC725/uPort](https://www.uport.me)
 identity contract, or a totally custom contract that _you_ create.

In this way you can use _composability_ to add additional layers of access control complexity to your contracts. Instead of having a single regular Ethereum account (Externally Owned Account, or EOA) as the owner, you could use a 2-of-3 multisig run by your project leads, for example. Prominent projects in the space, such as [MakerDAO](https://makerdao.com)
, use systems similar to this one.

[](#role-based-access-control)
Role-Based Access Control
--------------------------------------------------------

While the simplicity of _ownership_ can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [_Role-Based Access Control (RBAC)_](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple _roles_, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using `onlyOwner`. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#using-access-control)
Using `AccessControl`

OpenZeppelin Contracts provides [`AccessControl`](api/access#AccessControl)
 for implementing role-based access control. Its usage is straightforward: for each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role.

Here’s a simple example of using `AccessControl` in an [`ERC20` token](tokens#ERC20)
 to define a 'minter' role, which allows accounts that have it create new tokens:

    // contracts/MyToken.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/access/AccessControl.sol";
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    
    contract MyToken is ERC20, AccessControl {
        // Create a new role identifier for the minter role
        bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    
        constructor(address minter) public ERC20("MyToken", "TKN") {
            // Grant the minter role to a specified account
            _setupRole(MINTER_ROLE, minter);
        }
    
        function mint(address to, uint256 amount) public {
            // Check that the calling account has the minter role
            require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
            _mint(to, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [`AccessControl`](api/access#AccessControl)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with `Ownable`. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    // contracts/MyToken.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/access/AccessControl.sol";
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    
    contract MyToken is ERC20, AccessControl {
        bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
        bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    
        constructor(address minter, address burner) public ERC20("MyToken", "TKN") {
            _setupRole(MINTER_ROLE, minter);
            _setupRole(BURNER_ROLE, burner);
        }
    
        function mint(address to, uint256 amount) public {
            require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
            _mint(to, amount);
        }
    
        function burn(address from, uint256 amount) public {
            require(hasRole(BURNER_ROLE, msg.sender), "Caller is not a burner");
            _burn(from, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler _ownership_ approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting-and-revoking)
Granting and Revoking Roles

The ERC20 token example above uses `_setupRole`, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `hasRole` check pass. To grant and revoke roles dynamically, you will need help from the _role’s admin_.

Every role has an associated admin role, which grants permission to call the `grantRole` and `revokeRole` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_setRoleAdmin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    // contracts/MyToken.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/access/AccessControl.sol";
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    
    contract MyToken is ERC20, AccessControl {
        bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
        bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    
        constructor() public ERC20("MyToken", "TKN") {
            // Grant the contract deployer the default admin role: it will be able
            // to grant and revoke any roles
            _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        }
    
        function mint(address to, uint256 amount) public {
            require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
            _mint(to, amount);
        }
    
        function burn(address from, uint256 amount) public {
            require(hasRole(BURNER_ROLE, msg.sender), "Caller is not a burner");
            _burn(from, amount);
        }
    }

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and _that_ role was granted to `msg.sender`, that same account can call `grantRole` to give minting or burning permission, and `revokeRole` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#querying-privileged-accounts)
Querying Privileged Accounts

Because accounts might [grant and revoke roles](#granting-and-revoking)
 dynamically, it is not always possible to determine which accounts hold a particular role. This is important as it allows to prove certain properties about a system, such as that an administrative account is a multisig or a DAO, or that a certain role has been removed from all users, effectively disabling any associated functionality.

Under the hood, `AccessControl` uses `EnumerableSet`, a more powerful variant of Solidity’s `mapping` type, which allows for key enumeration. `getRoleMemberCount` can be used to retrieve the number of accounts that have a particular role, and `getRoleMember` can then be called to get the address of each of these accounts.

    const minterCount = await myToken.getRoleMemberCount(MINTER_ROLE);
    
    const members = [];
    for (let i = 0; i < minterCount; ++i) {
        members.push(await myToken.getRoleMember(MINTER_ROLE, i));
    }

[](#delayed_operation)
Delayed operation
----------------------------------------

Access control is essential to prevent unauthorized access to critical functions. These functions may be used to mint tokens, freeze transfers or perform an upgrade that completely changes the smart contract logic. While [`Ownable`](api/access#Ownable)
 and [`AccessControl`](api/access#AccessControl)
 can prevent unauthorized access, they do not address the issue of a misbehaving administrator attacking their own system to the prejudice of their users.

This is the issue the [`TimelockControler`](api/access#TimelockController)
 is addressing.

The [`TimelockControler`](api/access#TimelockController)
 is a proxy that is governed by proposers and executors. When set as the owner/admin/controller of a smart contract, it ensures that whichever maintenance operation is ordered by the proposers is subject to a delay. This delay protects the users of the smart contract by giving them time to review the maintenance operation and exit the system if they consider it is in their best interest to do so.

### [](#using_timelockcontroler)
Using `TimelockControler`

By default, the address that deployed the [`TimelockControler`](api/access#TimelockController)
 gets administration privileges over the timelock. This role grants the right to assign proposers, executors, and other administrators.

The first step in configuring the [`TimelockControler`](api/access#TimelockController)
 is to assign at least one proposer and one executor. These can be assigned during construction or later by anyone with the administrator role. These roles are not exclusive, meaning an account can have both roles.

Roles are managed using the [`AccessControl`](api/access#AccessControl)
 interface and the `bytes32` values for each role are accessible through the `ADMIN_ROLE`, `PROPOSER_ROLE` and `EXECUTOR_ROLE` constants.

There is an additional feature built on top of `AccessControl`: giving the proposer or executor role to `address(0)` opens access to anyone. This feature, while potentially useful for testing and in some cases for the executor role, is dangerous and should be used with caution.

At this point, with both a proposer and an executor assigned, the timelock can perform operations.

An optional next step is for the deployer to renounce its administrative privileges and leave the timelock self-administered. If the deployer decides to do so, all further maintenance, including assigning new proposers/schedulers or changing the timelock duration will have to follow the timelock workflow. This links the governance of the timelock to the governance of contracts attached to the timelock, and enforce a delay on timelock maintenance operations.

|     |     |
| --- | --- |
|     | If the deployer renounces administrative rights in favour of timelock itself, assigning new proposers or executors will require a timelocked operation. This means that if the accounts in charge of any of these two roles become unavailable, then the entire contract (and any contract it controls) becomes locked indefinitely. |

With both the proposer and executor roles assigned and the timelock in charge of its own administration, you can now transfer the ownership/control of any contract to the timelock.

|     |     |
| --- | --- |
|     | A recommended configuration is to grant both roles to a secure governance contract such as a DAO or a multisig, and to additionally grant the executor role to a few EOAs held by people in charge of helping with the maintenance operations. These wallets cannot take over control of the timelock but they can help smoothen the workflow. |

### [](#minimum_delay)
Minimum delay

Operations executed by the [`TimelockControler`](api/access#TimelockController)
 are not subject to a fixed delay but rather a minimum delay. Some major updates might call for a longer delay. For example, if a delay of just a few days might be sufficient for users to audit a minting operation, it makes sense to use a delay of a few weeks, or even a few months, when scheduling a smart contract upgrade.

The minimum delay (accessible through the [`getMinDelay`](api/access#TimelockController-getMinDelay--)
 method) can be updated by calling the [`updateDelay`](api/access#TimelockController-updateDelay-uint256-)
 function. Bear in mind that access to this function is only accessible by the timelock itself, meaning this maintenance operation has to go through the timelock itself.

[← Releases & Stability](/contracts/3.x/releases-stability)

[Tokens →](/contracts/3.x/tokens)




 Creating ERC20 Supply - OpenZeppelin Docs       

Creating ERC20 Supply
=====================

In this guide you will learn how to create an ERC20 token with a custom supply mechanism. We will showcase two idiomatic ways to use OpenZeppelin Contracts for this purpose that you will be able to apply to your smart contract development practice.

The standard interface implemented by tokens built on Ethereum is called ERC20, and Contracts includes a widely used implementation of it: the aptly named [`ERC20`](api/token/ERC20)
 contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try to deploy an instance of `ERC20` as-is it will be quite literally useless…​ it will have no supply! What use is a token with no supply?

The way that supply is created is not defined in the ERC20 document. Every token is free to experiment with their own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.

[](#fixed-supply)
Fixed Supply
------------------------------

Let’s say we want a token with a fixed supply of 1000, initially allocated to the account that deploys the contract. If you’ve used Contracts v1, you may have written code like the following:

    contract ERC20FixedSupply is ERC20 {
        constructor() public {
            totalSupply += 1000;
            balances[msg.sender] += 1000;
        }
    }

Starting with Contracts v2 this pattern is not only discouraged, but disallowed. The variables `totalSupply` and `balances` are now private implementation details of `ERC20`, and you can’t directly write to them. Instead, there is an internal [`_mint`](api/token/ERC20#ERC20-_mint-address-uint256-)
 function that will do exactly this:

    contract ERC20FixedSupply is ERC20 {
        constructor() public ERC20("Fixed", "FIX") {
            _mint(msg.sender, 1000);
        }
    }

Encapsulating state like this makes it safer to extend contracts. For instance, in the first example we had to manually keep the `totalSupply` in sync with the modified balances, which is easy to forget. In fact, we omitted something else that is also easily forgotten: the `Transfer` event that is required by the standard, and which is relied on by some clients. The second example does not have this bug, because the internal `_mint` function takes care of it.

[](#rewarding-miners)
Rewarding Miners
--------------------------------------

The internal [`_mint`](api/token/ERC20#ERC20-_mint-address-uint256-)
 function is the key building block that allows us to write ERC20 extensions that implement a supply mechanism.

The mechanism we will implement is a token reward for the miners that produce Ethereum blocks. In Solidity we can access the address of the current block’s miner in the global variable `block.coinbase`. We will mint a token reward to this address whenever someone calls the function `mintMinerReward()` on our token. The mechanism may sound silly, but you never know what kind of dynamic this might result in, and it’s worth analyzing and experimenting with!

    contract ERC20WithMinerReward is ERC20 {
        constructor() public ERC20("Reward", "RWD") {}
    
        function mintMinerReward() public {
            _mint(block.coinbase, 1000);
        }
    }

As we can see, `_mint` makes it super easy to do this correctly.

[](#modularizing-the-mechanism)
Modularizing the Mechanism
----------------------------------------------------------

There is one supply mechanism already included in Contracts: `ERC20PresetMinterPauser`. This is a generic mechanism in which a set of accounts is assigned the `minter` role, granting them the permission to call a `mint` function, an external version of `_mint`.

This can be used for centralized minting, where an externally owned account (i.e. someone with a pair of cryptographic keys) decides how much supply to create and for whom. There are very legitimate use cases for this mechanism, such as [traditional asset-backed stablecoins](https://medium.com/reserve-currency/why-another-stablecoin-866f774afede#3aea)
.

The accounts with the minter role don’t need to be externally owned, though, and can just as well be smart contracts that implement a trustless mechanism. We can in fact implement the same behavior as the previous section.

    contract MinerRewardMinter {
        ERC20PresetMinterPauser _token;
    
        constructor(ERC20PresetMinterPauser token) public {
            _token = token;
        }
    
        function mintMinerReward() public {
            _token.mint(block.coinbase, 1000);
        }
    }

This contract, when initialized with an `ERC20PresetMinterPauser` instance, and granted the `minter` role for that contract, will result in exactly the same behavior implemented in the previous section. What is interesting about using `ERC20PresetMinterPauser` is that we can easily combine multiple supply mechanisms by assigning the role to multiple contracts, and moreover that we can do this dynamically.

|     |     |
| --- | --- |
|     | To learn more about roles and permissioned systems, head to our [Access Control guide](access-control)<br>. |

[](#automating-the-reward)
Automating the Reward
------------------------------------------------

So far our supply mechanisms were triggered manually, but `ERC20` also allows us to extend the core functionality of the token through the [`_beforeTokenTransfer`](api/token/ERC20#ERC20-_beforeTokenTransfer-address-address-uint256-)
 hook (see [Using Hooks](extending-contracts#using-hooks)
).

Adding to the supply mechanism from previous sections, we can use this hook to mint a miner reward for every token transfer that is included in the blockchain.

    contract ERC20WithAutoMinerReward is ERC20 {
        constructor() public ERC20("Reward", "RWD") {}
    
        function _mintMinerReward() internal {
            _mint(block.coinbase, 1000);
        }
    
        function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual override {
            _mintMinerReward();
            super._beforeTokenTransfer(from, to, value);
        }
    }

[](#wrapping-up)
Wrapping Up
----------------------------

We’ve seen two ways to implement ERC20 supply mechanisms: internally through `_mint`, and externally through `ERC20PresetMinterPauser`. Hopefully this has helped you understand how to use OpenZeppelin and some of the design principles behind it, and you can apply them to your own smart contracts.

[← ERC20](/contracts/3.x/erc20)

[ERC721 →](/contracts/3.x/erc721)




 New Releases and API Stability - OpenZeppelin Docs       

New Releases and API Stability
==============================

Developing smart contracts is hard, and a conservative approach towards dependencies is sometimes favored. However, it is also very important to stay on top of new releases: these may include bug fixes, or deprecate old patterns in favor of newer and better practices.

Here we describe when you should expect new releases to come out, and how this affects you as a user of OpenZeppelin Contracts.

[](#release-schedule)
Release Schedule
--------------------------------------

OpenZeppelin Contracts follows a [semantic versioning scheme](#versioning-scheme)
.

### [](#minor-releases)
Minor Releases

OpenZeppelin Contracts aims for a new minor release every 1 or 2 months.

At the beginning of the release cycle we decide which issues we want to prioritize, and assign them to [a milestone on GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts/milestones)
. During the next five weeks, they are worked on and fixed.

Once the milestone is complete, we publish a feature-frozen release candidate. The purpose of the release candidate is to have a period where the community can review the new code before the actual release. If important problems are discovered, several more release candidates may be required. After a week of no more changes to the release candidate, the new version is published.

### [](#major-releases)
Major Releases

After several months or a year a new major release may come out. These are not scheduled, but will be based on the need to release breaking changes such as a redesign of a core feature of the library (e.g. [access control](https://github.com/OpenZeppelin/openzeppelin-contracts/pulls/2112)
 in 3.0). Since we value stability, we aim for these to happen infrequently (expect no less than six months between majors). However, we may be forced to release one when there are big changes to the Solidity language.

[](#api-stability)
API Stability
--------------------------------

On the [OpenZeppelin 2.0 release](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v2.0.0)
, we committed ourselves to keeping a stable API. We aim to more precisely define what we understand by _stable_ and _API_ here, so users of the library can understand these guarantees and be confident their project won’t break unexpectedly.

In a nutshell, the API being stable means _if your project is working today, it will continue to do so_. New contracts and features will be added in minor releases, but only in a backwards compatible way.

### [](#versioning-scheme)
Versioning Scheme

We follow [SemVer](https://semver.org/)
, which means API breakage may occur between major releases (which [don’t happen very often](#release-schedule)
).

### [](#solidity-functions)
Solidity Functions

While the internal implementation of functions may change, their semantics and signature will remain the same. The domain of their arguments will not be less restrictive (e.g. if transferring a value of 0 is disallowed, it will remain disallowed), nor will general state restrictions be lifted (e.g. `whenPaused` modifiers).

If new functions are added to a contract, it will be in a backwards-compatible way: their usage won’t be mandatory, and they won’t extend functionality in ways that may foreseeable break an application (e.g. [an `internal` method may be added to make it easier to retrieve information that was already available](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/1512)
).

#### [](#internal)
`internal`

This extends not only to `external` and `public` functions, but also `internal` ones: many contracts are meant to be used by inheriting them (e.g. `Pausable`, `PullPayment`, the different `Roles` contracts), and are therefore used by calling these functions. Similarly, since all OpenZeppelin Contracts state variables are `private`, they can only be accessed this way (e.g. to create new `ERC20` tokens, instead of manually modifying `totalSupply` and `balances`, `_mint` should be called).

`private` functions have no guarantees on their behavior, usage, or existence.

Finally, sometimes language limitations will force us to e.g. make `internal` a function that should be `private` in order to implement features the way we want to. These cases will be well documented, and the normal stability guarantees won’t apply.

### [](#libraries)
Libraries

Some of our Solidity libraries use `struct`s to handle internal data that should not be accessed directly (e.g. `Roles`). There’s an [open issue](https://github.com/ethereum/solidity/issues/4637)
 in the Solidity repository requesting a language feature to prevent said access, but it looks like it won’t be implemented any time soon. Because of this, we will use leading underscores and mark said `struct` s to make it clear to the user that its contents and layout are _not_ part of the API.

### [](#events)
Events

No events will be removed, and their arguments won’t be changed in any way. New events may be added in later versions, and existing events may be emitted under new, reasonable circumstances (e.g. [from 2.1 on, `ERC20` also emits `Approval` on `transferFrom` calls](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/707)
).

### [](#gas-costs)
Gas Costs

While attempts will generally be made to lower the gas costs of working with OpenZeppelin Contracts, there are no guarantees regarding this. In particular, users should not assume gas costs will not increase when upgrading library versions.

### [](#bugfixes)
Bug Fixes

The API stability guarantees may need to be broken in order to fix a bug, and we will do so. This decision won’t be made lightly however, and all options will be explored to make the change as non-disruptive as possible. When sufficient, contracts or functions which may result in unsafe behavior will be deprecated instead of removed (e.g. [#1543](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1543)
 and [#1550](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1550)
).

### [](#solidity-compiler-version)
Solidity Compiler Version

Starting on version 0.5.0, the Solidity team switched to a faster release cycle, with minor releases every few weeks (v0.5.0 was released on November 2018, and v0.5.5 on March 2019), and major, breaking-change releases every couple of months (with v0.6.0 released on December 2019 and v0.7.0 on July 2020). Including the compiler version in OpenZeppelin Contract’s stability guarantees would therefore force the library to either stick to old compilers, or release frequent major updates simply to keep up with newer Solidity releases.

Because of this, **the minimum required Solidity compiler version is not part of the stability guarantees**, and users may be required to upgrade their compiler when using newer versions of Contracts. Bug fixes will still be backported to older library releases so that all versions currently in use receive these updates.

You can read more about the rationale behind this, the other options we considered and why we went down this path [here](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/1498#issuecomment-449191611)
.

[← Using with Upgrades](/contracts/3.x/upgradeable)

[Access Control →](/contracts/3.x/access-control)









 ERC721 - OpenZeppelin Docs       

ERC721
======

We’ve discussed how you can make a _fungible_ token using [ERC20](erc20)
, but what if not all tokens are alike? This comes up in situations like **real estate** or **collectibles**, where some items are valued more than others, due to their usefulness, rarity, etc. ERC721 is a standard for representing ownership of [_non-fungible_ tokens](tokens#different-kinds-of-tokens)
, that is, where each token is unique.

ERC721 is a more complex standard than ERC20, with multiple optional extensions, and is split across a number of contracts. The OpenZeppelin Contracts provide flexibility regarding how these are combined, along with custom useful extensions. Check out the [API Reference](api/token/ERC721)
 to learn more about these.

[](#constructing_an_erc721_token_contract)
Constructing an ERC721 Token Contract
--------------------------------------------------------------------------------

We’ll use ERC721 to track items in our game, which will each have their own unique attributes. Whenever one is to be awarded to a player, it will be minted and sent to them. Players are free to keep their token or trade it with other people as they see fit, as they would any other asset on the blockchain! Please note any account can call `awardItem` to mint items. To restrict what accounts can mint items we can add [Access Control](access-control)
.

Here’s what a contract for tokenized items might look like:

    // contracts/GameItem.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
    import "@openzeppelin/contracts/utils/Counters.sol";
    
    contract GameItem is ERC721 {
        using Counters for Counters.Counter;
        Counters.Counter private _tokenIds;
    
        constructor() public ERC721("GameItem", "ITM") {}
    
        function awardItem(address player, string memory tokenURI)
            public
            returns (uint256)
        {
            _tokenIds.increment();
    
            uint256 newItemId = _tokenIds.current();
            _mint(player, newItemId);
            _setTokenURI(newItemId, tokenURI);
    
            return newItemId;
        }
    }

The [`ERC721`](api/token/ERC721#ERC721)
 contract includes all standard extensions ([`IERC721Metadata`](api/token/ERC721#IERC721Metadata)
 and [`IERC721Enumerable`](api/token/ERC721#IERC721Enumerable)
). That’s where the [`_setTokenURI`](api/token/ERC721#ERC721-_setTokenURI-uint256-string-)
 method comes from: we use it to store an item’s metadata.

Also note that, unlike ERC20, ERC721 lacks a `decimals` field, since each token is distinct and cannot be partitioned.

New items can be created:

    > gameItem.awardItem(playerAddress, "https://game.example/item-id-8u5h2m.json")
    Transaction successful. Transaction hash: 0x...
    Events emitted:
     - Transfer(0x0000000000000000000000000000000000000000, playerAddress, 7)

And the owner and metadata of each item queried:

    > gameItem.ownerOf(7)
    playerAddress
    > gameItem.tokenURI(7)
    "https://game.example/item-id-8u5h2m.json"

This `tokenURI` should resolve to a JSON document that might look something like:

    {
        "name": "Thor's hammer",
        "description": "Mjölnir, the legendary hammer of the Norse god of thunder.",
        "image": "https://game.example/item-id-8u5h2m.png",
        "strength": 20
    }

For more information about the `tokenURI` metadata JSON Schema, check out the [ERC721 specification](https://eips.ethereum.org/EIPS/eip-721)
.

|     |     |
| --- | --- |
|     | you’ll notice that the item’s information is included in the metadata, but that information isn’t on-chain! So a game developer could change the underlying metadata, changing the rules of the game! If you’d like to put all item information on-chain, you can extend ERC721 to do so (though it will be rather costly). You could also leverage IPFS to store the tokenURI information, but these techniques are out of the scope of this overview guide. |

[](#Presets)
Preset ERC721 contract
-----------------------------------

A preset ERC721 is available, [`ERC721PresetMinterPauserAutoId`](api/presets#ERC721PresetMinterPauserAutoId)
. It is preset to allow for token minting (create) with token ID and URI auto generation, stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses [Access Control](access-control)
 to control access to the minting and pausing functionality. The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.

This contract is ready to deploy without having to write any Solidity code. It can be used as-is for quick prototyping and testing, but is also suitable for production environments.

[← Creating Supply](/contracts/3.x/erc20-supply)

[ERC777 →](/contracts/3.x/erc777)




 Proxies - OpenZeppelin Docs       

Proxies
=======

|     |     |
| --- | --- |
|     | Expect rapid iteration as this pattern matures and more patterns potentially emerge. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Solidity/Cairo upgrades comparison](#soliditycairo_upgrades_comparison)
    
    *   [Constructors](#constructors)
        
    *   [Storage](#storage)
        
    
*   [Proxies](#proxies2)
    
    *   [Proxy contract](#proxy_contract)
        
    *   [Implementation contract](#implementation_contract)
        
    
*   [Upgrades library API](#upgrades_library_api)
    
    *   [Methods](#methods)
        
    *   [Events](#events)
        
    
*   [Using proxies](#using_proxies)
    
    *   [Contract upgrades](#contract_upgrades)
        
    *   [Declaring contracts](#declaring_contracts)
        
    *   [Testing method calls](#testing_method_calls)
        
    
*   [Presets](#presets)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  declare an implementation [contract class](https://starknet.io/docs/hello_starknet/intro.html#declare-the-contract-on-the-starknet-testnet)
    
2.  deploy proxy contract with the implementation contract’s class hash set in the proxy’s constructor calldata
    
3.  initialize the implementation contract by sending a call to the proxy contract. This will redirect the call to the implementation contract class and behave like the implementation contract’s constructor
    

In Python, this would look as follows:

        # declare implementation contract
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation contract class hash\
            ]
        )
    
        # users should only interact with the proxy contract
        await signer.send_transaction(
            account, PROXY.contract_address, 'initializer', [\
                proxy_admin\
            ]
        )

[](#soliditycairo_upgrades_comparison)
Solidity/Cairo upgrades comparison
-------------------------------------------------------------------------

### [](#constructors)
Constructors

OpenZeppelin Contracts for Solidity requires the use of an alternative library for upgradeable contracts. Consider that in Solidity constructors are not part of the deployed contract’s runtime bytecode; rather, a constructor’s logic is executed only once when the contract instance is deployed and then discarded. This is why proxies can’t imitate the construction of its implementation, therefore requiring a different initialization mechanism.

The constructor problem in upgradeable contracts is resolved by the use of initializer methods. Initializer methods are essentially regular methods that execute the logic that would have been in the constructor. Care needs to be exercised with initializers to ensure they can only be called once. Thus, OpenZeppelin offers an [upgradeable contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
 where much of this process is abstracted away. See OpenZeppelin’s [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)
 for more info.

The Cairo programming language does not support inheritance. Instead, Cairo contracts follow the [Extensibility Pattern](extensibility)
 which already uses initializer methods to mimic constructors. Upgradeable contracts do not, therefore, require a separate library with refactored constructor logic.

### [](#storage)
Storage

OpenZeppelin’s alternative Upgrades library also implements [unstructured storage](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies)
 for its upgradeable contracts. The basic idea behind unstructured storage is to pseudo-randomize the storage structure of the upgradeable contract so it’s based on variable names instead of declaration order, which makes the chances of storage collision during an upgrade extremely unlikely.

The StarkNet compiler, meanwhile, already creates pseudo-random storage addresses by hashing the storage variable names (and keys in mappings) by default. In other words, StarkNet already uses unstructured storage and does not need a second library to modify how storage is set. See StarkNet’s [Contracts Storage documentation](https://starknet.io/documentation/contracts/#contracts_storage)
 for more information.

[](#proxies2)
Proxies
---------------------

A proxy contract is a contract that delegates function calls to another contract. This type of pattern decouples state and logic. Proxy contracts store the state and redirect function calls to an implementation contract that handles the logic. This allows for different patterns such as upgrades, where implementation contracts can change but the proxy contract (and thus the state) does not; as well as deploying multiple proxy instances pointing to the same implementation. This can be useful to deploy many contracts with identical logic but unique initialization data.

In the case of contract upgrades, it is achieved by simply changing the proxy’s reference to the class hash of the declared implementation. This allows developers to add features, update logic, and fix bugs without touching the state or the contract address to interact with the application.

### [](#proxy_contract)
Proxy contract

The [Proxy contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/presets/Proxy.cairo)
 includes two core methods:

1.  The `__default__` method is a fallback method that redirects a function call and associated calldata to the implementation contract.
    
2.  The `__l1_default__` method is also a fallback method; however, it redirects the function call and associated calldata to a layer one contract. In order to invoke `__l1_default__`, the original function call must include the library function `send_message_to_l1`. See Cairo’s [Interacting with L1 contracts](https://www.cairo-lang.org/docs/hello_starknet/l1l2.html)
     for more information.
    

Since this proxy is designed to work both as an [UUPS-flavored upgrade proxy](https://eips.ethereum.org/EIPS/eip-1822)
 as well as a non-upgradeable proxy, it does not know how to handle its own state. Therefore it requires the implementation contract class to be declared beforehand, so its class hash can be passed to the Proxy on construction time.

When interacting with the contract, function calls should be sent by the user to the proxy. The proxy’s fallback function redirects the function call to the implementation contract to execute.

### [](#implementation_contract)
Implementation contract

The implementation contract, also known as the logic contract, receives the redirected function calls from the proxy contract. The implementation contract should follow the [Extensibility pattern](extensibility#the_pattern)
 and import directly from the [Proxy library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/library.cairo)
.

The implementation contract should:

*   import `Proxy` namespace
    
*   initialize the proxy immediately after contract deployment with `Proxy.initializer`.
    

If the implementation is upgradeable, it should:

*   include a method to upgrade the implementation (i.e. `upgrade`)
    
*   use access control to protect the contract’s upgradeability.
    

The implementation contract should NOT:

*   be deployed like a regular contract. Instead, the implementation contract should be declared (which creates a `DeclaredClass` containing its hash and abi)
    
*   set its initial state with a traditional constructor (decorated with `@constructor`). Instead, use an initializer method that invokes the Proxy `constructor`.
    

|     |     |
| --- | --- |
|     | The Proxy `constructor` includes a check the ensures the initializer can only be called once; however, `_set_implementation` does not include this check. It’s up to the developers to protect their implementation contract’s upgradeability with access controls such as [`assert_only_admin`](#assert_only_admin)<br>. |

For a full implementation contract example, please see:

*   [Proxiable implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ProxiableImplementation.cairo)
    

[](#upgrades_library_api)
Upgrades library API
----------------------------------------------

### [](#methods)
Methods

    func initializer(proxy_admin: felt):
    end
    
    func assert_only_admin():
    end
    
    func get_implementation_hash() -> (implementation: felt):
    end
    
    func get_admin() -> (admin: felt):
    end
    
    func _set_admin(new_admin: felt):
    end
    
    func _set_implementation_hash(new_implementation: felt):
    end

#### [](#initializer)
`initializer`

Initializes the proxy contract with an initial implementation.

Parameters:

    proxy_admin: felt

Returns: None.

#### [](#assert_only_admin)
`assert_only_admin`

Reverts if called by any account other than the admin.

Parameters: None.

Returns: None.

#### [](#get_implementation)
`get_implementation`

Returns the current implementation hash.

Parameters: None.

Returns:

    implementation: felt

#### [](#get_admin)
`get_admin`

Returns the current admin.

Parameters: None.

Returns:

    admin: felt

#### [](#set_admin)
`_set_admin`

Sets `new_admin` as the admin of the proxy contract.

Parameters:

    new_admin: felt

Returns: None.

#### [](#set_implementation_hash)
`_set_implementation_hash`

Sets `new_implementation` as the implementation’s contract class. This method is included in the proxy contract’s constructor and can be used to upgrade contracts.

Parameters:

    new_implementation: felt

Returns: None.

### [](#events)
Events

    func Upgraded(implementation: felt):
    end
    
    func AdminChanged(previousAdmin: felt, newAdmin: felt):
    end

#### [](#upgraded)
`Upgraded`

Emitted when a proxy contract sets a new implementation class hash.

Parameters:

    implementation: felt

#### [](#adminchanged)
`AdminChanged`

Emitted when the `admin` changes from `previousAdmin` to `newAdmin`.

Parameters:

    previousAdmin: felt
    newAdmin: felt

[](#using_proxies)
Using proxies
--------------------------------

### [](#contract_upgrades)
Contract upgrades

To upgrade a contract, the implementation contract should include an `upgrade` method that, when called, changes the reference to a new deployed contract like this:

        # declare first implementation
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation hash\
            ]
        )
    
        # declare implementation v2
        IMPLEMENTATION_V2 = await starknet.declare(
            "path/to/implementation_v2.cairo",
        )
    
        # call upgrade with the new implementation contract class hash
        await signer.send_transaction(
            account, PROXY.contract_address, 'upgrade', [\
                IMPLEMENTATION_V2.class_hash\
            ]
        )

For a full deployment and upgrade implementation, please see:

*   [Upgrades V1](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV1.cairo)
    
*   [Upgrades V2](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV2.cairo)
    

### [](#declaring_contracts)
Declaring contracts

StarkNet contracts come in two forms: contract classes and contract instances. Contract classes represent the uninstantiated, stateless code; whereas, contract instances are instantiated and include the state. Since the Proxy contract references the implementation contract by its class hash, declaring an implementation contract proves sufficient (as opposed to a full deployment). For more information on declaring classes, see [StarkNet’s documentation](https://starknet.io/docs/hello_starknet/intro.html#declare-contract)
.

### [](#testing_method_calls)
Testing method calls

As with most StarkNet contracts, interacting with a proxy contract requires an [account abstraction](accounts#quickstart)
. Due to limitations in the StarkNet testing framework, however, `@view` methods also require an account abstraction. This is only a requirement when testing. The differences in getter methods written in Python, for example, are as follows:

    # standard ERC20 call
    result = await erc20.totalSupply().call()
    
    # upgradeable ERC20 call
    result = await signer.send_transaction(
            account, PROXY.contract_address, 'totalSupply', []
        )

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets include:

*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   more to come! have an idea? [open an issue](https://github.com/OpenZeppelin/cairo-contracts/issues/new/choose)
    !
    

[← Extensibility](/contracts-cairo/0.4.0b/extensibility)

[Accounts →](/contracts-cairo/0.4.0b/accounts)




 Extensibility - OpenZeppelin Docs       

Extensibility
=============

|     |     |
| --- | --- |
|     | Expect this pattern to evolve (as it has already done) or even disappear if [proper extensibility features](https://community.starknet.io/t/contract-extensibility-pattern/210/11?u=martriay)<br> are implemented into Cairo. |

*   [The extensibility problem](#the_extensibility_problem)
    
*   [The pattern ™️](#the_pattern)
    
    *   [Libraries](#libraries)
        
    *   [Contracts](#contracts)
        
    
*   [Presets](#presets)
    
*   [Function names and coding style](#function_names_and_coding_style)
    
*   [Emulating hooks](#emulating_hooks)
    

[](#the_extensibility_problem)
The extensibility problem
--------------------------------------------------------

Smart contract development is a critical task. As with all software development, it is error prone; but unlike most scenarios, a bug can result in major losses for organizations as well as individuals. Therefore writing complex smart contracts is a delicate task.

One of the best approaches to minimize introducing bugs is to reuse existing, battle-tested code, a.k.a. using libraries. But code reutilization in StarkNet’s smart contracts is not easy:

*   Cairo has no explicit smart contract extension mechanisms such as inheritance or composability
    
*   Using imports for modularity can result in clashes (more so given that arguments are not part of the selector), and lack of overrides or aliasing leaves no way to resolve them
    
*   Any `@external` function defined in an imported module will be automatically re-exposed by the importer (i.e. the smart contract)
    

To overcome these problems, this project builds on the following guidelines™.

[](#the_pattern)
The pattern
----------------------------

The idea is to have two types of Cairo modules: libraries and contracts. Libraries define reusable logic and storage variables which can then be extended and exposed by contracts. Contracts can be deployed, libraries cannot.

To minimize risk, boilerplate, and avoid function naming clashes, we follow these rules:

### [](#libraries)
Libraries

Considering the following types of functions:

*   `private`: private to a library, not meant to be used outside the module or imported
    
*   `public`: part of the public API of a library
    
*   `internal`: subset of `public` that is either discouraged or potentially unsafe (e.g. `_transfer` on ERC20)
    
*   `external`: subset of `public` that is ready to be exported as-is by contracts (e.g. `transfer` on ERC20)
    
*   `storage`: storage variable functions
    

Then:

*   Must implement `public` and `external` functions under a namespace
    
*   Must implement `private` functions outside the namespace to avoid exposing them
    
*   Must prefix `internal` functions with an underscore (e.g. `ERC20._mint`)
    
*   Must not prefix `external` functions with an underscore (e.g. `ERC20.transfer`)
    
*   Must prefix `storage` functions with the name of the namespace to prevent clashing with other libraries (e.g. `ERC20balances`)
    
*   Must not implement any `@external`, `@view`, or `@constructor` functions
    
*   Can implement initializers (never as `@constructor` or `@external`)
    
*   Must not call initializers on any function
    

### [](#contracts)
Contracts

*   Can import from libraries
    
*   Should implement `@external` functions if needed
    
*   Should implement a `@constructor` function that calls initializers
    
*   Must not call initializers in any function beside the constructor
    

Note that since initializers will never be marked as `@external` and they won’t be called from anywhere but the constructor, there’s no risk of re-initialization after deployment. It’s up to the library developers not to make initializers interdependent to avoid weird dependency paths that may lead to double construction of libraries.

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets are:

*   [Account](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
    
*   [ERC165](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/tests/mocks/ERC165.cairo)
    
*   [ERC20Mintable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
    
*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   [ERC20](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
    
*   [ERC721MintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    
*   [ERC721EnumerableMintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/enumerable/presets/ERC721EnumerableMintableBurnable.cairo)
    

[](#function_names_and_coding_style)
Function names and coding style
--------------------------------------------------------------------

*   Following Cairo’s programming style, we use `snake_case` for library APIs (e.g. `ERC20.transfer_from`, `ERC721.safe_transfer_from`).
    
*   But for standard EVM ecosystem compatibility, we implement external functions in contracts using `camelCase` (e.g. `transferFrom` in a ERC20 contract).
    
*   Guard functions such as the so-called "only owner" are prefixed with `assert_` (e.g. `Ownable.assert_only_owner`).
    

[](#emulating_hooks)
Emulating hooks
------------------------------------

Unlike the Solidity version of [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts)
, this library does not implement [hooks](https://docs.openzeppelin.com/contracts/4.x/extending-contracts#using-hooks)
. The main reason being that Cairo does not support overriding functions.

This is what a hook looks like in Solidity:

    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }

Instead, the extensibility pattern allows us to simply extend the library implementation of a function (namely `transfer`) by adding lines before or after calling it. This way, we can get away with:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()
        ERC20.transfer(recipient, amount)
        return (TRUE)
    end

[← Overview](/contracts-cairo/0.4.0b/)

[Proxies and Upgrades →](/contracts-cairo/0.4.0b/proxies)




 Presets - OpenZeppelin Docs       

Presets
=======

Presets are ready-to-deploy contracts provided by the library. Since presets are intended to be very simple and as generic as possible, there’s no support for custom or complex contracts such as `ERC20Pausable` or `ERC721Mintable`.

|     |     |
| --- | --- |
|     | For contract customization and combination of modules you can use [Wizard for Cairo](https://wizard.openzeppelin.com)<br>, our code-generation tool. |

[](#available_presets)
Available presets
----------------------------------------

List of available presets and their corresponding [Sierra class hashes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash)
.

|     |     |
| --- | --- |
|     | Class hashes were computed using [cairo 2.4.1](https://crates.io/crates/cairo-lang-compiler/2.4.1)<br>. |

 
| Name | Sierra Class Hash |
| --- | --- |
| `[Account.cairo](api/account#Account) ` | `0x061dac032f228abef9c6626f995015233097ae253a7f72d68552db02f2971b8f` |
| `[ERC20.cairo](api/erc20#ERC20) ` | `0x046ded64ae2dead6448e247234bab192a9c483644395b66f2155f2614e5804b0` |
| `[ERC721.cairo](api/erc721#ERC721) ` | `0x05e5a302b02eca41819fe263420eb8dc96bfb9770a90f55847c4c1337b551635` |

|     |     |
| --- | --- |
|     | [starkli](https://book.starkli.rs/introduction)<br> class-hash command can be used to compute the class hash from a Sierra artifact. |

[← Components](/contracts-cairo/0.8.1/components)

[Interfaces and Dispatchers →](/contracts-cairo/0.8.1/interfaces)




 Components - OpenZeppelin Docs       

Components
==========

The following documentation provides reasoning and examples on how to use Contracts for Cairo components.

Starknet components are separate modules that contain storage, events, and implementations that can be integrated into a contract. Components themselves cannot be declared or deployed. Another way to think of components is that they are abstract modules that must be instantiated.

|     |     |
| --- | --- |
|     | For more information on the construction and design of Starknet components, see the [Starknet Shamans post](https://community.starknet.io/t/cairo-components/101136#components-1)<br> and the [Cairo book](https://book.cairo-lang.org/ch99-01-05-00-components.html)<br>. |

[](#building_a_contract)
Building a contract
--------------------------------------------

### [](#setup)
Setup

The contract should first import the component and declare it with the `component!` macro:

    #[starknet::contract]
    mod MyContract {
        // Import the component
        use openzeppelin::security::InitializableComponent;
    
        // Declare the component
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    }

The `path` argument should be the imported component itself (in this case, [InitializableComponent](security#initializable)
). The `storage` and `event` arguments are the variable names that will be set in the `Storage` struct and `Event` enum, respectively. Note that even if the component doesn’t define any events, the compiler will still create an empty event enum inside the component module.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

The `#[substorage(v0)]` attribute must be included for each component in the `Storage` trait. This allows the contract to have indirect access to the component’s storage. See [Accessing component storage](#accessing_component_storage)
 for more on this.

The `#[flat]` attribute for events in the `Event` enum, however, is not required. For component events, the first key in the event log is the component ID. Flattening the component event removes it, leaving the event ID as the first key.

### [](#implementations)
Implementations

Components come with granular implementations of different interfaces. This allows contracts to integrate only the implementations that they’ll use and avoid unnecessary bloat. Integrating an implementation looks like this:

    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        // Gives the contract access to the implementation methods
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

Defining an `impl` gives the contract access to the methods within the implementation from the component. For example, `is_initialized` is defined in the `InitializableImpl`. A function on the contract level can expose it like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    
        #[external(v0)]
        fn is_initialized(ref self: ContractState) -> bool {
            self.initializable.is_initialized()
        }
    }

While there’s nothing wrong with manually exposing methods like in the previous example, this process can be tedious for implementations with many methods. Fortunately, a contract can embed implementations which will expose all of the methods of the implementation. To embed an implementation, add the `#[abi(embed_v0)]` attribute above the `impl`:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        // This attribute exposes the methods of the `impl`
        #[abi(embed_v0)]
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

`InitializableImpl` defines the `is_initialized` method in the component. By adding the embed attribute, `is_initialized` becomes a contract entrypoint for `MyContract`.

|     |     |
| --- | --- |
|     | Embeddable implementations, when available in this library’s components, are segregated from the internal component implementation which makes it easier to safely expose. Components also separate standard implementations (`snake_case`) from `camelCase`. This trichotomy structures the API documentation design. See [ERC20Component](api/erc20#ERC20Component)<br> as an example which includes:<br><br>*   **Embeddable implementations**<br>    <br>*   **Embeddable implementations (camelCase)**<br>    <br>*   **Internal implementations** |

### [](#initializers)
Initializers

|     |     |
| --- | --- |
|     | Failing to use a component’s `initializer` can result in irreparable contract deployments. Always read the API documentation for each integrated component. |

Some components require some sort of setup upon construction. Usually, this would be a job for a constructor; however, components themselves cannot implement constructors. Components instead offer `initializer`s within their `InternalImpl` to call from the contract’s constructor. Let’s look at how a contract would integrate [OwnableComponent](api/access#OwnableComponent)
:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        // Instantiate `InternalImpl` to give the contract access to the `initializer`
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Invoke ownable's `initializer`
            self.ownable.initializer(owner);
        }
    }

### [](#dependencies)
Dependencies

Some components include dependencies of other components. Contracts that integrate components with dependencies must also include the component dependency. For instance, [AccessControlComponent](api/access#AccessControlComponent)
 depends on [SRC5Component](api/introspection#SRC5Component)
. Creating a contract with `AccessControlComponent` should look like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl AccessControlCamelImpl =
            AccessControlComponent::AccessControlCamelImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        (...)
    }

[](#customization)
Customization
--------------------------------

|     |     |
| --- | --- |
|     | Customizing implementations and accessing component storage can potentially corrupt the state, bypass security checks, and undermine the component logic. **Exercise extreme caution**. See [Security](#security)<br>. |

### [](#custom_implementations)
Custom implementations

There are instances where a contract requires different or amended behaviors from a component implementation. In these scenarios, a contract must create a custom implementation of the interface. Let’s break down a pausable ERC20 contract to see what that looks like. Here’s the setup:

    #[starknet::contract]
    mod ERC20Pausable {
        use openzeppelin::security::pausable::PausableComponent;
        use openzeppelin::token::erc20::ERC20Component;
        // Import the ERC20 interfaces to create custom implementations
        use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly};
        use starknet::ContractAddress;
    
        component!(path: PausableComponent, storage: pausable, event: PausableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
        impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    
        // `ERC20MetadataImpl` can keep the embed directive because the implementation
        // will not change
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        // Do not add the embed directive to these implementations because
        // these will be customized
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
    
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    }

The first thing to notice is that the contract imports the interfaces of the implementations that will be customized. These will be used in the next code example.

Next, the contract includes the [ERC20Component](api/erc20#ERC20Component)
 implementations; however, `ERC20Impl` and `ERC20CamelOnlyImplt` are **not** embedded. Instead, we want to expose our custom implementation of an interface. The following example shows the pausable logic integrated into the ERC20 implementations:

    #[starknet::contract]
    mod ERC20Pausable {
        (...)
    
        // Custom ERC20 implementation
        #[external(v0)]
        impl CustomERC20Impl of IERC20<ContractState> {
            fn transfer(
                ref self: ContractState, recipient: ContractAddress, amount: u256
            ) -> bool {
                // Add the custom logic
                self.pausable.assert_not_paused();
                // Add the original implementation method from `IERC20Impl`
                self.erc20.transfer(recipient, amount)
            }
    
            fn total_supply(self: @ContractState) -> u256 {
                // This method's behavior does not change from the component
                // implementation, but this method must still be defined.
                // Simply add the original implementation method from `IERC20Impl`
                self.erc20.total_supply()
            }
    
            (...)
        }
    
        // Custom ERC20CamelOnly implementation
        #[external(v0)]
        impl CustomERC20CamelOnlyImpl of IERC20CamelOnly<ContractState> {
            fn totalSupply(self: @ContractState) -> u256 {
                self.erc20.total_supply()
            }
    
            fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {
                self.erc20.balance_of(account)
            }
    
            fn transferFrom(
                ref self: ContractState,
                sender: ContractAddress,
                recipient: ContractAddress,
                amount: u256
            ) -> bool {
                self.pausable.assert_not_paused();
                self.erc20.transfer_from(sender, recipient, amount)
            }
        }
    }

Notice that in the `CustomERC20Impl`, the `transfer` method integrates `pausable.assert_not_paused` as well as `erc20.transfer` from `PausableImpl` and `ERC20Impl` respectively. This is why the contract defined the `ERC20Impl` from the component in the previous example.

Creating a custom implementation of an interface must define **all** methods from that interface. This is true even if the behavior of a method does not change from the component implementation (as `total_supply` exemplifies in this example).

|     |     |
| --- | --- |
|     | The ERC20 documentation provides another custom implementation guide for [Customizing decimals](erc20#customizing_decimals)<br>. |

### [](#accessing_component_storage)
Accessing component storage

There may be cases where the contract must read or write to an integrated component’s storage. To do so, use the same syntax as calling an implementation method except replace the name of the method with the storage variable like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        (...)
    
        fn write_to_comp_storage(ref self: ContractState) {
            self.initializable.Initializable_initialized.write(true);
        }
    
        fn read_from_comp_storage(self: @ContractState) -> bool {
            self.initializable.Initializable_initialized.read()
        }
    }

[](#security)
Security
----------------------

The maintainers of OpenZeppelin Contracts for Cairo are mainly concerned with the correctness and security of the code as published in the library.

Customizing implementations and manipulating the component state may break some important assumptions and introduce vulnerabilities. While we try to ensure the components remain secure in the face of a wide range of potential customizations, this is done in a best-effort manner. Any and all customizations to the component logic should be carefully reviewed and checked against the source code of the component they are customizing so as to fully understand their impact and guarantee their security.

[← Wizard](/contracts-cairo/0.8.1/wizard)

[Presets →](/contracts-cairo/0.8.1/presets)














 Using with Upgrades - OpenZeppelin Docs       

Using with Upgrades
===================

If your contract is going to be deployed with upgradeability, such as using the [OpenZeppelin Upgrades Plugins](../../upgrades-plugins/1.x/)
, you will need to use the Upgrade Safe variant of OpenZeppelin Contracts.

This variant is available as a separate package called `@openzeppelin/contracts-upgradeable`, which is hosted in the repository [OpenZeppelin/openzeppelin-contracts-upgradeable](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
.

It follows all of the rules for [Writing Upgradeable Contracts](../../upgrades-plugins/1.x/writing-upgradeable)
: constructors are replaced by initializer functions, state variables are initialized in initializer functions, and we additionally check for storage incompatibilities across minor versions.

[](#overview)
Overview
----------------------

### [](#installation)
Installation

    $ npm install @openzeppelin/contracts-upgradeable

### [](#usage)
Usage

The package replicates the structure of the main OpenZeppelin Contracts package, but every file and contract has the suffix `Upgradeable`.

    -import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
    +import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
    
    -contract MyCollectible is ERC721 {
    +contract MyCollectible is ERC721Upgradeable {

Constructors are replaced by internal initializer functions following the naming convention `__{ContractName}_init`. Since these are internal, you must always define your own public initializer function and call the parent initializer of the contract you extend.

    -    constructor() ERC721("MyCollectible", "MCO") public {
    +    function initialize() initializer public {
    +        __ERC721_init("MyCollectible", "MCO");
         }

|     |     |
| --- | --- |
|     | Use with multiple inheritance requires special attention. See the section below titled [Multiple Inheritance](#multiple-inheritance)<br>. |

Once this contract is set up and compiled, you can deploy it using the [Upgrades Plugins](../../upgrades-plugins/1.x/)
. The following snippet shows an example deployment script using Hardhat.

    // scripts/deploy-my-collectible.js
    const { ethers, upgrades } = require("hardhat");
    
    async function main() {
      const MyCollectible = await ethers.getContractFactory("MyCollectible");
    
      const mc = await upgrades.deployProxy(MyCollectible);
    
      await mc.deployed();
      console.log("MyCollectible deployed to:", mc.address);
    }
    
    main();

[](#further_notes)
Further Notes
--------------------------------

### [](#multiple-inheritance)
Multiple Inheritance

Initializer functions are not linearized by the compiler like constructors. Because of this, each `__{ContractName}_init` function embeds the linearized calls to all parent initializers. As a consequence, calling two of these `init` functions can potentially initialize the same contract twice.

The function `__{ContractName}_init_unchained` found in every contract is the initializer function minus the calls to parent initializers, and can be used to avoid the double initialization problem, but doing this manually is not recommended. We hope to be able to implement safety checks for this in future versions of the Upgrades Plugins.

### [](#storage_gaps)
Storage Gaps

You may notice that every contract includes a state variable named `__gap`. This is empty reserved space in storage that is put in place in Upgrade Safe contracts. It allows us to freely add new state variables in the future without compromising the storage compatibility with existing deployments.

It isn’t safe to simply add a state variable because it "shifts down" all of the state variables below in the inheritance chain. This makes the storage layouts incompatible, as explained in [Writing Upgradeable Contracts](../../upgrades-plugins/1.x/writing-upgradeable#modifying-your-contracts)
. The size of the `__gap` array is calculated so that the amount of storage used by a contract always adds up to the same number (in this case 50 storage slots).

[← Extending Contracts](/contracts/3.x/extending-contracts)

[Releases & Stability →](/contracts/3.x/releases-stability)




 Proxies - OpenZeppelin Docs       

Proxies
=======

|     |     |
| --- | --- |
|     | Expect rapid iteration as this pattern matures and more patterns potentially emerge. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Solidity/Cairo upgrades comparison](#soliditycairo_upgrades_comparison)
    
    *   [Constructors](#constructors)
        
    *   [Storage](#storage)
        
    
*   [Proxies](#proxies2)
    
    *   [Proxy contract](#proxy_contract)
        
    *   [Implementation contract](#implementation_contract)
        
    
*   [Upgrades library API](#upgrades_library_api)
    
    *   [Methods](#methods)
        
    *   [Events](#events)
        
    
*   [Using proxies](#using_proxies)
    
    *   [Contract upgrades](#contract_upgrades)
        
    *   [Declaring contracts](#declaring_contracts)
        
    *   [Handling method calls](#handling_method_calls)
        
    
*   [Presets](#presets)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  declare an implementation [contract class](https://starknet.io/docs/hello_starknet/intro.html#declare-the-contract-on-the-starknet-testnet)
    
2.  deploy proxy contract with the implementation contract’s class hash set in the proxy’s constructor calldata
    
3.  initialize the implementation contract by sending a call to the proxy contract. This will redirect the call to the implementation contract class and behave like the implementation contract’s constructor
    

In Python, this would look as follows:

        # declare implementation contract
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation contract class hash\
            ]
        )
    
        # users should only interact with the proxy contract
        await signer.send_transaction(
            account, PROXY.contract_address, 'initializer', [\
                proxy_admin\
            ]
        )

[](#soliditycairo_upgrades_comparison)
Solidity/Cairo upgrades comparison
-------------------------------------------------------------------------

### [](#constructors)
Constructors

OpenZeppelin Contracts for Solidity requires the use of an alternative library for upgradeable contracts. Consider that in Solidity constructors are not part of the deployed contract’s runtime bytecode; rather, a constructor’s logic is executed only once when the contract instance is deployed and then discarded. This is why proxies can’t imitate the construction of its implementation, therefore requiring a different initialization mechanism.

The constructor problem in upgradeable contracts is resolved by the use of initializer methods. Initializer methods are essentially regular methods that execute the logic that would have been in the constructor. Care needs to be exercised with initializers to ensure they can only be called once. Thus, OpenZeppelin offers an [upgradeable contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
 where much of this process is abstracted away. See OpenZeppelin’s [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)
 for more info.

The Cairo programming language does not support inheritance. Instead, Cairo contracts follow the [Extensibility Pattern](extensibility)
 which already uses initializer methods to mimic constructors. Upgradeable contracts do not, therefore, require a separate library with refactored constructor logic.

### [](#storage)
Storage

OpenZeppelin’s alternative Upgrades library also implements [unstructured storage](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies)
 for its upgradeable contracts. The basic idea behind unstructured storage is to pseudo-randomize the storage structure of the upgradeable contract so it’s based on variable names instead of declaration order, which makes the chances of storage collision during an upgrade extremely unlikely.

The StarkNet compiler, meanwhile, already creates pseudo-random storage addresses by hashing the storage variable names (and keys in mappings) by default. In other words, StarkNet already uses unstructured storage and does not need a second library to modify how storage is set. See StarkNet’s [Contracts Storage documentation](https://starknet.io/documentation/contracts/#contracts_storage)
 for more information.

[](#proxies2)
Proxies
---------------------

A proxy contract is a contract that delegates function calls to another contract. This type of pattern decouples state and logic. Proxy contracts store the state and redirect function calls to an implementation contract that handles the logic. This allows for different patterns such as upgrades, where implementation contracts can change but the proxy contract (and thus the state) does not; as well as deploying multiple proxy instances pointing to the same implementation. This can be useful to deploy many contracts with identical logic but unique initialization data.

In the case of contract upgrades, it is achieved by simply changing the proxy’s reference to the class hash of the declared implementation. This allows developers to add features, update logic, and fix bugs without touching the state or the contract address to interact with the application.

### [](#proxy_contract)
Proxy contract

The [Proxy contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/presets/Proxy.cairo)
 includes two core methods:

1.  The `__default__` method is a fallback method that redirects a function call and associated calldata to the implementation contract.
    
2.  The `__l1_default__` method is also a fallback method; however, it redirects the function call and associated calldata to a layer one contract. In order to invoke `__l1_default__`, the original function call must include the library function `send_message_to_l1`. See Cairo’s [Interacting with L1 contracts](https://www.cairo-lang.org/docs/hello_starknet/l1l2.html)
     for more information.
    

Since this proxy is designed to work both as an [UUPS-flavored upgrade proxy](https://eips.ethereum.org/EIPS/eip-1822)
 as well as a non-upgradeable proxy, it does not know how to handle its own state. Therefore it requires the implementation contract class to be declared beforehand, so its class hash can be passed to the Proxy on construction time.

When interacting with the contract, function calls should be sent by the user to the proxy. The proxy’s fallback function redirects the function call to the implementation contract to execute.

### [](#implementation_contract)
Implementation contract

The implementation contract, also known as the logic contract, receives the redirected function calls from the proxy contract. The implementation contract should follow the [Extensibility pattern](extensibility#the_pattern)
 and import directly from the [Proxy library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/library.cairo)
.

The implementation contract should:

*   import `Proxy` namespace
    
*   initialize the proxy immediately after contract deployment with `Proxy.initializer`.
    

If the implementation is upgradeable, it should:

*   include a method to upgrade the implementation (i.e. `upgrade`)
    
*   use access control to protect the contract’s upgradeability.
    

The implementation contract should NOT:

*   be deployed like a regular contract. Instead, the implementation contract should be declared (which creates a `DeclaredClass` containing its hash and abi)
    
*   set its initial state with a traditional constructor (decorated with `@constructor`). Instead, use an initializer method that invokes the Proxy `constructor`.
    

|     |     |
| --- | --- |
|     | The Proxy `constructor` includes a check the ensures the initializer can only be called once; however, `_set_implementation` does not include this check. It’s up to the developers to protect their implementation contract’s upgradeability with access controls such as [`assert_only_admin`](#assert_only_admin)<br>. |

For a full implementation contract example, please see:

*   [Proxiable implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ProxiableImplementation.cairo)
    

[](#upgrades_library_api)
Upgrades library API
----------------------------------------------

### [](#methods)
Methods

    func initializer(proxy_admin: felt):
    end
    
    func assert_only_admin():
    end
    
    func get_implementation_hash() -> (implementation: felt):
    end
    
    func get_admin() -> (admin: felt):
    end
    
    func _set_admin(new_admin: felt):
    end
    
    func _set_implementation_hash(new_implementation: felt):
    end

#### [](#initializer)
`initializer`

Initializes the proxy contract with an initial implementation.

Parameters:

    proxy_admin: felt

Returns: None.

#### [](#assert_only_admin)
`assert_only_admin`

Reverts if called by any account other than the admin.

Parameters: None.

Returns: None.

#### [](#get_implementation)
`get_implementation`

Returns the current implementation hash.

Parameters: None.

Returns:

    implementation: felt

#### [](#get_admin)
`get_admin`

Returns the current admin.

Parameters: None.

Returns:

    admin: felt

#### [](#set_admin)
`_set_admin`

Sets `new_admin` as the admin of the proxy contract.

Parameters:

    new_admin: felt

Returns: None.

#### [](#set_implementation_hash)
`_set_implementation_hash`

Sets `new_implementation` as the implementation’s contract class. This method is included in the proxy contract’s constructor and can be used to upgrade contracts.

Parameters:

    new_implementation: felt

Returns: None.

### [](#events)
Events

    func Upgraded(implementation: felt):
    end
    
    func AdminChanged(previousAdmin: felt, newAdmin: felt):
    end

#### [](#upgraded)
`Upgraded`

Emitted when a proxy contract sets a new implementation class hash.

Parameters:

    implementation: felt

#### [](#adminchanged)
`AdminChanged`

Emitted when the `admin` changes from `previousAdmin` to `newAdmin`.

Parameters:

    previousAdmin: felt
    newAdmin: felt

[](#using_proxies)
Using proxies
--------------------------------

### [](#contract_upgrades)
Contract upgrades

To upgrade a contract, the implementation contract should include an `upgrade` method that, when called, changes the reference to a new deployed contract like this:

        # declare first implementation
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation hash\
            ]
        )
    
        # declare implementation v2
        IMPLEMENTATION_V2 = await starknet.declare(
            "path/to/implementation_v2.cairo",
        )
    
        # call upgrade with the new implementation contract class hash
        await signer.send_transaction(
            account, PROXY.contract_address, 'upgrade', [\
                IMPLEMENTATION_V2.class_hash\
            ]
        )

For a full deployment and upgrade implementation, please see:

*   [Upgrades V1](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV1.cairo)
    
*   [Upgrades V2](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV2.cairo)
    

### [](#declaring_contracts)
Declaring contracts

StarkNet contracts come in two forms: contract classes and contract instances. Contract classes represent the uninstantiated, stateless code; whereas, contract instances are instantiated and include the state. Since the Proxy contract references the implementation contract by its class hash, declaring an implementation contract proves sufficient (as opposed to a full deployment). For more information on declaring classes, see [StarkNet’s documentation](https://starknet.io/docs/hello_starknet/intro.html#declare-contract)
.

### [](#handling_method_calls)
Handling method calls

As with most StarkNet contracts, interacting with a proxy contract requires an [account abstraction](accounts#quickstart)
. One notable difference with proxy contracts versus other contract implementations is that calling `@view` methods also requires an account abstraction. As of now, direct calls to default entrypoints are only supported by StarkNet’s `syscalls` from other contracts i.e. account contracts. The differences in getter methods written in Python, for example, are as follows:

    # standard ERC20 call
    result = await erc20.totalSupply().call()
    
    # upgradeable ERC20 call
    result = await signer.send_transaction(
            account, PROXY.contract_address, 'totalSupply', []
        )

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets include:

*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   more to come! have an idea? [open an issue](https://github.com/OpenZeppelin/cairo-contracts/issues/new/choose)
    !
    

[← Extensibility](/contracts-cairo/0.3.0/extensibility)

[Accounts →](/contracts-cairo/0.3.0/accounts)




 Wizard for Cairo - OpenZeppelin Docs       

Wizard for Cairo
================

Not sure where to start? Use the interactive generator below to bootstrap your contract and learn about the components offered in OpenZeppelin Contracts for Cairo.

|     |     |
| --- | --- |
|     | We strongly recommend checking the [Components](components)<br> section to understand how to extend from our library. |

[← Overview](/contracts-cairo/0.8.1/)

[Components →](/contracts-cairo/0.8.1/components)









 ERC20 - OpenZeppelin Docs       

ERC20
=====

An ERC20 token contract keeps track of [_fungible_ tokens](tokens#different-kinds-of-tokens)
: any one token is exactly equal to any other token; no tokens have special rights or behavior associated with them. This makes ERC20 tokens useful for things like a **medium of exchange currency**, **voting rights**, **staking**, and more.

OpenZeppelin Contracts provides many ERC20-related contracts. On the [`API reference`](api/token/ERC20)
 you’ll find detailed information on their properties and usage.

[](#constructing-an-erc20-token-contract)
Constructing an ERC20 Token Contract
------------------------------------------------------------------------------

Using Contracts, we can easily create our own ERC20 token contract, which will be used to track _Gold_ (GLD), an internal currency in a hypothetical game.

Here’s what our GLD token might look like.

    // contracts/GLDToken.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    
    contract GLDToken is ERC20 {
        constructor(uint256 initialSupply) public ERC20("Gold", "GLD") {
            _mint(msg.sender, initialSupply);
        }
    }

Our contracts are often used via [inheritance](https://solidity.readthedocs.io/en/latest/contracts.html#inheritance)
, and here we’re reusing [`ERC20`](api/token/ERC20#erc20)
 for both the basic standard implementation and the [`name`](api/token/ERC20#ERC20-name--)
, [`symbol`](api/token/ERC20#ERC20-symbol--)
, and [`decimals`](api/token/ERC20#ERC20-decimals--)
 optional extensions. Additionally, we’re creating an `initialSupply` of tokens, which will be assigned to the address that deploys the contract.

|     |     |
| --- | --- |
|     | For a more complete discussion of ERC20 supply mechanisms, see [Creating ERC20 Supply](erc20-supply)<br>. |

That’s it! Once deployed, we will be able to query the deployer’s balance:

    > GLDToken.balanceOf(deployerAddress)
    1000000000000000000000

We can also [transfer](api/token/ERC20#IERC20-transfer-address-uint256-)
 these tokens to other accounts:

    > GLDToken.transfer(otherAddress, 300000000000000000000)
    > GLDToken.balanceOf(otherAddress)
    300000000000000000000
    > GLDToken.balanceOf(deployerAddress)
    700000000000000000000

[](#a-note-on-decimals)
A Note on `decimals`
--------------------------------------------

Often, you’ll want to be able to divide your tokens into arbitrary amounts: say, if you own `5 GLD`, you may want to send `1.5 GLD` to a friend, and keep `3.5 GLD` to yourself. Unfortunately, Solidity and the EVM do not support this behavior: only integer (whole) numbers can be used, which poses an issue. You may send `1` or `2` tokens, but not `1.5`.

To work around this, [`ERC20`](api/token/ERC20#ERC20)
 provides a [`decimals`](api/token/ERC20#ERC20-decimals--)
 field, which is used to specify how many decimal places a token has. To be able to transfer `1.5 GLD`, `decimals` must be at least `1`, since that number has a single decimal place.

How can this be achieved? It’s actually very simple: a token contract can use larger integer values, so that a balance of `50` will represent `5 GLD`, a transfer of `15` will correspond to `1.5 GLD` being sent, and so on.

It is important to understand that `decimals` is _only used for display purposes_. All arithmetic inside the contract is still performed on integers, and it is the different user interfaces (wallets, exchanges, etc.) that must adjust the displayed values according to `decimals`. The total token supply and balance of each account are not specified in `GLD`: you need to divide by `10^decimals` to get the actual `GLD` amount.

You’ll probably want to use a `decimals` value of `18`, just like Ether and most ERC20 token contracts in use, unless you have a very special reason not to. When minting tokens or transferring them around, you will be actually sending the number `num GLD * 10^decimals`.

|     |     |
| --- | --- |
|     | By default, `ERC20` uses a value of `18` for `decimals`. To use a different value, you will need to call [\_setupDecimals](api/token/ERC20#ERC20-_setupDecimals-uint8-)<br> in your constructor. |

So if you want to send `5` tokens using a token contract with 18 decimals, the the method to call will actually be:

    transfer(recipient, 5 * 10^18);

[](#Presets)
Preset ERC20 contract
----------------------------------

A preset ERC20 is available, [`ERC20PresetMinterPauser`](api/presets#ERC20PresetMinterPauser)
. It is preset to allow for token minting (create), stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses [Access Control](access-control)
 to control access to the minting and pausing functionality. The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.

This contract is ready to deploy without having to write any Solidity code. It can be used as-is for quick prototyping and testing, but is also suitable for production environments.

[← Tokens](/contracts/3.x/tokens)

[Creating Supply →](/contracts/3.x/erc20-supply)









 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes non-standard functions like `increase_allowance`.

    #[starknet::interface]
    trait ERC20ABI<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
        fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool;
        fn decrease_allowance(
            ref self: TState, spender: ContractAddress, subtracted_value: u256
        ) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> felt252;
        fn symbol(self: @DualCaseERC20) -> felt252;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    trait IERC20Camel<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, snake_selector: felt252, camel_selector: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, snake_selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, camel_selector, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Overview](/contracts-cairo/0.8.0-beta.1/)

[Upgrades →](/contracts-cairo/0.8.0-beta.1/upgrades)




 Extensibility - OpenZeppelin Docs       

Extensibility
=============

|     |     |
| --- | --- |
|     | Expect this pattern to evolve (as it has already done) or even disappear if [proper extensibility features](https://community.starknet.io/t/contract-extensibility-pattern/210/11?u=martriay)<br> are implemented into Cairo. |

*   [The extensibility problem](#the_extensibility_problem)
    
*   [The pattern ™️](#the_pattern)
    
    *   [Libraries](#libraries)
        
    *   [Contracts](#contracts)
        
    
*   [Presets](#presets)
    
*   [Function names and coding style](#function_names_and_coding_style)
    
*   [Emulating hooks](#emulating_hooks)
    

[](#the_extensibility_problem)
The extensibility problem
--------------------------------------------------------

Smart contract development is a critical task. As with all software development, it is error prone; but unlike most scenarios, a bug can result in major losses for organizations as well as individuals. Therefore writing complex smart contracts is a delicate task.

One of the best approaches to minimize introducing bugs is to reuse existing, battle-tested code, a.k.a. using libraries. But code reutilization in StarkNet’s smart contracts is not easy:

*   Cairo has no explicit smart contract extension mechanisms such as inheritance or composability
    
*   Using imports for modularity can result in clashes (more so given that arguments are not part of the selector), and lack of overrides or aliasing leaves no way to resolve them
    
*   Any `@external` function defined in an imported module will be automatically re-exposed by the importer (i.e. the smart contract)
    

To overcome these problems, this project builds on the following guidelines™.

[](#the_pattern)
The pattern
----------------------------

The idea is to have two types of Cairo modules: libraries and contracts. Libraries define reusable logic and storage variables which can then be extended and exposed by contracts. Contracts can be deployed, libraries cannot.

To minimize risk, boilerplate, and avoid function naming clashes, we follow these rules:

### [](#libraries)
Libraries

Considering the following types of functions:

*   `private`: private to a library, not meant to be used outside the module or imported
    
*   `public`: part of the public API of a library
    
*   `internal`: subset of `public` that is either discouraged or potentially unsafe (e.g. `_transfer` on ERC20)
    
*   `external`: subset of `public` that is ready to be exported as-is by contracts (e.g. `transfer` on ERC20)
    
*   `storage`: storage variable functions
    

Then:

*   Must implement `public` and `external` functions under a namespace
    
*   Must implement `private` functions outside the namespace to avoid exposing them
    
*   Must prefix `internal` functions with an underscore (e.g. `ERC20._mint`)
    
*   Must not prefix `external` functions with an underscore (e.g. `ERC20.transfer`)
    
*   Must prefix `storage` functions with the name of the namespace to prevent clashing with other libraries (e.g. `ERC20balances`)
    
*   Must not implement any `@external`, `@view`, or `@constructor` functions
    
*   Can implement initializers (never as `@constructor` or `@external`)
    
*   Must not call initializers on any function
    

### [](#contracts)
Contracts

*   Can import from libraries
    
*   Should implement `@external` functions if needed
    
*   Should implement a `@constructor` function that calls initializers
    
*   Must not call initializers in any function beside the constructor
    

Note that since initializers will never be marked as `@external` and they won’t be called from anywhere but the constructor, there’s no risk of re-initialization after deployment. It’s up to the library developers not to make initializers interdependent to avoid weird dependency paths that may lead to double construction of libraries.

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets are:

*   [Account](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
    
*   [ERC165](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/tests/mocks/ERC165.cairo)
    
*   [ERC20Mintable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
    
*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   [ERC20](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
    
*   [ERC721MintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    
*   [ERC721EnumerableMintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/enumerable/presets/ERC721EnumerableMintableBurnable.cairo)
    

[](#function_names_and_coding_style)
Function names and coding style
--------------------------------------------------------------------

*   Following Cairo’s programming style, we use `snake_case` for library APIs (e.g. `ERC20.transfer_from`, `ERC721.safe_transfer_from`).
    
*   But for standard EVM ecosystem compatibility, we implement external functions in contracts using `camelCase` (e.g. `transferFrom` in a ERC20 contract).
    
*   Guard functions such as the so-called "only owner" are prefixed with `assert_` (e.g. `Ownable.assert_only_owner`).
    

[](#emulating_hooks)
Emulating hooks
------------------------------------

Unlike the Solidity version of [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts)
, this library does not implement [hooks](https://docs.openzeppelin.com/contracts/4.x/extending-contracts#using-hooks)
. The main reason being that Cairo does not support overriding functions.

This is what a hook looks like in Solidity:

    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }

Instead, the extensibility pattern allows us to simply extend the library implementation of a function (namely `transfer`) by adding lines before or after calling it. This way, we can get away with:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()
        ERC20.transfer(recipient, amount)
        return (TRUE)
    end

[← Overview](/contracts-cairo/0.3.1/)

[Proxies and Upgrades →](/contracts-cairo/0.3.1/proxies)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

ERC1155 is a novel token standard that aims to take the best from previous standards to create a [**fungibility-agnostic**](tokens#different-kinds-of-tokens)
 and **gas-efficient** [token contract](tokens#but_first_coffee_a_primer_on_token_contracts)
.

|     |     |
| --- | --- |
|     | ERC1155 draws ideas from all of [ERC20](erc20)<br>, [ERC721](#721.adoc)<br>, and [ERC777](erc777)<br>. If you’re unfamiliar with those standards, head to their guides before moving on. |

[](#multi-token-standard)
Multi Token Standard
----------------------------------------------

The distinctive feature of ERC1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its [`balanceOf`](api/token/ERC1155#IERC1155-balanceOf-address-uint256-)
 function differs from ERC20’s and ERC777’s: it has an additional `id` argument for the identifier of the token that you want to query the balance of.

This is similar to how ERC721 does things, but in that standard a token `id` has no concept of balance: each token is non-fungible and exists or doesn’t. The ERC721 [`balanceOf`](api/token/ERC721#IERC721-balanceOf-address-)
 function refers to _how many different tokens_ an account has, not how many of each. On the other hand, in ERC1155 accounts have a distinct balance for each token `id`, and non-fungible tokens are implemented by simply minting a single one of them.

This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC1155 token contract can hold the entire system state, reducing deployment costs and complexity.

[](#batch-operations)
Batch Operations
--------------------------------------

Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, [`balanceOfBatch`](api/token/ERC1155#IERC1155-balanceOfBatch-address---uint256---)
 and [`safeBatchTransferFrom`](api/token/ERC1155#IERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-)
, that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive.

In the spirit of the standard, we’ve also included batch operations in the non-standard functions, such as [`_mintBatch`](api/token/ERC1155#ERC1155-_mintBatch-address-uint256---uint256---bytes-)
.

[](#constructing_an_erc1155_token_contract)
Constructing an ERC1155 Token Contract
----------------------------------------------------------------------------------

We’ll use ERC1155 to track multiple items in our game, which will each have their own unique attributes. We mint all items to the deployer of the contract, which we can later transfer to players. Players are free to keep their tokens or trade them with other people as they see fit, as they would any other asset on the blockchain!

For simplicity we will mint all items in the constructor but you could add minting functionality to the contract to mint on demand to players.

|     |     |
| --- | --- |
|     | For an overview of minting mechanisms check out [Creating ERC20 Supply](erc20-supply)<br>. |

Here’s what a contract for tokenized items might look like:

    // contracts/GameItems.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
    
    contract GameItems is ERC1155 {
        uint256 public constant GOLD = 0;
        uint256 public constant SILVER = 1;
        uint256 public constant THORS_HAMMER = 2;
        uint256 public constant SWORD = 3;
        uint256 public constant SHIELD = 4;
    
        constructor() public ERC1155("https://game.example/api/item/{id}.json") {
            _mint(msg.sender, GOLD, 10**18, "");
            _mint(msg.sender, SILVER, 10**27, "");
            _mint(msg.sender, THORS_HAMMER, 1, "");
            _mint(msg.sender, SWORD, 10**9, "");
            _mint(msg.sender, SHIELD, 10**9, "");
        }
    }

Note that for our Game Items, Gold is a fungible token whilst Thor’s Hammer is a non-fungible token as we minted only one.

The [`ERC1155`](api/token/ERC1155#ERC1155)
 contract includes the optional extension [`IERC1155MetadataURI`](api/token/ERC1155#IERC1155MetadataURI)
. That’s where the [`uri`](api/token/ERC1155#IERC1155MetadataURI-uri-uint256-)
 function comes from: we use it to retrieve the metadata uri.

Also note that, unlike ERC20, ERC1155 lacks a `decimals` field, since each token is distinct and cannot be partitioned.

Once deployed, we will be able to query the deployer’s balance:

    > gameItems.balanceOf(deployerAddress,3)
    1000000000

We can transfer items to player accounts:

    > gameItems.safeTransferFrom(deployerAddress, playerAddress, 2, 1, "0x0")
    > gameItems.balanceOf(playerAddress, 2)
    1
    > gameItems.balanceOf(deployerAddress, 2)
    0

We can also batch transfer items to player accounts and get the balance of batches:

    > gameItems.safeBatchTransferFrom(deployerAddress, playerAddress, [0,1,3,4], [50,100,1,1], "0x0")
    > gameItems.balanceOfBatch([playerAddress,playerAddress,playerAddress,playerAddress,playerAddress], [0,1,2,3,4])
    [50,100,1,1,1]

The metadata uri can be obtained:

    > gameItems.uri(2)
    "https://game.example/api/item/{id}.json"

The `uri` can include the string `{id}` which clients must replace with the actual token ID, in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters.

For token ID `2` and uri `https://game.example/api/item/{id}.json` clients would replace `{id}` with `0000000000000000000000000000000000000000000000000000000000000002` to retrieve JSON at `[https://game.example/api/item/0000000000000000000000000000000000000000000000000000000000000002.json](https://game.example/api/item/0000000000000000000000000000000000000000000000000000000000000002.json) `.

The JSON document for token ID 2 might look something like:

    {
        "name": "Thor's hammer",
        "description": "Mjölnir, the legendary hammer of the Norse god of thunder.",
        "image": "https://game.example/item-id-8u5h2m.png",
        "strength": 20
    }

For more information about the metadata JSON Schema, check out the [ERC-1155 Metadata URI JSON Schema](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema)
.

|     |     |
| --- | --- |
|     | you’ll notice that the item’s information is included in the metadata, but that information isn’t on-chain! So a game developer could change the underlying metadata, changing the rules of the game! |

[](#sending-to-contracts)
Sending Tokens to Contracts
-----------------------------------------------------

A key difference when using [`safeTransferFrom`](api/token/ERC1155#IERC1155-safeTransferFrom-address-address-uint256-uint256-bytes-)
 is that token transfers to other contracts may revert with the following message:

    ERC1155: transfer to non ERC1155Receiver implementer

This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC1155 protocol, so transfers to it are disabled to **prevent tokens from being locked forever**. As an example, [the Golem contract currently holds over 350k `GNT` tokens](https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d)
, worth multiple tens of thousands of dollars, and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error.

In order for our contract to receive ERC1155 tokens we can inherit from the convenience contract [`ERC1155Holder`](api/token/ERC1155#ERC1155Holder)
 which handles the registering for us. Though we need to remember to implement functionality to allow tokens to be transferred out of our contract:

    // contracts/MyContract.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol";
    
    contract MyContract is ERC1155Holder {
    }

We can also implement more complex scenarios using the [`onERC1155Received`](api/token/ERC1155#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-)
 and [`onERC1155BatchReceived`](api/token/ERC1155#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-)
 functions.

[](#Presets)
Preset ERC1155 contract
------------------------------------

A preset ERC1155 is available, [`ERC1155PresetMinterPauser`](api/presets#ERC1155PresetMinterPauser)
. It is preset to allow for token minting (create) - including batch minting, stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses [Access Control](access-control)
 to control access to the minting and pausing functionality. The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.

This contract is ready to deploy without having to write any Solidity code. It can be used as-is for quick prototyping and testing, but is also suitable for production environments.

[← ERC777](/contracts/3.x/erc777)

[Gas Station Network →](/contracts/3.x/gsn)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are directly derived from a private key, there’s no native account concept on StarkNet.

Instead, signature validation has to be done at the contract level. To relieve smart contract applications such as ERC20 tokens or exchanges from this responsibility, we make use of Account contracts to deal with transaction authentication.

A more detailed writeup on the topic can be found on [Perama’s blogpost](https://perama-v.github.io/cairo/account-abstraction/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Standard Interface](#standard_interface)
    
*   [Keys, signatures and signers](#keys_signatures_and_signers)
    
    *   [Signer](#signer)
        
    *   [MockSigner utility](#mocksigner_utility)
        
    *   [MockEthSigner utility](#mockethsigner_utility)
        
    
*   [Account entrypoint](#account_entrypoint)
    
*   [Call and AccountCallArray format](#call_and_accountcallarray_format)
    
    *   [Call](#call)
        
    *   [AccountCallArray](#accountcallarray)
        
    
*   [Multicall transactions](#multicall_transactions)
    
*   [API Specification](#api_specification)
    
    *   [`get_public_key`](#get_public_key)
        
    *   [`get_nonce`](#get_nonce)
        
    *   [`set_public_key`](#set_public_key)
        
    *   [`is_valid_signature`](#is_valid_signature)
        
    *   [`__execute__`](#execute)
        
    *   [`is_valid_eth_signature`](#is_valid_eth_signature)
        
    *   [`eth_execute`](#eth_execute)
        
    *   [`_unsafe_execute`](#unsafe_execute)
        
    
*   [Presets](#presets)
    
    *   [Account](#account)
        
    *   [Eth Account](#eth_account)
        
    
*   [Account differentiation with ERC165](#account_differentiation_with_erc165)
    
*   [Extending the Account contract](#extending_the_account_contract)
    
*   [L1 escape hatch mechanism](#l1_escape_hatch_mechanism)
    
*   [Paying for gas](#paying_for_gas)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Account contract is deployed to StarkNet
    
2.  Signed transactions can now be sent to the Account contract which validates and executes them
    

In Python, this would look as follows:

    from starkware.starknet.testing.starknet import Starknet
    from utils import get_contract_class
    from signers import MockSigner
    
    signer = MockSigner(123456789987654321)
    
    starknet = await Starknet.empty()
    
    # 1. Deploy Account
    account = await starknet.deploy(
        get_contract_class("Account"),
        constructor_calldata=[signer.public_key]
    )
    
    # 2. Send transaction through Account
    await signer.send_transaction(account, some_contract_address, 'some_function', [some_parameter])

[](#standard_interface)
Standard Interface
------------------------------------------

The [`IAccount.cairo`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/IAccount.cairo)
 contract interface contains the standard account interface proposed in [#41](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and adopted by OpenZeppelin and Argent. It implements [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and it is agnostic of signature validation and nonce management strategies.

    @contract_interface
    namespace IAccount:
        #
        # Getters
        #
    
        func get_nonce() -> (res : felt):
        end
    
        #
        # Business logic
        #
    
        func is_valid_signature(
                hash: felt,
                signature_len: felt,
                signature: felt*
            ) -> (is_valid: felt):
        end
    
        func __execute__(
                call_array_len: felt,
                call_array: AccountCallArray*,
                calldata_len: felt,
                calldata: felt*,
                nonce: felt
            ) -> (response_len: felt, response: felt*):
        end
    end

[](#keys_signatures_and_signers)
Keys, signatures and signers
-------------------------------------------------------------

While the interface is agnostic of signature validation schemes, this implementation assumes there’s a public-private key pair controlling the Account. That’s why the `constructor` function expects a `public_key` parameter to set it. Since there’s also a `set_public_key()` method, accounts can be effectively transferred.

### [](#signer)
Signer

The signer is responsible for creating a transaction signature with the user’s private key for a given transaction. This implementation utilizes [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 class to create transaction signatures through the `Signer` method `sign_transaction`.

`sign_transaction` expects the following parameters per transaction:

*   `sender` the contract address invoking the tx
    
*   `calls` a list containing a sublist of each call to be sent. Each sublist must consist of:
    
    1.  `to` the address of the target contract of the message
        
    2.  `selector` the function to be called on the target contract
        
    3.  `calldata` the parameters for the given `selector`
        
    
*   `nonce` an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    
*   `max_fee` the maximum fee a user will pay
    

Which returns:

*   `calls` a list of calls to be bundled in the transaction
    
*   `calldata` a list of arguments for each call
    
*   `sig_r` the transaction signature
    
*   `sig_s` the transaction signature
    

While the `Signer` class performs much of the work for a transaction to be sent, it neither manages nonces nor invokes the actual transaction on the Account contract. To simplify Account management, most of this is abstracted away with `MockSigner`.

### [](#mocksigner_utility)
MockSigner utility

The `MockSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account, crafting the transaction and managing nonces.

The flow of a transaction starts with checking the nonce and converting the `to` contract address of each call to hexadecimal format. The hexadecimal conversion is necessary because Nile’s `Signer` converts the address to a base-16 integer (which requires a string argument). Note that directly converting `to` to a string will ultimately result in an integer exceeding Cairo’s `FIELD_PRIME`.

The values included in the transaction are passed to the `sign_transaction` method of Nile’s `Signer` which creates and returns a signature. Finally, the `MockSigner` instance invokes the account contract’s `__execute__` with the transaction data.

Users only need to interact with the following exposed methods to perform a transaction:

*   `send_transaction(account, to, selector_name, calldata, nonce=None, max_fee=0)` returns a future of a signed transaction, ready to be sent.
    
*   `send_transactions(account, calls, nonce=None, max_fee=0)` returns a future of batched signed transactions, ready to be sent.
    

To use `MockSigner`, pass a private key when instantiating the class:

    from utils import MockSigner
    
    PRIVATE_KEY = 123456789987654321
    signer = MockSigner(PRIVATE_KEY)

Then send single transactions with the `send_transaction` method.

    await signer.send_transaction(account, contract_address, 'method_name', [])

If utilizing multicall, send multiple transactions with the `send_transactions` method.

        await signer.send_transactions(
            account,
            [\
                (contract_address, 'method_name', [param1, param2]),\
                (contract_address, 'another_method', [])\
            ]
        )

### [](#mockethsigner_utility)
MockEthSigner utility

The `MockEthSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account with a secp256k1 curve key pair, crafting the transaction and managing nonces. It differs from the `MockSigner` implementation by:

*   not using the public key but its derived address instead (the last 20 bytes of the keccak256 hash of the public key and adding `0x` to the beginning)
    
*   signing the message with a secp256k1 curve address
    

[](#account_entrypoint)
Account entrypoint
------------------------------------------

`__execute__` acts as a single entrypoint for all user interaction with any contract, including managing the account contract itself. That’s why if you want to change the public key controlling the Account, you would send a transaction targeting the very Account contract:

    await signer.send_transaction(account, account.contract_address, 'set_public_key', [NEW_KEY])

Or if you want to update the Account’s L1 address on the `AccountRegistry` contract, you would

    await signer.send_transaction(account, registry.contract_address, 'set_L1_address', [NEW_ADDRESS])

You can read more about how messages are structured and hashed in the [Account message scheme discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/24)
. For more information on the design choices and implementation of multicall, you can read the [How should Account multicall work discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/27)
.

The `__execute__` method has the following interface:

    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

Where:

*   `call_array_len` is the number of calls
    
*   `call_array` is an array representing each `Call`
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    
*   `nonce` is an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    

|     |     |
| --- | --- |
|     | The scheme of building multicall transactions within the `__execute__` method will change once StarkNet allows for pointers in struct arrays. In which case, multiple transactions can be passed to (as opposed to built within) `__execute__`. |

[](#call_and_accountcallarray_format)
`Call` and `AccountCallArray` format
--------------------------------------------------------------------------

The idea is for all user intent to be encoded into a `Call` representing a smart contract call. Users can also pack multiple messages into a single transaction (creating a multicall transaction). Cairo currently does not support arrays of structs with pointers which means the `__execute__` function cannot properly iterate through mutiple `Call`s. Instead, this implementation utilizes a workaround with the `AccountCallArray` struct. See [Multicall transactions](#multicall_transactions)
.

### [](#call)
`Call`

A single `Call` is structured as follows:

    struct Call:
        member to: felt
        member selector: felt
        member calldata_len: felt
        member calldata: felt*
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    

### [](#accountcallarray)
`AccountCallArray`

`AccountCallArray` is structured as:

    struct AccountCallArray:
        member to: felt
        member selector: felt
        member data_offset: felt
        member data_len: felt
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `data_offset` is the starting position of the calldata array that holds the `Call`'s calldata
    
*   `data_len` is the number of calldata elements in the `Call`
    

[](#multicall_transactions)
Multicall transactions
--------------------------------------------------

A multicall transaction packs the `to`, `selector`, `calldata_offset`, and `calldata_len` of each call into the `AccountCallArray` struct and keeps the cumulative calldata for every call in a separate array. The `__execute__` function rebuilds each message by combining the `AccountCallArray` with its calldata (demarcated by the offset and calldata length specified for that particular call). The rebuilding logic is set in the internal `_from_call_array_to_call`.

This is the basic flow:

First, the user sends the messages for the transaction through a Signer instantiation which looks like this:

     await signer.send_transaction(
             account, [\
                 (contract_address, 'contract_method', [arg_1]),\
                 (contract_address, 'another_method', [arg_1, arg_2])\
             ]
         )

Then the `_from_call_to_call_array` method in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 converts each call into the `AccountCallArray` format and cumulatively stores the calldata of every call into a single array. Next, both arrays (as well as the `sender`, `nonce`, and `max_fee`) are used to create the transaction hash. The Signer then invokes `__execute__` with the signature and passes `AccountCallArray`, calldata, and nonce as arguments.

Finally, the `__execute__` method takes the `AccountCallArray` and calldata and builds an array of `Call`s (MultiCall).

|     |     |
| --- | --- |
|     | Every transaction utilizes `AccountCallArray`. A single `Call` is treated as a bundle with one message. |

[](#api_specification)
API Specification
----------------------------------------

This in a nutshell is the Account contract public API:

    func get_public_key() -> (res: felt):
    end
    
    func get_nonce() -> (res: felt):
    end
    
    func set_public_key(new_public_key: felt):
    end
    
    func is_valid_signature(hash: felt,
            signature_len: felt,
            signature: felt*
        ) -> (is_valid: felt):
    end
    
    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

### [](#get_public_key)
`get_public_key`

Returns the public key associated with the Account contract.

Parameters: None.

Returns:

    public_key: felt

### [](#get_nonce)
`get_nonce`

Returns the current transaction nonce for the Account.

Parameters: None.

Returns:

    nonce: felt

### [](#set_public_key)
`set_public_key`

Sets the public key that will control this Account. It can be used to rotate keys for security, change them in case of compromised keys or even transferring ownership of the account.

Parameters:

    public_key: felt

Returns: None.

### [](#is_valid_signature)
`is_valid_signature`

This function is inspired by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and returns `TRUE` if a given signature is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    hash: felt
    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#execute)
`__execute__`

This is the only external entrypoint to interact with the Account contract. It:

1.  Validates the transaction signature matches the message (including the nonce)
    
2.  Increments the nonce
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

|     |     |
| --- | --- |
|     | The current signature scheme expects a 2-element array like `[sig_r, sig_s]`. |

Returns:

    response_len: felt
    response: felt*

### [](#is_valid_eth_signature)
`is_valid_eth_signature`

Returns `TRUE` if a given signature in the secp256k1 curve is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#eth_execute)
`eth_execute`

This follows the same idea as the vanilla version of `execute` with the sole difference that signature verification is on the secp256k1 curve.

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

Returns:

    response_len: felt
    response: felt*

|     |     |
| --- | --- |
|     | The current signature scheme expects a 7-element array like `[sig_v, uint256_sig_r_low, uint256_sig_r_high, uint256_sig_s_low, uint256_sig_s_high, uint256_hash_low, uint256_hash_high]` given that the parameters of the verification are bigger than a felt. |

### [](#unsafe_execute)
`_unsafe_execute`

It’s an [internal](extensibility#the_pattern)
 method that performs the following tasks:

1.  Increments the nonce.
    
2.  Takes the input and builds a `Call` for each iterated message. See [Multicall transactions](#multicall_transactions)
     for more information.
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset differs on the signature type being used by the Account.

### [](#account)
Account

The [`Account`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
 preset uses StarkNet keys to validate transactions.

### [](#eth_account)
Eth Account

The [`EthAccount`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/EthAccount.cairo)
 preset supports Ethereum addresses, validating transactions with secp256k1 keys.

[](#account_differentiation_with_erc165)
Account differentiation with ERC165
----------------------------------------------------------------------------

Certain contracts like ERC721 require a means to differentiate between account contracts and non-account contracts. For a contract to declare itself as an account, it should implement [ERC165](https://eips.ethereum.org/EIPS/eip-165)
 as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. To be in compliance with ERC165 specifications, the idea is to calculate the XOR of `IAccount`'s EVM selectors (not StarkNet selectors). The resulting magic value of `IAccount` is 0x50b70dcb.

Our ERC165 integration on StarkNet is inspired by OpenZeppelin’s Solidity implementation of [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
 which stores the interfaces that the implementing contract supports. In the case of account contracts, querying `supportsInterface` of an account’s address with the `IAccount` magic value should return `TRUE`.

[](#extending_the_account_contract)
Extending the Account contract
------------------------------------------------------------------

Account contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
.

To implement custom account contracts, a pair of `validate` and `execute` functions should be exposed. This is why the Account library comes with different flavors of such pairs, like the vanilla `is_valid_signature` and `execute`, or the Ethereum flavored `is_valid_eth_signature` and `eth_execute` pair.

Account contract developers are encouraged to implement the [standard Account interface](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and incorporate the custom logic thereafter.

To implement alternative `execute` functions, make sure to check their corresponding `validate` function before calling the `_unsafe_execute` building block, as each of the current presets is doing. Do not expose `_unsafe_execute` directly.

|     |     |
| --- | --- |
|     | The `ecdsa_ptr` implicit argument should be included in new methods that invoke `_unsafe_execute` (even if the `ecdsa_ptr` is not being used). Otherwise, it’s possible that an account’s functionality can work in both the testing and local devnet environments; however, it could fail on public networks on account of the [SignatureBuiltinRunner](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py)<br>. See [issue #386](https://github.com/OpenZeppelin/cairo-contracts/issues/386)<br> for more information. |

Some other validation schemes to look out for in the future:

*   multisig
    
*   guardian logic like in [Argent’s account](https://github.com/argentlabs/argent-contracts-starknet/blob/de5654555309fa76160ba3d7393d32d2b12e7349/contracts/ArgentAccount.cairo)
    

[](#l1_escape_hatch_mechanism)
L1 escape hatch mechanism
--------------------------------------------------------

[](#paying_for_gas)
Paying for gas
----------------------------------

[← Proxies and Upgrades](/contracts-cairo/0.4.0b/proxies)

[Access Control →](/contracts-cairo/0.4.0b/access)




 Components - OpenZeppelin Docs       

Components
==========

The following documentation provides reasoning and examples on how to use Contracts for Cairo components.

Starknet components are separate modules that contain storage, events, and implementations that can be integrated into a contract. Components themselves cannot be declared or deployed. Another way to think of components is that they are abstract modules that must be instantiated.

|     |     |
| --- | --- |
|     | For more information on the construction and design of Starknet components, see the [Starknet Shamans post](https://community.starknet.io/t/cairo-components/101136#components-1)<br> and the [Cairo book](https://book.cairo-lang.org/ch99-01-05-00-components.html)<br>. |

[](#building_a_contract)
Building a contract
--------------------------------------------

### [](#setup)
Setup

The contract should first import the component and declare it with the `component!` macro:

    #[starknet::contract]
    mod MyContract {
        // Import the component
        use openzeppelin::security::InitializableComponent;
    
        // Declare the component
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    }

The `path` argument should be the imported component itself (in this case, [InitializableComponent](security#initializable)
). The `storage` and `event` arguments are the variable names that will be set in the `Storage` struct and `Event` enum, respectively. Note that even if the component doesn’t define any events, the compiler will still create an empty event enum inside the component module.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

The `#[substorage(v0)]` attribute must be included for each component in the `Storage` trait. This allows the contract to have indirect access to the component’s storage. See [Accessing component storage](#accessing_component_storage)
 for more on this.

The `#[flat]` attribute for events in the `Event` enum, however, is not required. For component events, the first key in the event log is the component ID. Flattening the component event removes it, leaving the event ID as the first key.

### [](#implementations)
Implementations

Components come with granular implementations of different interfaces. This allows contracts to integrate only the implementations that they’ll use and avoid unnecessary bloat. Integrating an implementation looks like this:

    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        // Gives the contract access to the implementation methods
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

Defining an `impl` gives the contract access to the methods within the implementation from the component. For example, `is_initialized` is defined in the `InitializableImpl`. A function on the contract level can expose it like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    
        #[external(v0)]
        fn is_initialized(ref self: ContractState) -> bool {
            self.initializable.is_initialized()
        }
    }

While there’s nothing wrong with manually exposing methods like in the previous example, this process can be tedious for implementations with many methods. Fortunately, a contract can embed implementations which will expose all of the methods of the implementation. To embed an implementation, add the `#[abi(embed_v0)]` attribute above the `impl`:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        // This attribute exposes the methods of the `impl`
        #[abi(embed_v0)]
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

`InitializableImpl` defines the `is_initialized` method in the component. By adding the embed attribute, `is_initialized` becomes a contract entrypoint for `MyContract`.

|     |     |
| --- | --- |
|     | Embeddable implementations, when available in this library’s components, are segregated from the internal component implementation which makes it easier to safely expose. Components also separate standard implementations (`snake_case`) from `camelCase`. This trichotomy structures the API documentation design. See [ERC20Component](api/erc20#ERC20Component)<br> as an example which includes:<br><br>*   **Embeddable implementations**<br>    <br>*   **Embeddable implementations (camelCase)**<br>    <br>*   **Internal implementations** |

### [](#initializers)
Initializers

|     |     |
| --- | --- |
|     | Failing to use a component’s `initializer` can result in irreparable contract deployments. Always read the API documentation for each integrated component. |

Some components require some sort of setup upon construction. Usually, this would be a job for a constructor; however, components themselves cannot implement constructors. Components instead offer `initializer`s within their `InternalImpl` to call from the contract’s constructor. Let’s look at how a contract would integrate [OwnableComponent](api/access#OwnableComponent)
:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        // Instantiate `InternalImpl` to give the contract access to the `initializer`
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Invoke ownable's `initializer`
            self.ownable.initializer(owner);
        }
    }

### [](#dependencies)
Dependencies

Some components include dependencies of other components. Contracts that integrate components with dependencies must also include the component dependency. For instance, [AccessControlComponent](api/access#AccessControlComponent)
 depends on [SRC5Component](api/introspection#SRC5Component)
. Creating a contract with `AccessControlComponent` should look like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl AccessControlCamelImpl =
            AccessControlComponent::AccessControlCamelImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        (...)
    }

[](#customization)
Customization
--------------------------------

|     |     |
| --- | --- |
|     | Customizing implementations and accessing component storage can potentially corrupt the state, bypass security checks, and undermine the component logic. **Exercise extreme caution**. See [Security](#security)<br>. |

### [](#custom_implementations)
Custom implementations

There are instances where a contract requires different or amended behaviors from a component implementation. In these scenarios, a contract must create a custom implementation of the interface. Let’s break down a pausable ERC20 contract to see what that looks like. Here’s the setup:

    #[starknet::contract]
    mod ERC20Pausable {
        use openzeppelin::security::pausable::PausableComponent;
        use openzeppelin::token::erc20::ERC20Component;
        // Import the ERC20 interfaces to create custom implementations
        use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly};
        use starknet::ContractAddress;
    
        component!(path: PausableComponent, storage: pausable, event: PausableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
        impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    
        // `ERC20MetadataImpl` can keep the embed directive because the implementation
        // will not change
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        // Do not add the embed directive to these implementations because
        // these will be customized
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
    
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    }

The first thing to notice is that the contract imports the interfaces of the implementations that will be customized. These will be used in the next code example.

Next, the contract includes the [ERC20Component](api/erc20#ERC20Component)
 implementations; however, `ERC20Impl` and `ERC20CamelOnlyImplt` are **not** embedded. Instead, we want to expose our custom implementation of an interface. The following example shows the pausable logic integrated into the ERC20 implementations:

    #[starknet::contract]
    mod ERC20Pausable {
        (...)
    
        // Custom ERC20 implementation
        #[external(v0)]
        impl CustomERC20Impl of IERC20<ContractState> {
            fn transfer(
                ref self: ContractState, recipient: ContractAddress, amount: u256
            ) -> bool {
                // Add the custom logic
                self.pausable.assert_not_paused();
                // Add the original implementation method from `IERC20Impl`
                self.erc20.transfer(recipient, amount)
            }
    
            fn total_supply(self: @ContractState) -> u256 {
                // This method's behavior does not change from the component
                // implementation, but this method must still be defined.
                // Simply add the original implementation method from `IERC20Impl`
                self.erc20.total_supply()
            }
    
            (...)
        }
    
        // Custom ERC20CamelOnly implementation
        #[external(v0)]
        impl CustomERC20CamelOnlyImpl of IERC20CamelOnly<ContractState> {
            fn totalSupply(self: @ContractState) -> u256 {
                self.erc20.total_supply()
            }
    
            fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {
                self.erc20.balance_of(account)
            }
    
            fn transferFrom(
                ref self: ContractState,
                sender: ContractAddress,
                recipient: ContractAddress,
                amount: u256
            ) -> bool {
                self.pausable.assert_not_paused();
                self.erc20.transfer_from(sender, recipient, amount)
            }
        }
    }

Notice that in the `CustomERC20Impl`, the `transfer` method integrates `pausable.assert_not_paused` as well as `erc20.transfer` from `PausableImpl` and `ERC20Impl` respectively. This is why the contract defined the `ERC20Impl` from the component in the previous example.

Creating a custom implementation of an interface must define **all** methods from that interface. This is true even if the behavior of a method does not change from the component implementation (as `total_supply` exemplifies in this example).

|     |     |
| --- | --- |
|     | The ERC20 documentation provides another custom implementation guide for [Customizing decimals](erc20#customizing_decimals)<br>. |

### [](#accessing_component_storage)
Accessing component storage

There may be cases where the contract must read or write to an integrated component’s storage. To do so, use the same syntax as calling an implementation method except replace the name of the method with the storage variable like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        (...)
    
        fn write_to_comp_storage(ref self: ContractState) {
            self.initializable.Initializable_initialized.write(true);
        }
    
        fn read_from_comp_storage(self: @ContractState) -> bool {
            self.initializable.Initializable_initialized.read()
        }
    }

[](#security)
Security
----------------------

The maintainers of OpenZeppelin Contracts for Cairo are mainly concerned with the correctness and security of the code as published in the library.

Customizing implementations and manipulating the component state may break some important assumptions and introduce vulnerabilities. While we try to ensure the components remain secure in the face of a wide range of potential customizations, this is done in a best-effort manner. Any and all customizations to the component logic should be carefully reviewed and checked against the source code of the component they are customizing so as to fully understand their impact and guarantee their security.

[← Wizard](/contracts-cairo/0.8.0/wizard)

[Presets →](/contracts-cairo/0.8.0/presets)









 ERC777 - OpenZeppelin Docs       

ERC777
======

Like [ERC20](erc20)
, ERC777 is a standard for [_fungible_ tokens](tokens#different-kinds-of-tokens)
, and is focused around allowing more complex interactions when trading tokens. More generally, it brings tokens and Ether closer together by providing the equivalent of a `msg.value` field, but for tokens.

The standard also brings multiple quality-of-life improvements, such as getting rid of the confusion around `decimals`, minting and burning with proper events, among others, but its killer feature is **receive hooks**. A hook is simply a function in a contract that is called when tokens are sent to it, meaning **accounts and contracts can react to receiving tokens**.

This enables a lot of interesting use cases, including atomic purchases using tokens (no need to do `approve` and `transferFrom` in two separate transactions), rejecting reception of tokens (by reverting on the hook call), redirecting the received tokens to other addresses (similarly to how [`PaymentSplitter`](api/payment#PaymentSplitter)
 does it), among many others.

Furthermore, since contracts are required to implement these hooks in order to receive tokens, _no tokens can get stuck in a contract that is unaware of the ERC777 protocol_, as has happened countless times when using ERC20s.

[](#what_if_i_already_use_erc20)
What If I Already Use ERC20?
-------------------------------------------------------------

The standard has you covered! The ERC777 standard is **backwards compatible with ERC20**, meaning you can interact with these tokens as if they were ERC20, using the standard functions, while still getting all of the niceties, including send hooks. See the [EIP’s Backwards Compatibility section](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility)
 to learn more.

[](#constructing_an_erc777_token_contract)
Constructing an ERC777 Token Contract
--------------------------------------------------------------------------------

We will replicate the `GLD` example of the [ERC20 guide](erc20#constructing-an-erc20-token-contract)
, this time using ERC777. As always, check out the [`API reference`](api/token/ERC777)
 to learn more about the details of each function.

    // contracts/GLDToken.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/token/ERC777/ERC777.sol";
    
    contract GLDToken is ERC777 {
        constructor(uint256 initialSupply, address[] memory defaultOperators)
            public
            ERC777("Gold", "GLD", defaultOperators)
        {
            _mint(msg.sender, initialSupply, "", "");
        }
    }

In this case, we’ll be extending from the [`ERC777`](api/token/ERC777#ERC777)
 contract, which provides an implementation with compatibility support for ERC20. The API is quite similar to that of [`ERC777`](api/token/ERC777#ERC777)
, and we’ll once again make use of [`_mint`](api/token/ERC777#ERC777-_mint-address-address-uint256-bytes-bytes-)
 to assign the `initialSupply` to the deployer account. Unlike [ERC20’s `_mint`](api/token/ERC20#ERC20-_mint-address-uint256-)
, this one includes some extra parameters, but you can safely ignore those for now.

You’ll notice both [`name`](api/token/ERC777#IERC777-name--)
 and [`symbol`](api/token/ERC777#IERC777-symbol--)
 are assigned, but not [`decimals`](api/token/ERC777#ERC777-decimals--)
. The ERC777 specification makes it mandatory to include support for these functions (unlike ERC20, where it is optional and we had to include [`ERC20Detailed`](api/token/ERC20#ERC20Detailed)
), but also mandates that `decimals` always returns a fixed value of `18`, so there’s no need to set it ourselves. For a review of `decimals`'s role and importance, refer back to our [ERC20 guide](erc20#a-note-on-decimals)
.

Finally, we’ll need to set the [`defaultOperators`](api/token/ERC777#IERC777-defaultOperators--)
: special accounts (usually other smart contracts) that will be able to transfer tokens on behalf of their holders. If you’re not planning on using operators in your token, you can simply pass an empty array. _Stay tuned for an upcoming in-depth guide on ERC777 operators!_

That’s it for a basic token contract! We can now deploy it, and use the same [`balanceOf`](api/token/ERC777#IERC777-balanceOf-address-)
 method to query the deployer’s balance:

    > GLDToken.balanceOf(deployerAddress)
    1000

To move tokens from one account to another, we can use both [`ERC20`'s `transfer`](api/token/ERC777#ERC777-transfer-address-uint256-)
 method, or the new [`ERC777`'s `send`](api/token/ERC777#ERC777-send-address-uint256-bytes-)
, which fulfills a very similar role, but adds an optional `data` field:

    > GLDToken.transfer(otherAddress, 300)
    > GLDToken.send(otherAddress, 300, "")
    > GLDToken.balanceOf(otherAddress)
    600
    > GLDToken.balanceOf(deployerAddress)
    400

[](#sending_tokens_to_contracts)
Sending Tokens to Contracts
------------------------------------------------------------

A key difference when using [`send`](api/token/ERC777#ERC777-send-address-uint256-bytes-)
 is that token transfers to other contracts may revert with the following message:

    ERC777: token recipient contract has no implementer for ERC777TokensRecipient

This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC777 protocol, so transfers to it are disabled to **prevent tokens from being locked forever**. As an example, [the Golem contract currently holds over 350k `GNT` tokens](https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d)
, worth multiple tens of thousands of dollars, and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error.

_An upcoming guide will cover how a contract can register itself as a recipient, send and receive hooks, and other advanced features of ERC777!_

[← ERC721](/contracts/3.x/erc721)

[ERC1155 →](/contracts/3.x/erc1155)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are directly derived from a private key, there’s no native account concept on StarkNet.

Instead, signature validation has to be done at the contract level. To relieve smart contract applications such as ERC20 tokens or exchanges from this responsibility, we make use of Account contracts to deal with transaction authentication.

A more detailed writeup on the topic can be found on [Perama’s blogpost](https://perama-v.github.io/cairo/account-abstraction/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Standard Interface](#standard_interface)
    
*   [Keys, signatures and signers](#keys_signatures_and_signers)
    
    *   [Signer](#signer)
        
    *   [MockSigner utility](#mocksigner_utility)
        
    *   [MockEthSigner utility](#mockethsigner_utility)
        
    
*   [Account entrypoint](#account_entrypoint)
    
*   [Call and AccountCallArray format](#call_and_accountcallarray_format)
    
    *   [Call](#call)
        
    *   [AccountCallArray](#accountcallarray)
        
    
*   [Multicall transactions](#multicall_transactions)
    
*   [API Specification](#api_specification)
    
    *   [`get_public_key`](#get_public_key)
        
    *   [`get_nonce`](#get_nonce)
        
    *   [`set_public_key`](#set_public_key)
        
    *   [`is_valid_signature`](#is_valid_signature)
        
    *   [`__execute__`](#execute)
        
    *   [`is_valid_eth_signature`](#is_valid_eth_signature)
        
    *   [`eth_execute`](#eth_execute)
        
    *   [`_unsafe_execute`](#unsafe_execute)
        
    
*   [Presets](#presets)
    
    *   [Account](#account)
        
    *   [Eth Account](#eth_account)
        
    
*   [Account differentiation with ERC165](#account_differentiation_with_erc165)
    
*   [Extending the Account contract](#extending_the_account_contract)
    
*   [L1 escape hatch mechanism](#l1_escape_hatch_mechanism)
    
*   [Paying for gas](#paying_for_gas)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Account contract is deployed to StarkNet
    
2.  Signed transactions can now be sent to the Account contract which validates and executes them
    

In Python, this would look as follows:

    from starkware.starknet.testing.starknet import Starknet
    from utils import get_contract_class
    from signers import MockSigner
    
    signer = MockSigner(123456789987654321)
    
    starknet = await Starknet.empty()
    
    # 1. Deploy Account
    account = await starknet.deploy(
        get_contract_class("Account"),
        constructor_calldata=[signer.public_key]
    )
    
    # 2. Send transaction through Account
    await signer.send_transaction(account, some_contract_address, 'some_function', [some_parameter])

[](#standard_interface)
Standard Interface
------------------------------------------

The [`IAccount.cairo`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/IAccount.cairo)
 contract interface contains the standard account interface proposed in [#41](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and adopted by OpenZeppelin and Argent. It implements [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and it is agnostic of signature validation and nonce management strategies.

    @contract_interface
    namespace IAccount:
        #
        # Getters
        #
    
        func get_nonce() -> (res : felt):
        end
    
        #
        # Business logic
        #
    
        func is_valid_signature(
                hash: felt,
                signature_len: felt,
                signature: felt*
            ) -> (is_valid: felt):
        end
    
        func __execute__(
                call_array_len: felt,
                call_array: AccountCallArray*,
                calldata_len: felt,
                calldata: felt*,
                nonce: felt
            ) -> (response_len: felt, response: felt*):
        end
    end

[](#keys_signatures_and_signers)
Keys, signatures and signers
-------------------------------------------------------------

While the interface is agnostic of signature validation schemes, this implementation assumes there’s a public-private key pair controlling the Account. That’s why the `constructor` function expects a `public_key` parameter to set it. Since there’s also a `set_public_key()` method, accounts can be effectively transferred.

### [](#signer)
Signer

The signer is responsible for creating a transaction signature with the user’s private key for a given transaction. This implementation utilizes [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 class to create transaction signatures through the `Signer` method `sign_transaction`.

`sign_transaction` expects the following parameters per transaction:

*   `sender` the contract address invoking the tx
    
*   `calls` a list containing a sublist of each call to be sent. Each sublist must consist of:
    
    1.  `to` the address of the target contract of the message
        
    2.  `selector` the function to be called on the target contract
        
    3.  `calldata` the parameters for the given `selector`
        
    
*   `nonce` an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    
*   `max_fee` the maximum fee a user will pay
    

Which returns:

*   `calls` a list of calls to be bundled in the transaction
    
*   `calldata` a list of arguments for each call
    
*   `sig_r` the transaction signature
    
*   `sig_s` the transaction signature
    

While the `Signer` class performs much of the work for a transaction to be sent, it neither manages nonces nor invokes the actual transaction on the Account contract. To simplify Account management, most of this is abstracted away with `MockSigner`.

### [](#mocksigner_utility)
MockSigner utility

The `MockSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account, crafting the transaction and managing nonces.

The flow of a transaction starts with checking the nonce and converting the `to` contract address of each call to hexadecimal format. The hexadecimal conversion is necessary because Nile’s `Signer` converts the address to a base-16 integer (which requires a string argument). Note that directly converting `to` to a string will ultimately result in an integer exceeding Cairo’s `FIELD_PRIME`.

The values included in the transaction are passed to the `sign_transaction` method of Nile’s `Signer` which creates and returns a signature. Finally, the `MockSigner` instance invokes the account contract’s `__execute__` with the transaction data.

Users only need to interact with the following exposed methods to perform a transaction:

*   `send_transaction(account, to, selector_name, calldata, nonce=None, max_fee=0)` returns a future of a signed transaction, ready to be sent.
    
*   `send_transactions(account, calls, nonce=None, max_fee=0)` returns a future of batched signed transactions, ready to be sent.
    

To use `MockSigner`, pass a private key when instantiating the class:

    from utils import MockSigner
    
    PRIVATE_KEY = 123456789987654321
    signer = MockSigner(PRIVATE_KEY)

Then send single transactions with the `send_transaction` method.

    await signer.send_transaction(account, contract_address, 'method_name', [])

If utilizing multicall, send multiple transactions with the `send_transactions` method.

        await signer.send_transactions(
            account,
            [\
                (contract_address, 'method_name', [param1, param2]),\
                (contract_address, 'another_method', [])\
            ]
        )

### [](#mockethsigner_utility)
MockEthSigner utility

The `MockEthSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account with a secp256k1 curve key pair, crafting the transaction and managing nonces. It differs from the `MockSigner` implementation by:

*   not using the public key but its derived address instead (the last 20 bytes of the keccak256 hash of the public key and adding `0x` to the beginning)
    
*   signing the message with a secp256k1 curve address
    

[](#account_entrypoint)
Account entrypoint
------------------------------------------

`__execute__` acts as a single entrypoint for all user interaction with any contract, including managing the account contract itself. That’s why if you want to change the public key controlling the Account, you would send a transaction targeting the very Account contract:

    await signer.send_transaction(account, account.contract_address, 'set_public_key', [NEW_KEY])

Or if you want to update the Account’s L1 address on the `AccountRegistry` contract, you would

    await signer.send_transaction(account, registry.contract_address, 'set_L1_address', [NEW_ADDRESS])

You can read more about how messages are structured and hashed in the [Account message scheme discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/24)
. For more information on the design choices and implementation of multicall, you can read the [How should Account multicall work discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/27)
.

The `__execute__` method has the following interface:

    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

Where:

*   `call_array_len` is the number of calls
    
*   `call_array` is an array representing each `Call`
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    
*   `nonce` is an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    

|     |     |
| --- | --- |
|     | The scheme of building multicall transactions within the `__execute__` method will change once StarkNet allows for pointers in struct arrays. In which case, multiple transactions can be passed to (as opposed to built within) `__execute__`. |

[](#call_and_accountcallarray_format)
`Call` and `AccountCallArray` format
--------------------------------------------------------------------------

The idea is for all user intent to be encoded into a `Call` representing a smart contract call. Users can also pack multiple messages into a single transaction (creating a multicall transaction). Cairo currently does not support arrays of structs with pointers which means the `__execute__` function cannot properly iterate through mutiple `Call`s. Instead, this implementation utilizes a workaround with the `AccountCallArray` struct. See [Multicall transactions](#multicall_transactions)
.

### [](#call)
`Call`

A single `Call` is structured as follows:

    struct Call:
        member to: felt
        member selector: felt
        member calldata_len: felt
        member calldata: felt*
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    

### [](#accountcallarray)
`AccountCallArray`

`AccountCallArray` is structured as:

    struct AccountCallArray:
        member to: felt
        member selector: felt
        member data_offset: felt
        member data_len: felt
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `data_offset` is the starting position of the calldata array that holds the `Call`'s calldata
    
*   `data_len` is the number of calldata elements in the `Call`
    

[](#multicall_transactions)
Multicall transactions
--------------------------------------------------

A multicall transaction packs the `to`, `selector`, `calldata_offset`, and `calldata_len` of each call into the `AccountCallArray` struct and keeps the cumulative calldata for every call in a separate array. The `__execute__` function rebuilds each message by combining the `AccountCallArray` with its calldata (demarcated by the offset and calldata length specified for that particular call). The rebuilding logic is set in the internal `_from_call_array_to_call`.

This is the basic flow:

First, the user sends the messages for the transaction through a Signer instantiation which looks like this:

     await signer.send_transaction(
             account, [\
                 (contract_address, 'contract_method', [arg_1]),\
                 (contract_address, 'another_method', [arg_1, arg_2])\
             ]
         )

Then the `_from_call_to_call_array` method in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 converts each call into the `AccountCallArray` format and cumulatively stores the calldata of every call into a single array. Next, both arrays (as well as the `sender`, `nonce`, and `max_fee`) are used to create the transaction hash. The Signer then invokes `__execute__` with the signature and passes `AccountCallArray`, calldata, and nonce as arguments.

Finally, the `__execute__` method takes the `AccountCallArray` and calldata and builds an array of `Call`s (MultiCall).

|     |     |
| --- | --- |
|     | Every transaction utilizes `AccountCallArray`. A single `Call` is treated as a bundle with one message. |

[](#api_specification)
API Specification
----------------------------------------

This in a nutshell is the Account contract public API:

    func get_public_key() -> (res: felt):
    end
    
    func get_nonce() -> (res: felt):
    end
    
    func set_public_key(new_public_key: felt):
    end
    
    func is_valid_signature(hash: felt,
            signature_len: felt,
            signature: felt*
        ) -> (is_valid: felt):
    end
    
    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

### [](#get_public_key)
`get_public_key`

Returns the public key associated with the Account contract.

Parameters: None.

Returns:

    public_key: felt

### [](#get_nonce)
`get_nonce`

Returns the current transaction nonce for the Account.

Parameters: None.

Returns:

    nonce: felt

### [](#set_public_key)
`set_public_key`

Sets the public key that will control this Account. It can be used to rotate keys for security, change them in case of compromised keys or even transferring ownership of the account.

Parameters:

    public_key: felt

Returns: None.

### [](#is_valid_signature)
`is_valid_signature`

This function is inspired by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and returns `TRUE` if a given signature is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    hash: felt
    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#execute)
`__execute__`

This is the only external entrypoint to interact with the Account contract. It:

1.  Validates the transaction signature matches the message (including the nonce)
    
2.  Increments the nonce
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

|     |     |
| --- | --- |
|     | The current signature scheme expects a 2-element array like `[sig_r, sig_s]`. |

Returns:

    response_len: felt
    response: felt*

### [](#is_valid_eth_signature)
`is_valid_eth_signature`

Returns `TRUE` if a given signature in the secp256k1 curve is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#eth_execute)
`eth_execute`

This follows the same idea as the vanilla version of `execute` with the sole difference that signature verification is on the secp256k1 curve.

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

Returns:

    response_len: felt
    response: felt*

|     |     |
| --- | --- |
|     | The current signature scheme expects a 7-element array like `[sig_v, uint256_sig_r_low, uint256_sig_r_high, uint256_sig_s_low, uint256_sig_s_high, uint256_hash_low, uint256_hash_high]` given that the parameters of the verification are bigger than a felt. |

### [](#unsafe_execute)
`_unsafe_execute`

It’s an [internal](extensibility#the_pattern)
 method that performs the following tasks:

1.  Increments the nonce.
    
2.  Takes the input and builds a `Call` for each iterated message. See [Multicall transactions](#multicall_transactions)
     for more information.
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset differs on the signature type being used by the Account.

### [](#account)
Account

The [`Account`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
 preset uses StarkNet keys to validate transactions.

### [](#eth_account)
Eth Account

The [`EthAccount`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/EthAccount.cairo)
 preset supports Ethereum addresses, validating transactions with secp256k1 keys.

[](#account_differentiation_with_erc165)
Account differentiation with ERC165
----------------------------------------------------------------------------

Certain contracts like ERC721 require a means to differentiate between account contracts and non-account contracts. For a contract to declare itself as an account, it should implement [ERC165](https://eips.ethereum.org/EIPS/eip-165)
 as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. To be in compliance with ERC165 specifications, the idea is to calculate the XOR of `IAccount`'s EVM selectors (not StarkNet selectors). The resulting magic value of `IAccount` is 0x50b70dcb.

Our ERC165 integration on StarkNet is inspired by OpenZeppelin’s Solidity implementation of [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
 which stores the interfaces that the implementing contract supports. In the case of account contracts, querying `supportsInterface` of an account’s address with the `IAccount` magic value should return `TRUE`.

[](#extending_the_account_contract)
Extending the Account contract
------------------------------------------------------------------

Account contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
.

To implement custom account contracts, a pair of `validate` and `execute` functions should be exposed. This is why the Account library comes with different flavors of such pairs, like the vanilla `is_valid_signature` and `execute`, or the Ethereum flavored `is_valid_eth_signature` and `eth_execute` pair.

Account contract developers are encouraged to implement the [standard Account interface](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and incorporate the custom logic thereafter.

To implement alternative `execute` functions, make sure to check their corresponding `validate` function before calling the `_unsafe_execute` building block, as each of the current presets is doing. Do not expose `_unsafe_execute` directly.

|     |     |
| --- | --- |
|     | The `ecdsa_ptr` implicit argument should be included in new methods that invoke `_unsafe_execute` (even if the `ecdsa_ptr` is not being used). Otherwise, it’s possible that an account’s functionality can work in both the testing and local devnet environments; however, it could fail on public networks on account of the [SignatureBuiltinRunner](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py)<br>. See [issue #386](https://github.com/OpenZeppelin/cairo-contracts/issues/386)<br> for more information. |

Some other validation schemes to look out for in the future:

*   multisig
    
*   guardian logic like in [Argent’s account](https://github.com/argentlabs/argent-contracts-starknet/blob/de5654555309fa76160ba3d7393d32d2b12e7349/contracts/ArgentAccount.cairo)
    

[](#l1_escape_hatch_mechanism)
L1 escape hatch mechanism
--------------------------------------------------------

[](#paying_for_gas)
Paying for gas
----------------------------------

[← Proxies and Upgrades](/contracts-cairo/0.3.0/proxies)

[Access Control →](/contracts-cairo/0.3.0/access)




 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes non-standard functions like `increase_allowance`.

    #[starknet::interface]
    trait ERC20ABI<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
        fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool;
        fn decrease_allowance(
            ref self: TState, spender: ContractAddress, subtracted_value: u256
        ) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> felt252;
        fn symbol(self: @DualCaseERC20) -> felt252;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    trait IERC20Camel<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, fallback, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Presets](/contracts-cairo/0.8.1/presets)

[Counterfactual Deployments →](/contracts-cairo/0.8.1/guides/deployment)




 Cairo Contracts Wizard - OpenZeppelin Docs       

Cairo Contracts Wizard
======================

Not sure where to start? Use the interactive generator below to bootstrap your contract and learn about the components offered in OpenZeppelin Cairo Contracts.

|     |     |
| --- | --- |
|     | We strongly recommend checking the [Components](components)<br> section to understand how to extend from our library. |

[← Overview](/contracts-cairo/0.8.0/)

[Components →](/contracts-cairo/0.8.0/components)




 Proxies - OpenZeppelin Docs       

Proxies
=======

|     |     |
| --- | --- |
|     | Expect rapid iteration as this pattern matures and more patterns potentially emerge. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Solidity/Cairo upgrades comparison](#soliditycairo_upgrades_comparison)
    
    *   [Constructors](#constructors)
        
    *   [Storage](#storage)
        
    
*   [Proxies](#proxies2)
    
    *   [Proxy contract](#proxy_contract)
        
    *   [Implementation contract](#implementation_contract)
        
    
*   [Upgrades library API](#upgrades_library_api)
    
    *   [Methods](#methods)
        
    *   [Events](#events)
        
    
*   [Using proxies](#using_proxies)
    
    *   [Contract upgrades](#contract_upgrades)
        
    *   [Declaring contracts](#declaring_contracts)
        
    *   [Handling method calls](#handling_method_calls)
        
    
*   [Presets](#presets)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  declare an implementation [contract class](https://starknet.io/docs/hello_starknet/intro.html#declare-the-contract-on-the-starknet-testnet)
    
2.  deploy proxy contract with the implementation contract’s class hash set in the proxy’s constructor calldata
    
3.  initialize the implementation contract by sending a call to the proxy contract. This will redirect the call to the implementation contract class and behave like the implementation contract’s constructor
    

In Python, this would look as follows:

        # declare implementation contract
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation contract class hash\
            ]
        )
    
        # users should only interact with the proxy contract
        await signer.send_transaction(
            account, PROXY.contract_address, 'initializer', [\
                proxy_admin\
            ]
        )

[](#soliditycairo_upgrades_comparison)
Solidity/Cairo upgrades comparison
-------------------------------------------------------------------------

### [](#constructors)
Constructors

OpenZeppelin Contracts for Solidity requires the use of an alternative library for upgradeable contracts. Consider that in Solidity constructors are not part of the deployed contract’s runtime bytecode; rather, a constructor’s logic is executed only once when the contract instance is deployed and then discarded. This is why proxies can’t imitate the construction of its implementation, therefore requiring a different initialization mechanism.

The constructor problem in upgradeable contracts is resolved by the use of initializer methods. Initializer methods are essentially regular methods that execute the logic that would have been in the constructor. Care needs to be exercised with initializers to ensure they can only be called once. Thus, OpenZeppelin offers an [upgradeable contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
 where much of this process is abstracted away. See OpenZeppelin’s [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)
 for more info.

The Cairo programming language does not support inheritance. Instead, Cairo contracts follow the [Extensibility Pattern](extensibility)
 which already uses initializer methods to mimic constructors. Upgradeable contracts do not, therefore, require a separate library with refactored constructor logic.

### [](#storage)
Storage

OpenZeppelin’s alternative Upgrades library also implements [unstructured storage](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies)
 for its upgradeable contracts. The basic idea behind unstructured storage is to pseudo-randomize the storage structure of the upgradeable contract so it’s based on variable names instead of declaration order, which makes the chances of storage collision during an upgrade extremely unlikely.

The StarkNet compiler, meanwhile, already creates pseudo-random storage addresses by hashing the storage variable names (and keys in mappings) by default. In other words, StarkNet already uses unstructured storage and does not need a second library to modify how storage is set. See StarkNet’s [Contracts Storage documentation](https://starknet.io/documentation/contracts/#contracts_storage)
 for more information.

[](#proxies2)
Proxies
---------------------

A proxy contract is a contract that delegates function calls to another contract. This type of pattern decouples state and logic. Proxy contracts store the state and redirect function calls to an implementation contract that handles the logic. This allows for different patterns such as upgrades, where implementation contracts can change but the proxy contract (and thus the state) does not; as well as deploying multiple proxy instances pointing to the same implementation. This can be useful to deploy many contracts with identical logic but unique initialization data.

In the case of contract upgrades, it is achieved by simply changing the proxy’s reference to the class hash of the declared implementation. This allows developers to add features, update logic, and fix bugs without touching the state or the contract address to interact with the application.

### [](#proxy_contract)
Proxy contract

The [Proxy contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/presets/Proxy.cairo)
 includes two core methods:

1.  The `__default__` method is a fallback method that redirects a function call and associated calldata to the implementation contract.
    
2.  The `__l1_default__` method is also a fallback method; however, it redirects the function call and associated calldata to a layer one contract. In order to invoke `__l1_default__`, the original function call must include the library function `send_message_to_l1`. See Cairo’s [Interacting with L1 contracts](https://www.cairo-lang.org/docs/hello_starknet/l1l2.html)
     for more information.
    

Since this proxy is designed to work both as an [UUPS-flavored upgrade proxy](https://eips.ethereum.org/EIPS/eip-1822)
 as well as a non-upgradeable proxy, it does not know how to handle its own state. Therefore it requires the implementation contract class to be declared beforehand, so its class hash can be passed to the Proxy on construction time.

When interacting with the contract, function calls should be sent by the user to the proxy. The proxy’s fallback function redirects the function call to the implementation contract to execute.

### [](#implementation_contract)
Implementation contract

The implementation contract, also known as the logic contract, receives the redirected function calls from the proxy contract. The implementation contract should follow the [Extensibility pattern](extensibility#the_pattern)
 and import directly from the [Proxy library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/library.cairo)
.

The implementation contract should:

*   import `Proxy` namespace
    
*   initialize the proxy immediately after contract deployment with `Proxy.initializer`.
    

If the implementation is upgradeable, it should:

*   include a method to upgrade the implementation (i.e. `upgrade`)
    
*   use access control to protect the contract’s upgradeability.
    

The implementation contract should NOT:

*   be deployed like a regular contract. Instead, the implementation contract should be declared (which creates a `DeclaredClass` containing its hash and abi)
    
*   set its initial state with a traditional constructor (decorated with `@constructor`). Instead, use an initializer method that invokes the Proxy `constructor`.
    

|     |     |
| --- | --- |
|     | The Proxy `constructor` includes a check the ensures the initializer can only be called once; however, `_set_implementation` does not include this check. It’s up to the developers to protect their implementation contract’s upgradeability with access controls such as [`assert_only_admin`](#assert_only_admin)<br>. |

For a full implementation contract example, please see:

*   [Proxiable implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ProxiableImplementation.cairo)
    

[](#upgrades_library_api)
Upgrades library API
----------------------------------------------

### [](#methods)
Methods

    func initializer(proxy_admin: felt):
    end
    
    func assert_only_admin():
    end
    
    func get_implementation_hash() -> (implementation: felt):
    end
    
    func get_admin() -> (admin: felt):
    end
    
    func _set_admin(new_admin: felt):
    end
    
    func _set_implementation_hash(new_implementation: felt):
    end

#### [](#initializer)
`initializer`

Initializes the proxy contract with an initial implementation.

Parameters:

    proxy_admin: felt

Returns: None.

#### [](#assert_only_admin)
`assert_only_admin`

Reverts if called by any account other than the admin.

Parameters: None.

Returns: None.

#### [](#get_implementation)
`get_implementation`

Returns the current implementation hash.

Parameters: None.

Returns:

    implementation: felt

#### [](#get_admin)
`get_admin`

Returns the current admin.

Parameters: None.

Returns:

    admin: felt

#### [](#set_admin)
`_set_admin`

Sets `new_admin` as the admin of the proxy contract.

Parameters:

    new_admin: felt

Returns: None.

#### [](#set_implementation_hash)
`_set_implementation_hash`

Sets `new_implementation` as the implementation’s contract class. This method is included in the proxy contract’s constructor and can be used to upgrade contracts.

Parameters:

    new_implementation: felt

Returns: None.

### [](#events)
Events

    func Upgraded(implementation: felt):
    end
    
    func AdminChanged(previousAdmin: felt, newAdmin: felt):
    end

#### [](#upgraded)
`Upgraded`

Emitted when a proxy contract sets a new implementation class hash.

Parameters:

    implementation: felt

#### [](#adminchanged)
`AdminChanged`

Emitted when the `admin` changes from `previousAdmin` to `newAdmin`.

Parameters:

    previousAdmin: felt
    newAdmin: felt

[](#using_proxies)
Using proxies
--------------------------------

### [](#contract_upgrades)
Contract upgrades

To upgrade a contract, the implementation contract should include an `upgrade` method that, when called, changes the reference to a new deployed contract like this:

        # declare first implementation
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation hash\
            ]
        )
    
        # declare implementation v2
        IMPLEMENTATION_V2 = await starknet.declare(
            "path/to/implementation_v2.cairo",
        )
    
        # call upgrade with the new implementation contract class hash
        await signer.send_transaction(
            account, PROXY.contract_address, 'upgrade', [\
                IMPLEMENTATION_V2.class_hash\
            ]
        )

For a full deployment and upgrade implementation, please see:

*   [Upgrades V1](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV1.cairo)
    
*   [Upgrades V2](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV2.cairo)
    

### [](#declaring_contracts)
Declaring contracts

StarkNet contracts come in two forms: contract classes and contract instances. Contract classes represent the uninstantiated, stateless code; whereas, contract instances are instantiated and include the state. Since the Proxy contract references the implementation contract by its class hash, declaring an implementation contract proves sufficient (as opposed to a full deployment). For more information on declaring classes, see [StarkNet’s documentation](https://starknet.io/docs/hello_starknet/intro.html#declare-contract)
.

### [](#handling_method_calls)
Handling method calls

As with most StarkNet contracts, interacting with a proxy contract requires an [account abstraction](accounts#quickstart)
. One notable difference with proxy contracts versus other contract implementations is that calling `@view` methods also requires an account abstraction. As of now, direct calls to default entrypoints are only supported by StarkNet’s `syscalls` from other contracts i.e. account contracts. The differences in getter methods written in Python, for example, are as follows:

    # standard ERC20 call
    result = await erc20.totalSupply().call()
    
    # upgradeable ERC20 call
    result = await signer.send_transaction(
            account, PROXY.contract_address, 'totalSupply', []
        )

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets include:

*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   more to come! have an idea? [open an issue](https://github.com/OpenZeppelin/cairo-contracts/issues/new/choose)
    !
    

[← Extensibility](/contracts-cairo/0.3.1/extensibility)

[Accounts →](/contracts-cairo/0.3.1/accounts)




 Tokens - OpenZeppelin Docs       

Tokens
======

Ah, the "token": blockchain’s most powerful and most misunderstood tool.

A token is a _representation of something in the blockchain_. This something can be money, time, services, shares in a company, a virtual pet, anything. By representing things as tokens, we can allow smart contracts to interact with them, exchange them, create or destroy them.

[](#but_first_coffee_a_primer_on_token_contracts)
But First, Coffee a Primer on Token Contracts
-----------------------------------------------------------------------------------------------

Much of the confusion surrounding tokens comes from two concepts getting mixed up: _token contracts_ and the actual _tokens_.

A _token contract_ is simply an Ethereum smart contract. "Sending tokens" actually means "calling a method on a smart contract that someone wrote and deployed". At the end of the day, a token contract is not much more a mapping of addresses to balances, plus some methods to add and subtract from those balances.

It is these balances that represent the _tokens_ themselves. Someone "has tokens" when their balance in the token contract is non-zero. That’s it! These balances could be considered money, experience points in a game, deeds of ownership, or voting rights, and each of these tokens would be stored in different token contracts.

[](#different-kinds-of-tokens)
Different Kinds of Tokens
--------------------------------------------------------

Note that there’s a big difference between having two voting rights and two deeds of ownership: each vote is equal to all others, but houses usually are not! This is called [fungibility](https://en.wikipedia.org/wiki/Fungibility)
. _Fungible goods_ are equivalent and interchangeable, like Ether, fiat currencies, and voting rights. _Non-fungible_ goods are unique and distinct, like deeds of ownership, or collectibles.

In a nutshell, when dealing with non-fungibles (like your house) you care about _which ones_ you have, while in fungible assets (like your bank account statement) what matters is _how much_ you have.

[](#standards)
Standards
------------------------

Even though the concept of a token is simple, they have a variety of complexities in the implementation. Because everything in Ethereum is just a smart contract, and there are no rules about what smart contracts have to do, the community has developed a variety of **standards** (called EIPs or ERCs) for documenting how a contract can interoperate with other contracts.

You’ve probably heard of the ERC20 or ERC721 token standards, and that’s why you’re here. Head to our specialized guides to learn more about these:

*   [ERC20](erc20)
    : the most widespread token standard for fungible assets, albeit somewhat limited by its simplicity.
    
*   [ERC721](erc721)
    : the de-facto solution for non-fungible tokens, often used for collectibles and games.
    
*   [ERC777](erc777)
    : a richer standard for fungible tokens, enabling new use cases and building on past learnings. Backwards compatible with ERC20.
    
*   [ERC1155](erc1155)
    : a novel standard for multi-tokens, allowing for a single contract to represent multiple fungible and non-fungible tokens, along with batched operations for increased gas efficiency.
    

[← Access Control](/contracts/3.x/access-control)

[ERC20 →](/contracts/3.x/erc20)














 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#OwnableComponent)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControlComponent)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#OwnableComponent)
`OwnableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::OwnableComponent;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

[Embeddable Mixin Implementations](../components#mixins)

OwnableMixinImpl

*   [`OwnableImpl`](#OwnableComponent-Embeddable-Impls-OwnableImpl)
    
*   [`OwnableCamelOnlyImpl`](#OwnableComponent-Embeddable-Impls-OwnableCamelOnlyImpl)
    

OwnableTwoStepMixinImpl

*   [`OwnableTwoStepImpl`](#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl)
    
*   [`OwnableTwoStepCamelOnlyImpl`](#OwnableComponent-Embeddable-Impls-OwnableTwoStepCamelOnlyImpl)
    

Embeddable Implementations

OwnableImpl

*   [`owner(self)`](#OwnableComponent-owner)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-renounce_ownership)
    

OwnableTwoStepImpl

*   [`owner(self)`](#OwnableComponent-two-step-owner)
    
*   [`pending_owner(self)`](#OwnableComponent-two-step-pending_owner)
    
*   [`accept_ownership(self)`](#OwnableComponent-two-step-accept_ownership)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-two-step-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-two-step-renounce_ownership)
    

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#OwnableComponent-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-renounceOwnership)
    

OwnableTwoStepCamelOnlyImpl

*   [`pendingOwner(self)`](#OwnableComponent-two-step-pendingOwner)
    
*   [`acceptOwnership(self)`](#OwnableComponent-two-step-acceptOwnership)
    
*   [`transferOwnership(self, new_owner)`](#OwnableComponent-two-step-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-two-step-renounceOwnership)
    

Internal Implementations

InternalImpl

*   [`initializer(self, owner)`](#OwnableComponent-initializer)
    
*   [`assert_only_owner(self)`](#OwnableComponent-assert_only_owner)
    
*   [`_accept_ownership(self)`](#OwnableComponent-_accept_ownership)
    
*   [`_propose_owner(self, new_owner)`](#OwnableComponent-_propose_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#OwnableComponent-_transfer_ownership)
    

Events

*   [`OwnershipTransferStarted(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferStarted)
    
*   [`OwnershipTransferred(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferred)
    

#### [](#OwnableComponent-Embeddable-Functions)
Embeddable functions

#### [](#OwnableComponent-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-Embeddable-Functions-Two-Step)
Embeddable functions (two step transfer)

#### [](#OwnableComponent-two-step-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-two-step-pending_owner)
`pending_owner(self: @ContractState) → ContractAddress` external

Returns the address of the pending owner.

#### [](#OwnableComponent-two-step-accept_ownership)
`accept_ownership(ref self: ContractState)` external

Transfers ownership of the contract to the pending owner. Can only be called by the pending owner. Resets pending owner to zero address.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-two-step-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Starts the two step ownership transfer process, by setting the pending owner. Can only be called by the current owner.

Emits an [OwnershipTransferStarted](#OwnableComponent-OwnershipTransferStarted)
 event.

#### [](#OwnableComponent-two-step-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#OwnableComponent-transfer_ownership)
.

#### [](#OwnableComponent-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#OwnableComponent-renounce_ownership)
.

#### [](#OwnableComponent-two-step-pendingOwner)
`pendingOwner(self: @ContractState)` external

See [pending\_owner](#OwnableComponent-two-step-pending_owner)
.

#### [](#OwnableComponent-two-step-acceptOwnership)
`acceptOwnership(self: @ContractState)` external

See [accept\_ownership](#OwnableComponent-two-step-accept_ownership)
.

#### [](#OwnableComponent-two-step-transferOwnership)
`transferOwnership(self: @ContractState)` external

See [transfer\_ownership](#OwnableComponent-two-step-transfer_ownership)
.

#### [](#OwnableComponent-two-step-renounceOwnership)
`renounceOwnership(self: @ContractState)` external

See [renounce\_ownership](#OwnableComponent-two-step-renounce_ownership)
.

#### [](#OwnableComponent-Internal-Functions)
Internal functions

#### [](#OwnableComponent-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#OwnableComponent-_accept_ownership)
`_accept_ownership(ref self: ContractState)` internal

Transfers ownership to the pending owner. Resets pending owner to zero address. Calls [\_transfer\_ownership](#OwnableComponent-_transfer_ownership)
.

Internal function without access restriction.

#### [](#OwnableComponent-_propose_owner)
`_propose_owner(ref self: ContractState, new_owner: ContractAddress)` internal

Sets a new pending owner in a two step transfer.

Internal function without access restriction.

Emits an [OwnershipTransferStarted](#OwnableComponent-OwnershipTransferStarted)
 event.

#### [](#OwnableComponent-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-Events)
Events

#### [](#OwnableComponent-OwnershipTransferStarted)
`OwnershipTransferStarted(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the pending owner is updated.

#### [](#OwnableComponent-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/access/accesscontrol/interface.cairo)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControlComponent)
`AccessControlComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControlComponent;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControlComponent-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

[Embeddable Mixin Implementations](../components#mixins)

AccessControlMixinImpl

*   [`AccessControlImpl`](#AccessControlComponent-Embeddable-Impls-AccessControlImpl)
    
*   [`AccessControlCamelImpl`](#AccessControlComponent-Embeddable-Impls-AccessControlCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControlComponent-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControlComponent-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControlComponent-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControlComponent-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControlComponent-renounce_role)
    

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControlComponent-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControlComponent-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControlComponent-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControlComponent-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControlComponent-renounceRole)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self)`](#AccessControlComponent-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControlComponent-assert_only_role)
    
*   [`_set_role_admin(self, role, admin_role)`](#AccessControlComponent-_set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControlComponent-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControlComponent-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControlComponent-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControlComponent-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControlComponent-RoleRevoked)
    

#### [](#AccessControlComponent-Embeddable-Functions)
Embeddable functions

#### [](#AccessControlComponent-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControlComponent-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#AccessControlComponent-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControlComponent-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControlComponent-has_role)
.

#### [](#AccessControlComponent-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControlComponent-get_role_admin)
.

#### [](#AccessControlComponent-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControlComponent-grant_role)
.

#### [](#AccessControlComponent-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControlComponent-revoke_role)
.

#### [](#AccessControlComponent-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControlComponent-renounce_role)
.

#### [](#AccessControlComponent-Internal-Functions)
Internal functions

#### [](#AccessControlComponent-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControlComponent-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControlComponent-_set_role_admin)
`_set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControlComponent-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-Events)
Events

#### [](#AccessControlComponent-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControlComponent-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControlComponent-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access](/contracts-cairo/0.10.0/access)

[Accounts →](/contracts-cairo/0.10.0/accounts)




 Creating ERC20 Supply - OpenZeppelin Docs       

Creating ERC20 Supply
=====================

In this guide you will learn how to create an ERC20 token with a custom supply mechanism. We will showcase two idiomatic ways to use OpenZeppelin Contracts for this purpose that you will be able to apply to your smart contract development practice.

The standard interface implemented by tokens built on Ethereum is called ERC20, and Contracts includes a widely used implementation of it: the aptly named [`ERC20`](api/token/ERC20)
 contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try deploy an instance of `ERC20` as-is it will be quite literally useless…​ it will have no supply! What use is a token with no supply?

The way that supply is created is not defined in the ERC20 document. Every token is free to experiment with their own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.

[](#fixed-supply)
Fixed Supply
------------------------------

Let’s say we want a token with a fixed supply of 1000, initially allocated to the account that deploys the contract. If you’ve used Contracts v1, you may have written code like the following:

    contract ERC20FixedSupply is ERC20 {
        constructor() public {
            totalSupply += 1000;
            balances[msg.sender] += 1000;
        }
    }

Starting with Contracts v2 this pattern is not only discouraged, but disallowed. The variables `totalSupply` and `balances` are now private implementation details of `ERC20`, and you can’t directly write to them. Instead, there is an internal [`_mint`](api/token/ERC20#ERC20-_mint-address-uint256-)
 function that will do exactly this:

    contract ERC20FixedSupply is ERC20 {
        constructor() public {
            _mint(msg.sender, 1000);
        }
    }

Encapsulating state like this makes it safer to extend contracts. For instance, in the first example we had to manually keep the `totalSupply` in sync with the modified balances, which is easy to forget. In fact, we omitted something else that is also easily forgotten: the `Transfer` event that is required by the standard, and which is relied on by some clients. The second example does not have this bug, because the internal `_mint` function takes care of it.

[](#rewarding-miners)
Rewarding Miners
--------------------------------------

The internal [`_mint`](api/token/ERC20#ERC20-_mint-address-uint256-)
 function is the key building block that allows us to write ERC20 extensions that implement a supply mechanism.

The mechanism we will implement is a token reward for the miners that produce Ethereum blocks. In Solidity we can access the address of the current block’s miner in the global variable `block.coinbase`. We will mint a token reward to this address whenever someone calls the function `mintMinerReward()` on our token. The mechanism may sound silly, but you never know what kind of dynamic this might result in, and it’s worth analyzing and experimenting with!

    contract ERC20WithMinerReward is ERC20 {
        function mintMinerReward() public {
            _mint(block.coinbase, 1000);
        }
    }

As we can see, `_mint` makes it super easy to do this correctly.

[](#modularizing-the-mechanism)
Modularizing the Mechanism
----------------------------------------------------------

There is one supply mechanism already included in Contracts: [`ERC20Mintable`](api/token/ERC20#ERC20Mintable)
. This is a generic mechanism in which a set of accounts is assigned the `minter` role, granting them the permission to call a [`mint`](api/token/ERC20#ERC20Mintable-mint-address-uint256-)
 function, an external version of `_mint`.

This can be used for centralized minting, where an externally owned account (i.e. someone with a pair of cryptographic keys) decides how much supply to create and to whom. There are very legitimate use cases for this mechanism, such as [traditional asset-backed stablecoins](https://medium.com/reserve-currency/why-another-stablecoin-866f774afede#3aea)
.

The accounts with the minter role don’t need to be externally owned, though, and can just as well be smart contracts that implement a trustless mechanism. We can in fact implement the same behavior as the previous section.

    contract MinerRewardMinter {
        ERC20Mintable _token;
    
        constructor(ERC20Mintable token) public {
            _token = token;
        }
    
        function mintMinerReward() public {
            _token.mint(block.coinbase, 1000);
        }
    }

This contract, when initialized with an `ERC20Mintable` instance, will result in exactly the same behavior implemented in the previous section. What is interesting about using `ERC20Mintable` is that we can easily combine multiple supply mechanisms by assigning the role to multiple contracts, and moreover that we can do this dynamically.

[](#automating-the-reward)
Automating the Reward
------------------------------------------------

Additionally to `_mint`, `ERC20` provides other internal functions that can be used or extended, such as [`_transfer`](api/token/ERC20#ERC20-_transfer-address-address-uint256-)
. This function implements token transfers and is used by `ERC20`, so it can be used to trigger functionality automatically. This is something that can’t be done with the `ERC20Mintable` approach.

Adding to our previous supply mechanism, we can use this to mint a miner reward for every token transfer that is included in the blockchain.

    contract ERC20WithAutoMinerReward is ERC20 {
        function _mintMinerReward() internal {
            _mint(block.coinbase, 1000);
        }
    
        function _transfer(address from, address to, uint256 value) internal {
            _mintMinerReward();
            super._transfer(from, to, value);
        }
    }

Note how we override `_transfer` to first mint the miner reward and then run the original implementation by calling `super._transfer`. This last step is very important to preserve the original semantics of ERC20 transfers.

[](#wrapping-up)
Wrapping Up
----------------------------

We’ve seen two ways to implement ERC20 supply mechanisms: internally through `_mint`, and externally through `ERC20Mintable`. Hopefully this has helped you understand how to use OpenZeppelin and some of the design principles behind it, and you can apply them to your own smart contracts.

[← ERC20](/contracts/2.x/erc20)

[Crowdsales →](/contracts/2.x/crowdsales)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: felt252
        ) -> felt252;
    }

[← Interfaces and Dispatchers](/contracts-cairo/0.8.1/interfaces)

[Access →](/contracts-cairo/0.8.1/access)




 ERC 20 - OpenZeppelin Docs       

ERC 20
======

|     |     |
| --- | --- |
|     | This document is better viewed at [https://docs.openzeppelin.com/contracts/api/token/erc20](https://docs.openzeppelin.com/contracts/api/token/erc20) |

This set of interfaces, contracts, and utilities are all related to the [ERC20 Token Standard](https://eips.ethereum.org/EIPS/eip-20)
.

|     |     |
| --- | --- |
|     | For an overview of ERC20 tokens and a walk through on how to create a token contract read our [ERC20 guide](../../erc20)<br>. |

There a few core contracts that implement the behavior specified in the EIP:

*   [`IERC20`](#IERC20)
    : the interface all ERC20 implementations should conform to.
    
*   [`ERC20`](#ERC20)
    : the implementation of the ERC20 interface, including the [`name`](#ERC20-name)
    , [`symbol`](#ERC20-symbol)
     and [`decimals`](#ERC20-decimals)
     optional standard extension to the base interface.
    

Additionally there are multiple custom extensions, including:

*   [`ERC20Permit`](../drafts#ERC20Permit)
    : gasless approval of tokens.
    
*   [`ERC20Snapshot`](#ERC20Snapshot)
    : efficient storage of past token balances to be later queried at any point in time.
    
*   [`ERC20Burnable`](#ERC20Burnable)
    : destruction of own tokens.
    
*   [`ERC20Capped`](#ERC20Capped)
    : enforcement of a cap to the total supply when minting tokens.
    
*   [`ERC20Pausable`](#ERC20Pausable)
    : ability to pause token transfers.
    

Finally, there are some utilities to interact with ERC20 contracts in various ways.

*   [`SafeERC20`](#SafeERC20)
    : a wrapper around the interface that eliminates the need to handle boolean return values.
    
*   [`TokenTimelock`](#TokenTimelock)
    : hold tokens for a beneficiary until a specified time.
    

The following related EIPs are in draft status and can be found in the drafts directory.

*   [`IERC20Permit`](../drafts#IERC20Permit)
    
*   [`ERC20Permit`](../drafts#ERC20Permit)
    

|     |     |
| --- | --- |
|     | This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC20 (such as [`_mint`](#ERC20-_mint-address-uint256-)<br>) and expose them as external functions in the way they prefer. On the other hand, [ERC20 Presets](../../erc20#Presets)<br> (such as [`ERC20PresetMinterPauser`](../presets#ERC20PresetMinterPauser)<br>) are designed using opinionated patterns to provide developers with ready to use, deployable contracts. |

[](#core)
Core
--------------

### [](#IERC20)
`IERC20`

Interface of the ERC20 standard as defined in the EIP.

Functions

*   [`totalSupply()`](#IERC20-totalSupply--)
    
*   [`balanceOf(account)`](#IERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](#IERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](#IERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](#IERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](#IERC20-transferFrom-address-address-uint256-)
    

Events

*   [`Transfer(from, to, value)`](#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval-address-address-uint256-)
    

#### [](#IERC20-totalSupply--)
`totalSupply() → uint256` external

Returns the amount of tokens in existence.

#### [](#IERC20-balanceOf-address-)
`balanceOf(address account) → uint256` external

Returns the amount of tokens owned by `account`.

#### [](#IERC20-transfer-address-uint256-)
`transfer(address recipient, uint256 amount) → bool` external

Moves `amount` tokens from the caller’s account to `recipient`.

Returns a boolean value indicating whether the operation succeeded.

Emits a [`Transfer`](#IERC20-Transfer-address-address-uint256-)
 event.

#### [](#IERC20-allowance-address-address-)
`allowance(address owner, address spender) → uint256` external

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through [`transferFrom`](#IERC20-transferFrom-address-address-uint256-)
. This is zero by default.

This value changes when [`approve`](#IERC20-approve-address-uint256-)
 or [`transferFrom`](#IERC20-transferFrom-address-address-uint256-)
 are called.

#### [](#IERC20-approve-address-uint256-)
`approve(address spender, uint256 amount) → bool` external

Sets `amount` as the allowance of `spender` over the caller’s tokens.

Returns a boolean value indicating whether the operation succeeded.

|     |     |
| --- | --- |
|     | Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender’s allowance to 0 and set the desired value afterwards: [https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729](https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729) |

Emits an [`Approval`](#IERC20-Approval-address-address-uint256-)
 event.

#### [](#IERC20-transferFrom-address-address-uint256-)
`transferFrom(address sender, address recipient, uint256 amount) → bool` external

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance.

Returns a boolean value indicating whether the operation succeeded.

Emits a [`Transfer`](#IERC20-Transfer-address-address-uint256-)
 event.

#### [](#IERC20-Transfer-address-address-uint256-)
`Transfer(address from, address to, uint256 value)` event

Emitted when `value` tokens are moved from one account (`from`) to another (`to`).

Note that `value` may be zero.

#### [](#IERC20-Approval-address-address-uint256-)
`Approval(address owner, address spender, uint256 value)` event

Emitted when the allowance of a `spender` for an `owner` is set by a call to [`approve`](#IERC20-approve-address-uint256-)
. `value` is the new allowance.

### [](#ERC20)
`ERC20`

Implementation of the [`IERC20`](#IERC20)
 interface.

This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using [`_mint`](#ERC20-_mint-address-uint256-)
. For a generic mechanism see [`ERC20PresetMinterPauser`](../presets#ERC20PresetMinterPauser)
.

|     |     |
| --- | --- |
|     | For a detailed writeup see our guide [How to implement supply mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226)<br>. |

We have followed general OpenZeppelin guidelines: functions revert instead of returning `false` on failure. This behavior is nonetheless conventional and does not conflict with the expectations of ERC20 applications.

Additionally, an [`Approval`](#IERC20-Approval-address-address-uint256-)
 event is emitted on calls to [`transferFrom`](#ERC20-transferFrom-address-address-uint256-)
. This allows applications to reconstruct the allowance for all accounts just by listening to said events. Other implementations of the EIP may not emit these events, as it isn’t required by the specification.

Finally, the non-standard [`decreaseAllowance`](#ERC20-decreaseAllowance-address-uint256-)
 and [`increaseAllowance`](#ERC20-increaseAllowance-address-uint256-)
 functions have been added to mitigate the well-known issues around setting allowances. See [`IERC20.approve`](#IERC20-approve-address-uint256-)
.

Functions

*   [`constructor(name_, symbol_)`](#ERC20-constructor-string-string-)
    
*   [`name()`](#ERC20-name--)
    
*   [`symbol()`](#ERC20-symbol--)
    
*   [`decimals()`](#ERC20-decimals--)
    
*   [`totalSupply()`](#ERC20-totalSupply--)
    
*   [`balanceOf(account)`](#ERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](#ERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](#ERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](#ERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](#ERC20-transferFrom-address-address-uint256-)
    
*   [`increaseAllowance(spender, addedValue)`](#ERC20-increaseAllowance-address-uint256-)
    
*   [`decreaseAllowance(spender, subtractedValue)`](#ERC20-decreaseAllowance-address-uint256-)
    
*   [`_transfer(sender, recipient, amount)`](#ERC20-_transfer-address-address-uint256-)
    
*   [`_mint(account, amount)`](#ERC20-_mint-address-uint256-)
    
*   [`_burn(account, amount)`](#ERC20-_burn-address-uint256-)
    
*   [`_approve(owner, spender, amount)`](#ERC20-_approve-address-address-uint256-)
    
*   [`_setupDecimals(decimals_)`](#ERC20-_setupDecimals-uint8-)
    
*   [`_beforeTokenTransfer(from, to, amount)`](#ERC20-_beforeTokenTransfer-address-address-uint256-)
    

Events

IERC20

*   [`Transfer(from, to, value)`](#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval-address-address-uint256-)
    

#### [](#ERC20-constructor-string-string-)
`constructor(string name_, string symbol_)` public

Sets the values for [`name`](#ERC20-name--)
 and [`symbol`](#ERC20-symbol--)
, initializes [`decimals`](#ERC20-decimals--)
 with a default value of 18.

To select a different value for [`decimals`](#ERC20-decimals--)
, use [`_setupDecimals`](#ERC20-_setupDecimals-uint8-)
.

All three of these values are immutable: they can only be set once during construction.

#### [](#ERC20-name--)
`name() → string` public

Returns the name of the token.

#### [](#ERC20-symbol--)
`symbol() → string` public

Returns the symbol of the token, usually a shorter version of the name.

#### [](#ERC20-decimals--)
`decimals() → uint8` public

Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`).

Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value [`ERC20`](#ERC20)
 uses, unless [`_setupDecimals`](#ERC20-_setupDecimals-uint8-)
 is called.

|     |     |
| --- | --- |
|     | This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including [`IERC20.balanceOf`](#IERC20-balanceOf-address-)<br> and [`IERC20.Transfer`](#IERC20-Transfer-address-address-uint256-)<br>. |

#### [](#ERC20-totalSupply--)
`totalSupply() → uint256` public

See [`IERC20.totalSupply`](#IERC20-totalSupply--)
.

#### [](#ERC20-balanceOf-address-)
`balanceOf(address account) → uint256` public

See [`IERC20.balanceOf`](#IERC20-balanceOf-address-)
.

#### [](#ERC20-transfer-address-uint256-)
`transfer(address recipient, uint256 amount) → bool` public

See [`IERC20.Transfer`](#IERC20-Transfer-address-address-uint256-)
.

Requirements:

*   `recipient` cannot be the zero address.
    
*   the caller must have a balance of at least `amount`.
    

#### [](#ERC20-allowance-address-address-)
`allowance(address owner, address spender) → uint256` public

See [`IERC20.allowance`](#IERC20-allowance-address-address-)
.

#### [](#ERC20-approve-address-uint256-)
`approve(address spender, uint256 amount) → bool` public

See [`IERC20.approve`](#IERC20-approve-address-uint256-)
.

Requirements:

*   `spender` cannot be the zero address.
    

#### [](#ERC20-transferFrom-address-address-uint256-)
`transferFrom(address sender, address recipient, uint256 amount) → bool` public

See [`IERC20.transferFrom`](#IERC20-transferFrom-address-address-uint256-)
.

Emits an [`Approval`](#IERC20-Approval-address-address-uint256-)
 event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of [`ERC20`](#ERC20)
.

Requirements:

*   `sender` and `recipient` cannot be the zero address.
    
*   `sender` must have a balance of at least `amount`.
    
*   the caller must have allowance for `sender`'s tokens of at least `amount`.
    

#### [](#ERC20-increaseAllowance-address-uint256-)
`increaseAllowance(address spender, uint256 addedValue) → bool` public

Atomically increases the allowance granted to `spender` by the caller.

This is an alternative to [`approve`](#ERC20-approve-address-uint256-)
 that can be used as a mitigation for problems described in [`IERC20.approve`](#IERC20-approve-address-uint256-)
.

Emits an [`Approval`](#IERC20-Approval-address-address-uint256-)
 event indicating the updated allowance.

Requirements:

*   `spender` cannot be the zero address.
    

#### [](#ERC20-decreaseAllowance-address-uint256-)
`decreaseAllowance(address spender, uint256 subtractedValue) → bool` public

Atomically decreases the allowance granted to `spender` by the caller.

This is an alternative to [`approve`](#ERC20-approve-address-uint256-)
 that can be used as a mitigation for problems described in [`IERC20.approve`](#IERC20-approve-address-uint256-)
.

Emits an [`Approval`](#IERC20-Approval-address-address-uint256-)
 event indicating the updated allowance.

Requirements:

*   `spender` cannot be the zero address.
    
*   `spender` must have allowance for the caller of at least `subtractedValue`.
    

#### [](#ERC20-_transfer-address-address-uint256-)
`_transfer(address sender, address recipient, uint256 amount)` internal

Moves tokens `amount` from `sender` to `recipient`.

This is internal function is equivalent to [`transfer`](#ERC20-transfer-address-uint256-)
, and can be used to e.g. implement automatic token fees, slashing mechanisms, etc.

Emits a [`transfer`](#ERC20-transfer-address-uint256-)
 event.

Requirements:

*   `sender` cannot be the zero address.
    
*   `recipient` cannot be the zero address.
    
*   `sender` must have a balance of at least `amount`.
    

#### [](#ERC20-_mint-address-uint256-)
`_mint(address account, uint256 amount)` internal

Creates `amount` tokens and assigns them to `account`, increasing the total supply.

Emits a [`transfer`](#ERC20-transfer-address-uint256-)
 event with `from` set to the zero address.

Requirements:

*   `to` cannot be the zero address.
    

#### [](#ERC20-_burn-address-uint256-)
`_burn(address account, uint256 amount)` internal

Destroys `amount` tokens from `account`, reducing the total supply.

Emits a [`transfer`](#ERC20-transfer-address-uint256-)
 event with `to` set to the zero address.

Requirements:

*   `account` cannot be the zero address.
    
*   `account` must have at least `amount` tokens.
    

#### [](#ERC20-_approve-address-address-uint256-)
`_approve(address owner, address spender, uint256 amount)` internal

Sets `amount` as the allowance of `spender` over the `owner` s tokens.

This internal function is equivalent to `approve`, and can be used to e.g. set automatic allowances for certain subsystems, etc.

Emits an [`Approval`](#IERC20-Approval-address-address-uint256-)
 event.

Requirements:

*   `owner` cannot be the zero address.
    
*   `spender` cannot be the zero address.
    

#### [](#ERC20-_setupDecimals-uint8-)
`_setupDecimals(uint8 decimals_)` internal

Sets [`decimals`](#ERC20-decimals--)
 to a value other than the default one of 18.

|     |     |
| --- | --- |
|     | This function should only be called from the constructor. Most applications that interact with token contracts will not expect [`decimals`](#ERC20-decimals--)<br> to ever change, and may work incorrectly if it does. |

#### [](#ERC20-_beforeTokenTransfer-address-address-uint256-)
`_beforeTokenTransfer(address from, address to, uint256 amount)` internal

Hook that is called before any transfer of tokens. This includes minting and burning.

Calling conditions:

*   when `from` and `to` are both non-zero, `amount` of `from`'s tokens will be to transferred to `to`.
    
*   when `from` is zero, `amount` tokens will be minted for `to`.
    
*   when `to` is zero, `amount` of `from`'s tokens will be burned.
    
*   `from` and `to` are never both zero.
    

To learn more about hooks, head to [Using Hooks](../../extending-contracts#using-hooks)
.

[](#extensions)
Extensions
--------------------------

### [](#ERC20Snapshot)
`ERC20Snapshot`

This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and total supply at the time are recorded for later access.

This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting. In naive implementations it’s possible to perform a "double spend" attack by reusing the same balance from different accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be used to create an efficient ERC20 forking mechanism.

Snapshots are created by the internal [`_snapshot`](#ERC20Snapshot-_snapshot--)
 function, which will emit the [`Snapshot`](#ERC20Snapshot-Snapshot-uint256-)
 event and return a snapshot id. To get the total supply at the time of a snapshot, call the function [`totalSupplyAt`](#ERC20Snapshot-totalSupplyAt-uint256-)
 with the snapshot id. To get the balance of an account at the time of a snapshot, call the [`balanceOfAt`](#ERC20Snapshot-balanceOfAt-address-uint256-)
 function with the snapshot id and the account address.

#### [](#gas_costs)
Gas Costs

Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much smaller since identical balances in subsequent snapshots are stored as a single entry.

There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent transfers will have normal cost until the next snapshot, and so on.

Functions

*   [`_snapshot()`](#ERC20Snapshot-_snapshot--)
    
*   [`balanceOfAt(account, snapshotId)`](#ERC20Snapshot-balanceOfAt-address-uint256-)
    
*   [`totalSupplyAt(snapshotId)`](#ERC20Snapshot-totalSupplyAt-uint256-)
    
*   [`_beforeTokenTransfer(from, to, amount)`](#ERC20Snapshot-_beforeTokenTransfer-address-address-uint256-)
    

ERC20

*   [`constructor(name_, symbol_)`](#ERC20-constructor-string-string-)
    
*   [`name()`](#ERC20-name--)
    
*   [`symbol()`](#ERC20-symbol--)
    
*   [`decimals()`](#ERC20-decimals--)
    
*   [`totalSupply()`](#ERC20-totalSupply--)
    
*   [`balanceOf(account)`](#ERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](#ERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](#ERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](#ERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](#ERC20-transferFrom-address-address-uint256-)
    
*   [`increaseAllowance(spender, addedValue)`](#ERC20-increaseAllowance-address-uint256-)
    
*   [`decreaseAllowance(spender, subtractedValue)`](#ERC20-decreaseAllowance-address-uint256-)
    
*   [`_transfer(sender, recipient, amount)`](#ERC20-_transfer-address-address-uint256-)
    
*   [`_mint(account, amount)`](#ERC20-_mint-address-uint256-)
    
*   [`_burn(account, amount)`](#ERC20-_burn-address-uint256-)
    
*   [`_approve(owner, spender, amount)`](#ERC20-_approve-address-address-uint256-)
    
*   [`_setupDecimals(decimals_)`](#ERC20-_setupDecimals-uint8-)
    

Events

*   [`Snapshot(id)`](#ERC20Snapshot-Snapshot-uint256-)
    

IERC20

*   [`Transfer(from, to, value)`](#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval-address-address-uint256-)
    

#### [](#ERC20Snapshot-_snapshot--)
`_snapshot() → uint256` internal

Creates a new snapshot and returns its snapshot id.

Emits a [`Snapshot`](#ERC20Snapshot-Snapshot-uint256-)
 event that contains the same id.

[`_snapshot`](#ERC20Snapshot-_snapshot--)
 is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a set of accounts, for example using [`AccessControl`](../access#AccessControl)
, or it may be open to the public.

|     |     |
| --- | --- |
|     | While an open way of calling [`_snapshot`](#ERC20Snapshot-_snapshot--)<br> is required for certain trust minimization mechanisms such as forking, you must consider that it can potentially be used by attackers in two ways.<br><br>First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs section above.<br><br>We haven’t measured the actual numbers; if this is something you’re interested in please reach out to us. |

#### [](#ERC20Snapshot-balanceOfAt-address-uint256-)
`balanceOfAt(address account, uint256 snapshotId) → uint256` public

Retrieves the balance of `account` at the time `snapshotId` was created.

#### [](#ERC20Snapshot-totalSupplyAt-uint256-)
`totalSupplyAt(uint256 snapshotId) → uint256` public

Retrieves the total supply at the time `snapshotId` was created.

#### [](#ERC20Snapshot-_beforeTokenTransfer-address-address-uint256-)
`_beforeTokenTransfer(address from, address to, uint256 amount)` internal

#### [](#ERC20Snapshot-Snapshot-uint256-)
`Snapshot(uint256 id)` event

Emitted by [`_snapshot`](#ERC20Snapshot-_snapshot--)
 when a snapshot identified by `id` is created.

### [](#ERC20Pausable)
`ERC20Pausable`

ERC20 token with pausable token transfers, minting and burning.

Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug.

Functions

*   [`_beforeTokenTransfer(from, to, amount)`](#ERC20Pausable-_beforeTokenTransfer-address-address-uint256-)
    

Pausable

*   [`constructor()`](../utils#Pausable-constructor--)
    
*   [`paused()`](../utils#Pausable-paused--)
    
*   [`_pause()`](../utils#Pausable-_pause--)
    
*   [`_unpause()`](../utils#Pausable-_unpause--)
    

ERC20

*   [`name()`](#ERC20-name--)
    
*   [`symbol()`](#ERC20-symbol--)
    
*   [`decimals()`](#ERC20-decimals--)
    
*   [`totalSupply()`](#ERC20-totalSupply--)
    
*   [`balanceOf(account)`](#ERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](#ERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](#ERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](#ERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](#ERC20-transferFrom-address-address-uint256-)
    
*   [`increaseAllowance(spender, addedValue)`](#ERC20-increaseAllowance-address-uint256-)
    
*   [`decreaseAllowance(spender, subtractedValue)`](#ERC20-decreaseAllowance-address-uint256-)
    
*   [`_transfer(sender, recipient, amount)`](#ERC20-_transfer-address-address-uint256-)
    
*   [`_mint(account, amount)`](#ERC20-_mint-address-uint256-)
    
*   [`_burn(account, amount)`](#ERC20-_burn-address-uint256-)
    
*   [`_approve(owner, spender, amount)`](#ERC20-_approve-address-address-uint256-)
    
*   [`_setupDecimals(decimals_)`](#ERC20-_setupDecimals-uint8-)
    

Events

Pausable

*   [`Paused(account)`](../utils#Pausable-Paused-address-)
    
*   [`Unpaused(account)`](../utils#Pausable-Unpaused-address-)
    

IERC20

*   [`Transfer(from, to, value)`](#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval-address-address-uint256-)
    

#### [](#ERC20Pausable-_beforeTokenTransfer-address-address-uint256-)
`_beforeTokenTransfer(address from, address to, uint256 amount)` internal

See [`ERC20._beforeTokenTransfer`](#ERC20-_beforeTokenTransfer-address-address-uint256-)
.

Requirements:

*   the contract must not be paused.
    

### [](#ERC20Burnable)
`ERC20Burnable`

Extension of [`ERC20`](#ERC20)
 that allows token holders to destroy both their own tokens and those that they have an allowance for, in a way that can be recognized off-chain (via event analysis).

Functions

*   [`burn(amount)`](#ERC20Burnable-burn-uint256-)
    
*   [`burnFrom(account, amount)`](#ERC20Burnable-burnFrom-address-uint256-)
    

ERC20

*   [`constructor(name_, symbol_)`](#ERC20-constructor-string-string-)
    
*   [`name()`](#ERC20-name--)
    
*   [`symbol()`](#ERC20-symbol--)
    
*   [`decimals()`](#ERC20-decimals--)
    
*   [`totalSupply()`](#ERC20-totalSupply--)
    
*   [`balanceOf(account)`](#ERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](#ERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](#ERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](#ERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](#ERC20-transferFrom-address-address-uint256-)
    
*   [`increaseAllowance(spender, addedValue)`](#ERC20-increaseAllowance-address-uint256-)
    
*   [`decreaseAllowance(spender, subtractedValue)`](#ERC20-decreaseAllowance-address-uint256-)
    
*   [`_transfer(sender, recipient, amount)`](#ERC20-_transfer-address-address-uint256-)
    
*   [`_mint(account, amount)`](#ERC20-_mint-address-uint256-)
    
*   [`_burn(account, amount)`](#ERC20-_burn-address-uint256-)
    
*   [`_approve(owner, spender, amount)`](#ERC20-_approve-address-address-uint256-)
    
*   [`_setupDecimals(decimals_)`](#ERC20-_setupDecimals-uint8-)
    
*   [`_beforeTokenTransfer(from, to, amount)`](#ERC20-_beforeTokenTransfer-address-address-uint256-)
    

Events

IERC20

*   [`Transfer(from, to, value)`](#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval-address-address-uint256-)
    

#### [](#ERC20Burnable-burn-uint256-)
`burn(uint256 amount)` public

Destroys `amount` tokens from the caller.

See [`ERC20._burn`](#ERC20-_burn-address-uint256-)
.

#### [](#ERC20Burnable-burnFrom-address-uint256-)
`burnFrom(address account, uint256 amount)` public

Destroys `amount` tokens from `account`, deducting from the caller’s allowance.

See [`ERC20._burn`](#ERC20-_burn-address-uint256-)
 and [`ERC20.allowance`](#ERC20-allowance-address-address-)
.

Requirements:

*   the caller must have allowance for `accounts`'s tokens of at least `amount`.
    

### [](#ERC20Capped)
`ERC20Capped`

Extension of [`ERC20`](#ERC20)
 that adds a cap to the supply of tokens.

Functions

*   [`constructor(cap_)`](#ERC20Capped-constructor-uint256-)
    
*   [`cap()`](#ERC20Capped-cap--)
    
*   [`_beforeTokenTransfer(from, to, amount)`](#ERC20Capped-_beforeTokenTransfer-address-address-uint256-)
    

ERC20

*   [`name()`](#ERC20-name--)
    
*   [`symbol()`](#ERC20-symbol--)
    
*   [`decimals()`](#ERC20-decimals--)
    
*   [`totalSupply()`](#ERC20-totalSupply--)
    
*   [`balanceOf(account)`](#ERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](#ERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](#ERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](#ERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](#ERC20-transferFrom-address-address-uint256-)
    
*   [`increaseAllowance(spender, addedValue)`](#ERC20-increaseAllowance-address-uint256-)
    
*   [`decreaseAllowance(spender, subtractedValue)`](#ERC20-decreaseAllowance-address-uint256-)
    
*   [`_transfer(sender, recipient, amount)`](#ERC20-_transfer-address-address-uint256-)
    
*   [`_mint(account, amount)`](#ERC20-_mint-address-uint256-)
    
*   [`_burn(account, amount)`](#ERC20-_burn-address-uint256-)
    
*   [`_approve(owner, spender, amount)`](#ERC20-_approve-address-address-uint256-)
    
*   [`_setupDecimals(decimals_)`](#ERC20-_setupDecimals-uint8-)
    

Events

IERC20

*   [`Transfer(from, to, value)`](#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval-address-address-uint256-)
    

#### [](#ERC20Capped-constructor-uint256-)
`constructor(uint256 cap_)` internal

Sets the value of the `cap`. This value is immutable, it can only be set once during construction.

#### [](#ERC20Capped-cap--)
`cap() → uint256` public

Returns the cap on the token’s total supply.

#### [](#ERC20Capped-_beforeTokenTransfer-address-address-uint256-)
`_beforeTokenTransfer(address from, address to, uint256 amount)` internal

See [`ERC20._beforeTokenTransfer`](#ERC20-_beforeTokenTransfer-address-address-uint256-)
.

Requirements:

*   minted tokens must not cause the total supply to go over the cap.
    

[](#utilities)
Utilities
------------------------

### [](#SafeERC20)
`SafeERC20`

Wrappers around ERC20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(…​)`, etc.

Functions

*   [`safeTransfer(token, to, value)`](#SafeERC20-safeTransfer-contract-IERC20-address-uint256-)
    
*   [`safeTransferFrom(token, from, to, value)`](#SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256-)
    
*   [`safeApprove(token, spender, value)`](#SafeERC20-safeApprove-contract-IERC20-address-uint256-)
    
*   [`safeIncreaseAllowance(token, spender, value)`](#SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-)
    
*   [`safeDecreaseAllowance(token, spender, value)`](#SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-)
    

#### [](#SafeERC20-safeTransfer-contract-IERC20-address-uint256-)
`safeTransfer(contract IERC20 token, address to, uint256 value)` internal

#### [](#SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256-)
`safeTransferFrom(contract IERC20 token, address from, address to, uint256 value)` internal

#### [](#SafeERC20-safeApprove-contract-IERC20-address-uint256-)
`safeApprove(contract IERC20 token, address spender, uint256 value)` internal

Deprecated. This function has issues similar to the ones found in [`IERC20.approve`](#IERC20-approve-address-uint256-)
, and its usage is discouraged.

Whenever possible, use [`safeIncreaseAllowance`](#SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-)
 and [`safeDecreaseAllowance`](#SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-)
 instead.

#### [](#SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-)
`safeIncreaseAllowance(contract IERC20 token, address spender, uint256 value)` internal

#### [](#SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-)
`safeDecreaseAllowance(contract IERC20 token, address spender, uint256 value)` internal

### [](#TokenTimelock)
`TokenTimelock`

A token holder contract that will allow a beneficiary to extract the tokens after a given release time.

Useful for simple vesting schedules like "advisors get all of their tokens after 1 year".

Functions

*   [`constructor(token_, beneficiary_, releaseTime_)`](#TokenTimelock-constructor-contract-IERC20-address-uint256-)
    
*   [`token()`](#TokenTimelock-token--)
    
*   [`beneficiary()`](#TokenTimelock-beneficiary--)
    
*   [`releaseTime()`](#TokenTimelock-releaseTime--)
    
*   [`release()`](#TokenTimelock-release--)
    

#### [](#TokenTimelock-constructor-contract-IERC20-address-uint256-)
`constructor(contract IERC20 token_, address beneficiary_, uint256 releaseTime_)` public

#### [](#TokenTimelock-token--)
`token() → contract IERC20` public

#### [](#TokenTimelock-beneficiary--)
`beneficiary() → address` public

#### [](#TokenTimelock-releaseTime--)
`releaseTime() → uint256` public

#### [](#TokenTimelock-release--)
`release()` public

[← Drafts](/contracts/3.x/api/drafts)

[ERC 721 →](/contracts/3.x/api/token/ERC721)




 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes non-standard functions like `increase_allowance`.

    #[starknet::interface]
    trait ERC20ABI<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
        fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool;
        fn decrease_allowance(
            ref self: TState, spender: ContractAddress, subtracted_value: u256
        ) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> felt252;
        fn symbol(self: @DualCaseERC20) -> felt252;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    trait IERC20Camel<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, snake_selector: felt252, camel_selector: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, snake_selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, camel_selector, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Overview](/contracts-cairo/0.8.0-beta.0/)

[Upgrades →](/contracts-cairo/0.8.0-beta.0/upgrades)




 Presets - OpenZeppelin Docs       

Presets
=======

List of "ready-to-deploy" presets available and their corresponding class hashes.

|     |     |
| --- | --- |
|     | Class hashes were computed using [cairo 2.3.1](https://crates.io/crates/cairo-lang-compiler/2.3.1)<br>. |

 
| Name | Compiled Class Hash |
| --- | --- |
| `[Account.cairo](api/account#Account) ` | `0x016c6081eb34ad1e0c5513234ed0c025b3c7f305902d291bad534cd6474c85bc` |
| `[ERC20.cairo](api/erc20#ERC20) ` | `0x01d7085cee580ba542cdb5709bda80ebfe8bdede664261a3e6af92994d9a1de7` |
| `[ERC721.cairo](api/erc721#ERC721) ` | `0x04376782cbcd20a05f8e742e96150757383dab737ab3e791b8505ad856756907` |

To understand the compiled class hash term, check [Cairo and Sierra](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/cairo-and-sierra/)
.

|     |     |
| --- | --- |
|     | [starkli](https://book.starkli.rs/introduction)<br> class-hash command can be used to compute the class hash from a compiled artifact. |

|     |     |
| --- | --- |
|     | To obtain the artifact using [scarb](https://docs.swmansion.com/scarb)<br>, set the `casm = true` option under `[[target.starknet-contract]]` in the `Scarb.toml` file. |

[← Components](/contracts-cairo/0.8.0/components)

[Interfaces and Dispatchers →](/contracts-cairo/0.8.0/interfaces)




 Writing GSN-capable contracts - OpenZeppelin Docs       

Writing GSN-capable contracts
=============================

The [Gas Station Network](https://gsn.openzeppelin.com)
 allows you to build apps where you pay for your users transactions, so they do not need to hold Ether to pay for gas, easing their onboarding process. In this guide, we will learn how to write smart contracts that can receive transactions from the GSN, by using OpenZeppelin Contracts.

If you’re new to the GSN, you probably want to first take a look at the [overview of the system](../../learn/sending-gasless-transactions)
 to get a clearer picture of how gasless transactions are achieved. Otherwise, strap in!

[](#receiving_a_relayed_call)
Receiving a Relayed Call
------------------------------------------------------

The first step to writing a recipient is to inherit from our GSNRecipient contract. If you’re also inheriting from other contracts, such as ERC20, this will work just fine: adding GSNRecipient will make all of your token functions GSN-callable.

    import "@openzeppelin/contracts/GSN/GSNRecipient.sol";
    
    contract MyContract is GSNRecipient, ... {
    
    }

### [](#msg_sender_and_msg_data)
`msg.sender` and `msg.data`

There’s only one extra detail you need to take care of when working with GSN recipient contracts: _you must never use `msg.sender` or `msg.data` directly_. On relayed calls, `msg.sender` will be `RelayHub` instead of your user! This doesn’t mean however you won’t be able to retrieve your users' addresses: `GSNRecipient` provides two functions, `_msgSender()` and `_msgData()`, which are drop-in replacements for `msg.sender` and `msg.data` while taking care of the low-level details. As long as you use these two functions instead of the original getters, you’re good to go!

|     |     |
| --- | --- |
|     | Third-party contracts you inherit from may not use these replacement functions, making them unsafe to use when mixed with `GSNRecipient`. If in doubt, head on over to our [support forum](https://forum.openzeppelin.com/c/support)<br>. |

### [](#accepting_and_charging)
Accepting and Charging

Unlike regular contract function calls, each relayed call has an additional number of steps it must go through, which are functions of the `IRelayRecipient` interface `RelayHub` will call on your contract. `GSNRecipient` includes this interface but no implementation: most of writing a recipient involves handling these function calls. They are designed to provide flexibility, but basic recipients can safely ignore most of them while still being secure and sound.

The OpenZeppelin Contracts provide a number of tried-and-tested approaches for you to use out of the box, but you should still have a basic idea of what’s going on under the hood.

#### [](#acceptrelayedcall)
`acceptRelayedCall`

First, RelayHub will ask your recipient contract if it wants to receive a relayed call. Recall that you will be charged for incurred gas costs by the relayer, so you should only accept calls that you’re willing to pay for!

        function acceptRelayedCall(
            address relay,
            address from,
            bytes calldata encodedFunction,
            uint256 transactionFee,
            uint256 gasPrice,
            uint256 gasLimit,
            uint256 nonce,
            bytes calldata approvalData,
            uint256 maxPossibleCharge
        ) external view returns (uint256, bytes memory);

There are multiple ways to make this work, including:

1.  having a whitelist of trusted users
    
2.  only accepting calls to an onboarding function
    
3.  charging users in tokens (possibly issued by you)
    
4.  delegating the acceptance logic off-chain
    

All relayed call requests can be rejected at no cost to the recipient.

In this function, you return a number indicating whether you accept the call (0) or not (any other number). You can also return some arbitrary data that will get passed along to the following two functions (pre and post) as an execution context.

### [](#pre_and_postrelayedcall)
pre and postRelayedCall

After a relayed call is accepted, RelayHub will give your contract two opportunities to charge your user for their call, perform some bookkeeping, etc.: _before_ and _after_ the actual relayed call is made. These functions are aptly named `preRelayedCall` and `postRelayedCall`.

    function preRelayedCall(bytes calldata context) external returns (bytes32);

`preRelayedCall` will inform you of the maximum cost the call may have, and can be used to charge the user in advance. This is useful if the user may spend their allowance as part of the call, so you can lock some funds here.

        function postRelayedCall(
            bytes calldata context,
            bool success,
            uint256 actualCharge,
            bytes32 preRetVal
        ) external;

`postRelayedCall` will give you an accurate estimate of the transaction cost, making it a natural place to charge users. It will also let you know if the relayed call reverted or not. This allows you, for instance, to not charge users for reverted calls - but remember that you will be charged by the relayer nonetheless.

These functions allow you to implement, for instance, a flow where you charge your users for the relayed transactions in a custom token. You can lock some of their tokens in `pre`, and execute the actual charge in `post`. This is similar to how gas fees work in Ethereum: the network first locks enough ETH to pay for the transaction’s gas limit at its gas price, and then pays for what it actually spent.

[](#further_reading)
Further reading
------------------------------------

Read our [guide on the payment strategies](gsn-strategies)
 pre-built and shipped in OpenZeppelin Contracts, or check out [the API reference of the GSN base contracts](api/GSN)
.

[← ERC1155](/contracts/3.x/erc1155)

[Strategies →](/contracts/3.x/gsn-strategies)




 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#Ownable)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControl)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#Ownable)
`Ownable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::Ownable;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

Embeddable Functions

OwnableImpl

*   [`owner(self)`](#Ownable-owner)
    
*   [`transfer_ownership(self, new_owner)`](#Ownable-transfer_ownership)
    
*   [`renounce_ownership(self)`](#Ownable-renounce_ownership)
    

camelCase Support

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#Ownable-transferOwnership)
    
*   [`renounceOwnership(self)`](#Ownable-renounceOwnership)
    

Internal Functions

InternalImpl

*   [`initializer(self, owner)`](#Ownable-initializer)
    
*   [`assert_only_owner(self)`](#Ownable-assert_only_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#Ownable-_transfer_ownership)
    

Events

*   [`OwnershipTransferred(previous_owner, new_owner)`](#Ownable-OwnershipTransferred)
    

#### [](#Ownable-Embeddable-Functions)
Embeddable Functions

#### [](#Ownable-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#Ownable-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#Ownable-OwnershipTransferred)
 event.

#### [](#Ownable-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#Ownable-camelCase-Support)
camelCase Support

#### [](#Ownable-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#Ownable-transfer_ownership)
.

#### [](#Ownable-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#Ownable-renounce_ownership)
.

#### [](#Ownable-Internal-Functions)
Internal Functions

#### [](#Ownable-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#Ownable-OwnershipTransferred)
 event.

#### [](#Ownable-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#Ownable-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#Ownable-OwnershipTransferred)
 event.

#### [](#Ownable-Events)
Events

#### [](#Ownable-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/05429e4fd34a250ce7a01450190c53275e5c1c0b/src/access/accesscontrol/interface.cairo#L10)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControl-_set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControl)
`AccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControl;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControl-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [\_set\_role\_admin](#AccessControl-_set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

Embeddable Functions

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControl-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControl-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControl-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControl-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControl-renounce_role)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](#AccessControl-supports_interface)
    

camelCase Support

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControl-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControl-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControl-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControl-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControl-renounceRole)
    

Internal Functions

InternalImpl

*   [`initializer(self)`](#AccessControl-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControl-assert_only_role)
    
*   [`_set_role_admin(self, role, admin_role)`](#AccessControl-_set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControl-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControl-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControl-RoleRevoked)
    

#### [](#AccessControl-Embeddable-Functions)
Embeddable Functions

#### [](#AccessControl-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControl-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControl-_set_role_admin)
.

#### [](#AccessControl-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControl-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControl-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControl-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControl-camelCase-Support)
camelCase Support

#### [](#AccessControl-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControl-has_role)
.

#### [](#AccessControl-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControl-get_role_admin)
.

#### [](#AccessControl-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControl-grant_role)
.

#### [](#AccessControl-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControl-revoke_role)
.

#### [](#AccessControl-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControl-renounce_role)
.

#### [](#AccessControl-Internal-Functions)
Internal Functions

#### [](#AccessControl-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControl-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControl-_set_role_admin)
`_set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControl-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControl-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControl-Events)
Events

#### [](#AccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access Control](/contracts-cairo/0.8.0-beta.1/access)

[ERC20 →](/contracts-cairo/0.8.0-beta.1/erc20)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

Access control—​that is, "who is allowed to do this thing"--is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Ownable](#ownable)
    
    *   [Quickstart](#quickstart)
        
    *   [Ownable library API](#ownable_library_api)
        
    *   [Ownable events](#ownable_events)
        
    
*   [AccessControl](#accesscontrol)
    
    *   [Usage](#usage)
        
    *   [Granting and revoking roles](#granting_and_revoking_roles)
        
    *   [Creating role identifiers](#creating_role_identifiers)
        
    *   [AccessControl library API](#accesscontrol_library_api)
        
    *   [AccessControl events](#accesscontrol_events)
        
    

[](#ownable)
Ownable
--------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 for implementing ownership in your contracts.

### [](#quickstart)
Quickstart

Integrating [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [initializer](#initializer)
 like this:

    from openzeppelin.access.ownable.library import Ownable
    
    @constructor
    func constructor{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(owner: felt):
        Ownable.initializer(owner)
        return ()
    end

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    from openzeppelin.access.ownable.library import Ownable
    
    func protected_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        Ownable.assert_only_owner()
        return ()
    end

### [](#ownable_library_api)
Ownable library API

    func initializer(owner: felt):
    end
    
    func assert_only_owner():
    end
    
    func owner() -> (owner: felt):
    end
    
    func transfer_ownership(new_owner: felt):
    end
    
    func renounce_ownership():
    end
    
    func _transfer_ownership(new_owner: felt):
    end

#### [](#initializer)
`initializer`

Initializes Ownable access control and should be called in the implementing contract’s constructor. Assigns `owner` as the initial owner address of the contract.

This must be called only once.

Parameters:

    owner: felt

Returns: None.

#### [](#assert_only_owner)
`assert_only_owner`

Reverts if called by any account other than the owner. In case of renounced ownership, any call from the default zero address will also be reverted.

Parameters: None.

Returns: None.

#### [](#owner)
`owner`

Returns the address of the current owner.

Parameters: None.

Returns:

    owner: felt

#### [](#transfer_ownership)
`transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

#### [](#renounce_ownership)
`renounce_ownership`

Leaves the contract without owner. It will not be possible to call functions with `assert_only_owner` anymore. Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters: None.

Returns: None.

#### [](#transfer-ownership-internal)
`_transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). [`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

### [](#ownable_events)
Ownable events

    func OwnershipTransferred(previousOwner: felt, newOwner: felt):
    end

#### [](#ownershiptransferred)
OwnershipTransferred

Emitted when ownership of a contract is transferred from `previousOwner` to `newOwner`.

Parameters:

    previousOwner: felt
    newOwner: felt

[](#accesscontrol)
AccessControl
--------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [assert\_only\_owner](#assert_only_owner)
. This check can be enforced through [assert\_only\_role](#assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role (see [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers).

Here’s a simple example of implementing `AccessControl` on a portion of an [ERC20 token contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 which defines and sets the 'minter' role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](#accesscontrol)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](#ownable)
. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens, and by using `assert_only_role`:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt,
            burner: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        AccessControl._grant_role(BURNER_ROLE, burner)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses `_grant_role`, an [`internal`](extensibility#the_pattern)
 function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `assert_only_role` check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the `grant_role` and `revoke_role` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_set_role_admin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    from openzeppelin.utils.constants import DEFAULT_ADMIN_ROLE
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            admin: felt,
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
    
        AccessControl._grant_role(DEFAULT_ADMIN_ROLE, admin)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

The following example uses the [AccessControl mock contract](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/AccessControl.cairo)
 which exposes the role management functions. To grant and revoke roles in Python, for example:

    MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    # grants MINTER_ROLE and BURNER_ROLE to account1 and account2 respectively
    await signer.send_transactions(
        admin, [\
            (accesscontrol.contract_address, 'grantRole', [MINTER_ROLE, account1.contract_address]),\
            (accesscontrol.contract_address, 'grantRole', [BURNER_ROLE, account2.contract_address])\
        ]
    )
    
    # revokes MINTER_ROLE from account1
    await signer.send_transaction(
        admin,
        accesscontrol.contract_address,
        'revokeRole',
        [MINTER_ROLE, account1.contract_address]
    )

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier. For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements store a maximum of 252 bits. Even further, a declared _constant_ field element in a StarkNet contract stores even less (see [cairo\_constants](https://github.com/starkware-libs/cairo-lang/blob/167b28bcd940fd25ea3816204fa882a0b0a49603/src/starkware/cairo/lang/cairo_constants.py#L1)
). With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   using the first or last 251 bits of keccak256 hash digests
    
*   using Cairo’s [hash2](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash.cairo)
    

### [](#accesscontrol_library_api)
AccessControl library API

    func initializer():
    end
    
    func assert_only_role(role: felt):
    end
    
    func has_role(role: felt, user: felt) -> (has_role: felt):
    end
    
    func get_role_admin(role: felt) -> (admin: felt):
    end
    
    func grant_role(role: felt, user: felt):
    end
    
    func revoke_role(role: felt, user: felt):
    end
    
    func renounce_role(role: felt, user: felt):
    end
    
    func _grant_role(role: felt, user: felt):
    end
    
    func _revoke_role(role: felt, user: felt):
    end
    
    func _set_role_admin(role: felt, admin_role: felt):
    end

#### [](#initializer-accesscontrol)
`initializer`

Initializes AccessControl and should be called in the implementing contract’s constructor.

This must only be called once.

Parameters: None.

Returns: None.

#### [](#assert_only_role)
`assert_only_role`

Checks that an account has a specific role. Reverts with a message including the required role.

Parameters:

    role: felt

Returns: None.

#### [](#has_role)
has\_role

Returns `TRUE` if `user` has been granted `role`, `FALSE` otherwise.

Parameters:

    role: felt
    user: felt

Returns:

    has_role: felt

#### [](#get_role_admin)
`get_role_admin`

Returns the admin role that controls `role`. See [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
.

To change a role’s admin, use [`_set_role_admin`](#set_role_admin)
.

Parameters:

    role: felt

Returns:

    admin: felt

#### [](#grant_role)
`grant_role`

Grants `role` to `user`.

If `user` had not been already granted `role`, emits a [RoleGranted](#rolegranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revoke_role)
`revoke_role`

Revokes `role` from `user`.

If `user` had been granted `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#renounce_role)
`renounce_role`

Revokes `role` from the calling `user`.

Roles are often managed via [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling `user` had been revoked `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must be `user`.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#grantrole-internal)
`_grant_role`

Grants `role` to `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleGranted](#rolegranted)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revokerole-internal)
`_revoke_role`

Revokes `role` from `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleRevoked](#rolerevoked)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#setroleadmin)
`_set_role_admin`

[`internal`](extensibility#the_pattern)
 function that sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#roleadminchanged)
 event.

Parameters:

    role: felt
    admin_role: felt

Returns: None.

### [](#accesscontrol_events)
AccessControl events

    func RoleGranted(role: felt, account: felt, sender: felt):
    end
    
    func RoleRevoked(role: felt, account: felt, sender: felt):
    end
    
    func RoleAdminChanged(
        role: felt,
        previousAdminRole: felt,
        newAdminRole: felt
      ):
    end

#### [](#rolegranted)
`RoleGranted`

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

Parameters:

    role: felt
    account: felt
    sender: felt

#### [](#rolerevoked)
`RoleRevoked`

Emitted when account is revoked role.

`sender` is the account that originated the contract call:

*   if using [revoke\_role](#revoke_role)
    , it is the admin role bearer
    
*   if using [renounce\_role](#renounce_role)
    , it is the role bearer (i.e. `account`).
    

    role: felt
    account: felt
    sender: felt

#### [](#roleadminchanged)
`RoleAdminChanged`

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite `RoleAdminChanged` not being emitted signaling this.

    role: felt
    previousAdminRole: felt
    newAdminRole: felt

[← Accounts](/contracts-cairo/0.4.0b/accounts)

[ERC20 →](/contracts-cairo/0.4.0b/erc20)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

In different blockchains, multiple patterns have been developed for making a contract upgradeable including the widely adopted proxy patterns.

Starknet has native upgradeability through a syscall that updates the contract source code, removing the need for proxies.

[](#replacing_contract_classes)
Replacing contract classes
----------------------------------------------------------

To better comprehend how upgradeability works in Starknet, it’s important to understand the difference between a contract and its contract class.

[Contract Classes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-classes/)
 represent the source code of a program. All contracts are associated to a class, and many contracts can be instances of the same one. Classes are usually represented by a [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
, and before a contract of a class can be deployed, the class hash needs to be declared.

### [](#replace_class_syscall)
`replace_class_syscall`

The `[replace_class](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#replace_class) ` syscall allows a contract to update its source code by replacing its class hash once deployed.

    /// Upgrades the contract source code to the new contract class.
    fn _upgrade(new_class_hash: ClassHash) {
        assert(!new_class_hash.is_zero(), 'Class hash cannot be zero');
        starknet::replace_class_syscall(new_class_hash).unwrap();
    }

|     |     |
| --- | --- |
|     | If a contract is deployed without this mechanism, its class hash can still be replaced through [library calls](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#library_call)<br>. |

[](#upgradeable_module)
`Upgradeable` module
--------------------------------------------

OpenZeppelin Contracts for Cairo provides [Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/upgrades/upgradeable.cairo)
 to add upgradeability support to your contracts.

### [](#usage)
Usage

Upgrades are often very sensitive operations, and some form of access control is usually required to avoid unauthorized upgrades. The [Ownable](access#ownership_and_ownable)
 module is used in this example.

|     |     |
| --- | --- |
|     | We will be using the following module to implement the [IUpgradeable](api/upgrades#IUpgradeable)<br> interface described in the API Reference section. |

    #[starknet::contract]
    mod UpgradeableContract {
        use openzeppelin::access::ownable::Ownable;
        use openzeppelin::upgrades::Upgradeable;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::ClassHash;
        use starknet::ContractAddress;
    
        #[storage]
        struct Storage {}
    
        #[constructor]
        fn constructor(self: @ContractState, owner: ContractAddress) {
            let mut unsafe_state = Ownable::unsafe_new_contract_state();
            Ownable::InternalImpl::initializer(ref unsafe_state, owner);
        }
    
        #[external(v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                // This function can only be called by the owner
                let ownable_state = Ownable::unsafe_new_contract_state();
                Ownable::InternalImpl::assert_only_owner(@ownable_state);
    
                // Replace the class hash upgrading the contract
                let mut upgradeable_state = Upgradeable::unsafe_new_contract_state();
                Upgradeable::InternalImpl::_upgrade(ref upgradeable_state, new_class_hash);
            }
        }
    
        (...)
    }

[](#proxies_and_starknet)
Proxies and Starknet
----------------------------------------------

Proxies enable different patterns such as upgrades and clones. But since Starknet achieves the same in different ways is that there’s no support to implement them.

In the case of contract upgrades, it is achieved by simply changing the contract’s class hash. As of clones, contracts already are like clones of the class they implement.

Implementing a proxy pattern in Starknet has an important limitation: there is no fallback mechanism to be used for redirecting every potential function call to the implementation. This means that a generic proxy contract can’t be implemented. Instead, a limited proxy contract can implement specific functions that forward their execution to another contract class. This can still be useful for example to upgrade the logic of some functions.

[← Interfaces and Dispatchers](/contracts-cairo/0.8.0-beta.1/interfaces)

[API Reference →](/contracts-cairo/0.8.0-beta.1/api/upgrades)




 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/access/ownable/ownable.cairo)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#AccessControl-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::Ownable as ownable_component;
        use starknet::ContractAddress;
    
        component!(path: ownable_component, storage: ownable, event: OwnableEvent);
    
        #[abi(embed_v0)]
        impl OwnableImpl = ownable_component::OwnableImpl<ContractState>;
        #[abi(embed_v0)]
        impl OwnableCamelOnlyImpl =
            ownable_component::OwnableCamelOnlyImpl<ContractState>;
        impl InternalImpl = ownable_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: ownable_component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: ownable_component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `Ownable` implementation:

    trait IOwnable {
        /// Returns the current owner.
        fn owner() -> ContractAddress;
    
        /// Transfers the ownership from the current owner to a new owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#Ownable-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControl-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing `AccessControl` on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControl as accesscontrol_component;
        use openzeppelin::introspection::src5::SRC5 as src5_component;
        use openzeppelin::token::erc20::ERC20;
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: accesscontrol_component, storage: accesscontrol, event: AccessControlEvent);
        component!(path: src5_component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl AccessControlImpl =
            accesscontrol_component::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5Impl = src5_component::SRC5Impl<ContractState>;
        impl AccessControlInternalImpl = accesscontrol_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: accesscontrol_component::Storage,
            #[substorage(v0)]
            src5: src5_component::Storage,
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: accesscontrol_component::Event,
            #[flat]
            SRC5Event: src5_component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20 related initialization
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref erc20_state, name, symbol);
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, initial_supply);
    
            // AccessControl related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControl)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#Ownable)
. Where `AccessControl` shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControl as accesscontrol_component;
        use openzeppelin::introspection::src5::SRC5 as src5_component;
        use openzeppelin::token::erc20::ERC20;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: accesscontrol_component, storage: accesscontrol, event: AccessControlEvent);
        component!(path: src5_component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl AccessControlImpl =
            accesscontrol_component::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5Impl = src5_component::SRC5Impl<ContractState>;
        impl AccessControlInternalImpl = accesscontrol_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: accesscontrol_component::Storage,
            #[substorage(v0)]
            src5: src5_component::Storage,
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: accesscontrol_component::Event,
            #[flat]
            SRC5Event: src5_component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20 related initialization
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref erc20_state, name, symbol);
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, initial_supply);
    
            // AccessControl related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_burn(ref erc20_state, account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControl-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControl-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControl-grant_role)
 and [`revoke_role`](api/access#AccessControl-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControl-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControl as accesscontrol_component;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5 as src5_component;
        use openzeppelin::token::erc20::ERC20;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: accesscontrol_component, storage: accesscontrol, event: AccessControlEvent);
        component!(path: src5_component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl AccessControlImpl =
            accesscontrol_component::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5Impl = src5_component::SRC5Impl<ContractState>;
        impl AccessControlInternalImpl = accesscontrol_component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20 related initialization
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref erc20_state, name, symbol);
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, initial_supply);
    
            // AccessControl related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_burn(ref erc20_state, account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControl` implementation:

    trait IAccessControl {
        /// Returns whether the account has the role or not.
        fn has_role(role: felt252, account: ContractAddress) -> bool;
    
        /// Returns the adming role that controls `role`.
        fn get_role_admin(role: felt252) -> felt252;
    
        /// Grants `role` to `account`.
        fn grant_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from `account`.
        fn revoke_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from self.
        fn renounce_role(role: felt252, account: ContractAddress);
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← API Reference](/contracts-cairo/0.8.0-beta.0/api/account)

[API Reference →](/contracts-cairo/0.8.0-beta.0/api/access)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. The `ERC721.cairo` contract implements an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC721](#ierc721)
    
*   [ERC721 Compatibility](#erc721_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC721 URIs](#interpreting_erc721_uris)
        
    *   [ERC721Received](#erc721received)
        
        *   [IERC721Receiver](#ierc721receiver)
            
        
    *   [Supporting Interfaces](#supporting_interfaces)
        
    *   [Ready\_to\_Use Presets](#ready_to_use_presets)
        
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC721MintableBurnable](#erc721mintableburnable)
        
    *   [ERC721MintablePausable](#erc721mintablepausable)
        
    *   [ERC721EnumerableMintableBurnable](#erc721enumerablemintableburnable)
        
        *   [IERC721Enumerable](#ierc721enumerable)
            
        
    *   [ERC721Metadata](#erc721metadata)
        
        *   [IERC721Metadata](#ierc721metadata)
            
        
    
*   [Utilities](#utilities)
    
    *   [ERC721Holder](#erc721_holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC721`](#ierc721_api)
        
        *   [`balanceOf`](#balanceof)
            
        *   [`ownerOf`](#ownerof)
            
        *   [`safeTransferFrom`](#safetransferfrom)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        *   [`setApprovalForAll`](#setapprovalforall)
            
        *   [`getApproved`](#getapproved)
            
        *   [`isApprovedForAll`](#isapprovedforall)
            
        
    *   [Events](#events)
        
        *   [`Approval (event)`](#approval_event)
            
        *   [`ApprovalForAll (event)`](#approvalforall_event)
            
        *   [`Transfer (event)`](#transfer_event)
            
        
    *   [`IERC721Metadata`](#ierc721metadata)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`tokenURI`](#tokenuri)
            
        
    *   [`IERC721Enumerable`](#ierc721enumerable)
        
        *   [`totalSupply`](#totalsupply)
            
        *   [`tokenByIndex`](#tokenbyindex)
            
        *   [`tokenOfOwnerByIndex`](#tokenofownerbyindex)
            
        
    *   [`IERC721Receiver`](#ierc721receiver_api)
        
        *   [`onERC721Received`](#onerc721received)
            
        
    

[](#ierc721)
IERC721
--------------------

    @contract_interface
    namespace IERC721:
        func balanceOf(owner: felt) -> (balance: Uint256):
        end
    
        func ownerOf(tokenId: Uint256) -> (owner: felt):
        end
    
        func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    
        func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
        func approve(approved: felt, tokenId: Uint256):
        end
    
        func setApprovalForAll(operator: felt, approved: felt):
        end
    
        func getApproved(tokenId: Uint256) -> (approved: felt):
        end
    
        func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
        end
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#erc721_compatibility)
ERC721 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `tokenURI` returns a felt representation of the queried token’s URI. The EIP721 standard, however, states that the return value should be of type string. If a token’s URI is not set, the returned value is `0`. Note that URIs cannot exceed 31 characters. See [Interpreting ERC721 URIs](#interpreting_erc721_uris)
    
*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Solidity’s selector calculations. See [Supporting Interfaces](#supporting_interfaces)
    
*   `safeTransferFrom` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721. The difference between both functions consists of accepting `data` as an argument. Because function overloading is currently not possible in Cairo, `safeTransferFrom` by default accepts the `data` argument. If `data` is not used, simply insert `0`.
    
*   `safeTransferFrom` is specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, it accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`
    
*   `ERC165.register_interface` allows contracts to set and communicate which interfaces they support. This follows OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) must support ERC165 by registering the `IERC721Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC721 transfers
    
*   `ERC721Enumerable` tracks the total number of tokens with the `all_tokens` and `all_tokens_len` storage variables mimicking the array of the Solidity implementation.
    

[](#usage)
Usage
----------------

Use cases go from artwork, digital collectibles, physical property, and many more.

To show a standard use case, we’ll use the `ERC721Mintable` preset which allows for only the owner to `mint` and `burn` tokens. To create a token you need to first deploy both Account and ERC721 contracts respectively. As most StarkNet contracts, ERC721 expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it.

Considering that the ERC721 constructor method looks like this:

    func constructor(
        name: felt,          # Token name as Cairo short string
        symbol: felt,        # Token symbol as Cairo short string
        owner: felt          # Address designated as the contract owner
    ):

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc721 = await starknet.deploy(
        "contracts/token/erc721/presets/ERC721Mintable.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),                       # name\
            str_to_felt("TKN"),                         # symbol\
            account.contract_address                    # owner\
        ]
    )

To mint a non-fungible token, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    tokenId = uint(1)
    
    await signer.send_transaction(
        account, erc721.contract_address, 'mint', [\
            recipient_address,\
            *tokenId\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `transferFrom` and `safeTransferFrom` to transfer NFTs. If using `transferFrom`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.**

The `safeTransferFrom` method incorporates the following conditional logic:

1.  if the calling address is an account contract, the token transfer will behave as if `transferFrom` was called
    
2.  if the calling address is not an account contract, the safe function will check that the contract supports ERC721 tokens
    

The current implementation of `safeTansferFrom` checks for `onERC721Received` and requires that the recipient contract supports ERC165 and exposes the `supportsInterface` method. See [ERC721Received](#erc721received)
.

### [](#interpreting_erc721_uris)
Interpreting ERC721 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard set in [EIP721](https://eips.ethereum.org/EIPS/eip-721)<br>. Therefore, this library’s ERC721 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC721, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc721.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc721.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc721received)
ERC721Received

In order to be sure a contract can safely accept ERC721 tokens, said contract must implement the `ERC721_Receiver` interface (as expressed in the EIP721 specification). Methods such as `safeTransferFrom` and `safeMint` call the recipient contract’s `onERC721Received` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. `safeTransferFrom` requires a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC721 implementation requires that all contracts that support safe ERC721 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC721Receiver` magic value `0x150b7a02` (which invokes `onERC721Received`). If the recipient contract supports the `IAccount` magic value `0x50b70dcb`, `supportsInterface` should return `TRUE`. Otherwise, `safeTransferFrom` should fail.

#### [](#ierc721receiver)
IERC721Receiver

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

    @contract_interface
    namespace IERC721Receiver:
        func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
        end
    end

### [](#supporting_interfaces)
Supporting Interfaces

In order to ensure EVM/StarkNet compatibility, this ERC721 implementation does not calculate interface identifiers. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

Further, this implementation stores supported interfaces in a mapping (similar to OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
).

### [](#ready_to_use_presets)
Ready-to-Use Presets

ERC721 presets have been created to allow for quick deployments as-is. To be as explicit as possible, each preset includes the additional features they offer in the contract name. For example:

*   `ERC721MintableBurnable` includes `mint` and `burn`
    
*   `ERC721MintablePausable` includes `mint`, `pause`, and `unpause`
    
*   `ERC721EnumerableMintableBurnable` includes `mint`, `burn`, and [IERC721Enumerable](#ierc721enumerable)
     methods
    

Ready-to-use presets are a great option for testing and prototyping. See [Presets](#presets)
.

[](#extensibility)
Extensibility
--------------------------------

Following the [contracts extensibility pattern](extensibility)
, this implementation is set up to include all ERC721 related storage and business logic under a namespace. Developers should be mindful of manually exposing the required methods from the namespace to comply with the standard interface. This is already done in the [preset contracts](#presets)
; however, additional functionality can be added. For instance, you could:

*   Implement a pausing mechanism
    
*   Add roles such as _owner_ or _minter_
    
*   Modify the `transferFrom` function to mimic the [`_beforeTokenTransfer` and `_afterTokenTransfer` hooks](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L335)
    

Just be sure that the exposed `external` methods invoke their imported function logic a la `approve` invokes `ERC721.approve`. As an example, see below.

    from openzeppelin.token.erc721.library import ERC721
    
    @external
    func approve{
            pedersen_ptr: HashBuiltin*,
            syscall_ptr: felt*,
            range_check_ptr
        }(to: felt, tokenId: Uint256):
        ERC721.approve(to, tokenId)
        return()
    end

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset includes a contract owner, which is set in the `constructor`, to offer simple access control on sensitive methods such as `mint` and `burn`.

### [](#erc721mintableburnable)
ERC721MintableBurnable

The `ERC721MintableBurnable` preset offers a quick and easy setup for creating NFTs. The contract owner can create tokens with `mint`, whereas token owners can destroy their tokens with `burn`.

### [](#erc721mintablepausable)
ERC721MintablePausable

The `ERC721MintablePausable` preset creates a contract with pausable token transfers and minting capabilities. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug. In this preset, only the contract owner can `mint`, `pause`, and `unpause`.

### [](#erc721enumerablemintableburnable)
ERC721EnumerableMintableBurnable

The `ERC721EnumerableMintableBurnable` preset adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This allows contracts to publish its full list of NFTs and make them discoverable.

In regard to implementation, contracts should expose the following view methods:

*   `ERC721Enumerable.total_supply`
    
*   `ERC721Enumerable.token_by_index`
    
*   `ERC721Enumerable.token_of_owner_by_index`
    

In order for the tokens to be correctly indexed, the contract should also use the following methods (which supercede some of the base `ERC721` methods):

*   `ERC721Enumerable.transfer_from`
    
*   `ERC721Enumerable.safe_transfer_from`
    
*   `ERC721Enumerable._mint`
    
*   `ERC721Enumerable._burn`
    

#### [](#ierc721enumerable)
IERC721Enumerable

    @contract_interface
    namespace IERC721Enumerable:
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
        end
    
        func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
        end
    end

### [](#erc721metadata)
ERC721Metadata

The `ERC721Metadata` extension allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

We follow OpenZeppelin’s Solidity approach of integrating the Metadata methods `name`, `symbol`, and `tokenURI` into all ERC721 implementations. If preferred, a contract can be created that does not import the Metadata methods from the `ERC721` library. Note that the `IERC721Metadata` interface id should be removed from the constructor as well.

#### [](#ierc721metadata)
IERC721Metadata

    @contract_interface
    namespace IERC721Metadata:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
        end
    end

[](#utilities)
Utilities
------------------------

### [](#erc721holder)
ERC721Holder

Implementation of the `IERC721Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC721.safeTransferFrom`, `IERC721.approve` or `IERC721.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC721Received](#erc721received)

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc721_api)
IERC721 API

    func balanceOf(owner: felt) -> (balance: Uint256):
    end
    
    func ownerOf(tokenId: Uint256) -> (owner: felt):
    end
    
    func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    end
    
    func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
    func approve(approved: felt, tokenId: Uint256):
    end
    
    func setApprovalForAll(operator: felt, approved: felt):
    end
    
    func getApproved(tokenId: Uint256) -> (approved: felt):
    end
    
    func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
    end

#### [](#balanceof)
`balanceOf`

Returns the number of tokens in `owner`'s account.

Parameters:

    owner: felt

Returns:

    balance: Uint256

#### [](#ownerof)
`ownerOf`

Returns the owner of the `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    owner: felt

#### [](#safetransferfrom)
`safeTransferFrom`

Safely transfers `tokenId` token from `from_` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [ERC721Received](#erc721received)
.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#transferfrom)
`transferFrom`

Transfers `tokenId` token from `from_` to `to`. **The caller is responsible to confirm that `to` is capable of receiving NFTs or else they may be permanently lost**.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

Returns: None.

#### [](#approve)
`approve`

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Emits an [Approval](#approval_event)
 event.

Parameters:

    to: felt
    tokenId: Uint256

Returns: None.

#### [](#getapproved)
`getApproved`

Returns the account approved for `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    operator: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.

Emits an [ApprovalForAll](#approvalforall_event)
 event.

Parameters:

    operator: felt

Returns: None.

#### [](#isapprovedforall)
`isApprovedForAll`

Returns if the `operator` is allowed to manage all of the assets of `owner`.

Parameters:

    owner: felt
    operator: felt

Returns:

    isApproved: felt

### [](#events)
Events

#### [](#approval_event)
`Approval (Event)`

Emitted when `owner` enables `approved` to manage the `tokenId` token.

Parameters:

    owner: felt
    approved: felt
    tokenId: Uint256

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    owner: felt
    operator: felt
    approved: felt

#### [](#transfer_event)
`Transfer (Event)`

Emitted when `tokenId` token is transferred from `from_` to `to`.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

* * *

### [](#ierc721metadata_api)
IERC721Metadata API

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
    end

#### [](#name)
`name`

Returns the token collection name.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the token collection symbol.

Parameters: None.

Returns:

    symbol: felt

#### [](#tokenuri)
`tokenURI`

Returns the Uniform Resource Identifier (URI) for `tokenID` token. If the URI is not set for the `tokenId`, the return value will be `0`.

Parameters:

    tokenId: Uint256

Returns:

    tokenURI: felt

* * *

### [](#ierc721enumerable_api)
IERC721Enumerable API

    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
    end
    
    func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
    end

#### [](#totalsupply)
`totalSupply`

Returns the total amount of tokens stored by the contract.

Parameters: None

Returns:

    totalSupply: Uint256

#### [](#tokenbyindex)
`tokenByIndex`

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [balanceOf](#balanceof)
 to enumerate all of `owner`'s tokens.

Parameters:

    index: Uint256

Returns:

    tokenId: Uint256

#### [](#tokenofownerbyindex)
`tokenOfOwnerByIndex`

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [totalSupply](#totalsupply)
 to enumerate all tokens.

Parameters:

    owner: felt
    index: Uint256

Returns:

    tokenId: Uint256

* * *

### [](#ierc721receiver_api)
IERC721Receiver API

    func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
    end

#### [](#onerc721received)
`onERC721Received`

Whenever an IERC721 `tokenId` token is transferred to this non-account contract via `safeTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC20](/contracts-cairo/0.3.1/erc20)

[Security →](/contracts-cairo/0.3.1/security)




 Account - OpenZeppelin Docs       

Account
=======

Reference of interfaces, presets, and utilities related to account contracts.

[](#core)
Core
--------------

### [](#ISRC6)
`ISRC6`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/account/interface.cairo)

    use openzeppelin::account::interface::ISRC6;

Interface of the SRC6 Standard Account as defined in the [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
.

[SRC5 ID](introspection#ISRC5)

0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd

Functions

*   [`__execute__(calls)`](#ISRC6-__execute__)
    
*   [`__validate__(calls)`](#ISRC6-__validate__)
    
*   [`is_valid_signature(hash, signature)`](#ISRC6-is_valid_signature)
    

#### [](#ISRC6-Functions)
Functions

#### [](#ISRC6-__execute__)
`__execute__(calls: Array<Call>) → Array<Span<felt252>>` external

Executes the list of calls as a transaction after validation.

Returns an array with each call’s output.

|     |     |
| --- | --- |
|     | The `Call` struct is defined in [corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3)<br>. |

#### [](#ISRC6-__validate__)
`__validate__(calls: Array<Call>) → felt252` external

Validates a transaction before execution.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#ISRC6-is_valid_signature)
`is_valid_signature(hash: felt252, signature: Array<felt252>) → felt252` external

Validates whether a signature is valid or not for the given message hash.

Returns the short string `'VALID'` if valid, otherwise it reverts.

### [](#AccountComponent)
`AccountComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/account/account.cairo#L27)

    use openzeppelin::account::AccountComponent;

Account component implementing [`ISRC6`](#ISRC6)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

Embeddable Implementations

SRC6Impl

*   [`__execute__(self, calls)`](#AccountComponent-__execute__)
    
*   [`__validate__(self, calls)`](#AccountComponent-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#AccountComponent-is_valid_signature)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#AccountComponent-__validate_declare__)
    

DeployableImpl

*   [`__validate_deploy__(self, hash, signature)`](#AccountComponent-__validate_deploy__)
    

PublicKeyImpl

*   [`get_public_key(self)`](#AccountComponent-get_public_key)
    
*   [`set_public_key(self, new_public_key)`](#AccountComponent-set_public_key)
    

Embeddable Implementations (camelCase)

SRC6CamelOnlyImpl

*   [`isValidSignature(self, hash, signature)`](#AccountComponent-isValidSignature)
    

PublicKeyCamelImpl

*   [`getPublicKey(self)`](#AccountComponent-getPublicKey)
    
*   [`setPublicKey(self, newPublicKey)`](#AccountComponent-setPublicKey)
    

Internal Implementations

InternalImpl

*   [`initializer(self, public_key)`](#AccountComponent-initializer)
    
*   [`assert_only_self(self)`](#AccountComponent-assert_only_self)
    
*   [`validate_transaction(self)`](#AccountComponent-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#AccountComponent-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#AccountComponent-_is_valid_signature)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#AccountComponent-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#AccountComponent-OwnerRemoved)
    

#### [](#AccountComponent-Embeddable-Functions)
Embeddable Functions

#### [](#AccountComponent-__execute__)
`__execute__(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#AccountComponent-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#AccountComponent-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: felt252) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-get_public_key)
`get_public_key(self: @ContractState) → felt252` external

Returns the current public key of the account.

#### [](#AccountComponent-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: felt252)` external

Sets a new public key for the account. Only accesible by the account calling itself through `__execute__`.

Emits both an [OwnerRemoved](#AccountComponent-OwnerRemoved)
 and an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

#### [](#AccountComponent-camelCase-Support)
camelCase Support

#### [](#AccountComponent-isValidSignature)
`isValidSignature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-getPublicKey)
`getPublicKey(self: @ContractState) → felt252` external

See [get\_public\_key](#AccountComponent-get_public_key)
.

#### [](#AccountComponent-setPublicKey)
`setPublicKey(ref self: ContractState, newPublicKey: felt252)` external

See [set\_public\_key](#AccountComponent-set_public_key)
.

#### [](#AccountComponent-Internal-Functions)
Internal Functions

#### [](#AccountComponent-initializer)
`initializer(ref self: ComponentState, public_key: felt252)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

#### [](#AccountComponent-assert_only_self)
`assert_only_self(self: @ComponentState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#AccountComponent-validate_transaction)
`validate_transaction(self: @ComponentState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-_set_public_key)
`_set_public_key(ref self: ComponentState, new_public_key: felt252)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#AccountComponent-_is_valid_signature)
`_is_valid_signature(self: @ComponentState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account’s current public key.

#### [](#AccountComponent-Events)
Events

#### [](#AccountComponent-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#AccountComponent-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

[](#presets)
Presets
--------------------

### [](#Account)
`Account`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/presets/account.cairo)

    use openzeppelin::presets::Account;

Basic account contract leveraging [AccountComponent](#AccountComponent)
.

[Compiled class hash](../presets)

0x016c6081eb34ad1e0c5513234ed0c025b3c7f305902d291bad534cd6474c85bc

Constructor

*   [`constructor(self, public_key)`](#Account-constructor)
    

Embedded Implementations

AccountComponent

*   [`SRC6Impl`](#AccountComponent-Embeddable-Impls)
    
*   [`PublicKeyImpl`](#AccountComponent-Embeddable-Impls)
    
*   [`DeclarerImpl`](#AccountComponent-Embeddable-Impls)
    
*   [`DeployableImpl`](#AccountComponent-Embeddable-Impls)
    
*   [`SRC6CamelOnlyImpl`](#AccountComponent-Embeddable-Impls-camelCase)
    
*   [`PublicKeyCamelImpl`](#AccountComponent-Embeddable-Impls-camelCase)
    

SRC5Component

*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

#### [](#Account-constructor-section)
Constructor

#### [](#Account-constructor)
`constructor(ref self: ContractState, public_key: felt252)` constructor

Sets the account `public_key` and registers the interfaces the contract supports.

[← Accounts](/contracts-cairo/0.8.0/accounts)

[Introspection →](/contracts-cairo/0.8.0/introspection)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of methods and constants found in `openzeppelin/security/`.

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Initializable](#initializable)
    
*   [Pausable](#pausable)
    
*   [Reentrancy Guard](#reentrancy_guard)
    
*   [SafeMath](#safemath)
    
    *   [SafeUint256](#safeuint256)
        
    

[](#initializable)
Initializable
--------------------------------

The Initializable library provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to setup a contract’s initial state when a constructor cannot be used.

The recommended pattern with Initializable is to include a check that the Initializable state is `False` and invoke `initialize` in the target function like this:

    from openzeppelin.security.initializable.library import Initializable
    
    @external
    func foo{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        let (initialized) = Initializable.initialized()
        assert initialized = FALSE
    
        Initializable.initialize()
        return ()
    end

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used on one function. |

[](#pausable)
Pausable
----------------------

The Pausable library allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To use the Pausable library, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when not paused, insert `assert_not_paused`. For methods that should be available only when paused, insert `assert_paused`. For example:

    from openzeppelin.security.pausable.library import Pausable
    
    @external
    func whenNotPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_not_paused()
    
        # function body
        return ()
    end
    
    @external
    func whenPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_paused()
    
        # function body
        return ()
    end

|     |     |
| --- | --- |
|     | `pause` and `unpause` already include these assertions. In other words, `pause` cannot be invoked when already paused and vice versa. |

For a list of full implementations utilizing the Pausable library, see:

*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [`reentrancy guard`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/reentrancyguard/library.cairo)
 library exposes two methods `_start` and `_end` to protect functions against reentrancy attacks. The protected function must call `ReentrancyGuard._start` before the first function statement, and `ReentrancyGuard._end` before the return statement, as shown below:

    from openzeppelin.security.reentrancyguard.library import ReentrancyGuard
    
    func test_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
       ReentrancyGuard._start()
       # function body
       ReentrancyGuard._end()
       return ()
    end

[](#safemath)
SafeMath
----------------------

### [](#safeuint256)
SafeUint256

The SafeUint256 namespace in the [SafeMath library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/safemath/library.cairo)
 offers arithmetic for unsigned 256-bit integers (uint256) by leveraging Cairo’s Uint256 library and integrating overflow checks. Some of Cairo’s Uint256 functions do not revert upon overflows. For instance, `uint256_add` will return a bit carry when the sum exceeds 256 bits. This library includes an additional assertion ensuring values do not overflow.

Using SafeUint256 methods is rather straightforward. Simply import SafeUint256 and insert the arithmetic method like this:

    from openzeppelin.security.safemath.library import SafeUint256
    
    func add_two_uints{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        } (a: Uint256, b: Uint256) -> (c: Uint256):
        let (c: Uint256) = SafeUint256.add(a, b)
        return (c)
    end

[← ERC721](/contracts-cairo/0.3.1/erc721)

[Introspection →](/contracts-cairo/0.3.1/introspection)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

An ERC20 token contract keeps track of [_fungible_ tokens](tokens#different-kinds-of-tokens)
: any one token is exactly equal to any other token; no tokens have special rights or behavior associated with them. This makes ERC20 tokens useful for things like a **medium of exchange currency**, **voting rights**, **staking**, and more.

OpenZeppelin Contracts provides many ERC20-related contracts. On the [`API reference`](api/token/ERC20)
 you’ll find detailed information on their properties and usage.

[](#constructing-an-erc20-token-contract)
Constructing an ERC20 Token Contract
------------------------------------------------------------------------------

Using Contracts, we can easily create our own ERC20 token contract, which will be used to track _Gold_ (GLD), an internal currency in a hypothetical game.

Here’s what our GLD token might look like.

    pragma solidity ^0.5.0;
    
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
    
    contract GLDToken is ERC20, ERC20Detailed {
        constructor(uint256 initialSupply) ERC20Detailed("Gold", "GLD", 18) public {
            _mint(msg.sender, initialSupply);
        }
    }

Our contracts are often used via [inheritance](https://solidity.readthedocs.io/en/latest/contracts.html#inheritance)
, and here we’re reusing [`ERC20`](api/token/ERC20#erc20)
 for the basic standard implementation and [`ERC20Detailed`](api/token/ERC20#ERC20Detailed)
 to get the [`name`](api/token/ERC20#ERC20Detailed-name--)
, [`symbol`](api/token/ERC20#ERC20Detailed-symbol--)
, and [`decimals`](api/token/ERC20#ERC20Detailed-decimals--)
 properties. Additionally, we’re creating an `initialSupply` of tokens, which will be assigned to the address that deploys the contract.

|     |     |
| --- | --- |
|     | For a more complete discussion of ERC20 supply mechanisms, see [Creating ERC20 Supply](erc20-supply)<br>. |

That’s it! Once deployed, we will be able to query the deployer’s balance:

    > GLDToken.balanceOf(deployerAddress)
    1000

We can also [transfer](api/token/ERC20#IERC20-transfer-address-uint256-)
 these tokens to other accounts:

    > GLDToken.transfer(otherAddress, 300)
    > GLDToken.balanceOf(otherAddress)
    300
    > GLDToken.balanceOf(deployerAddress)
    700

[](#a-note-on-decimals)
A Note on `decimals`
--------------------------------------------

Often, you’ll want to be able to divide your tokens into arbitrary amounts: say, if you own `5 GLD`, you may want to send `1.5 GLD` to a friend, and keep `3.5 GLD` to yourself. Unfortunately, Solidity and the EVM do not support this behavior: only integer (whole) numbers can be used, which poses an issue. You may send `1` or `2` tokens, but not `1.5`.

To work around this, [`ERC20Detailed`](api/token/ERC20#ERC20Detailed)
 provides a [`decimals`](api/token/ERC20#ERC20Detailed-decimals--)
 field, which is used to specify how many decimal places a token has. To be able to transfer `1.5 GLD`, `decimals` must be at least `1`, since that number has a single decimal place.

How can this be achieved? It’s actually very simple: a token contract can use larger integer values, so that a balance of `50` will represent `5 GLD`, a transfer of `15` will correspond to `1.5 GLD` being sent, and so on.

It is important to understand that `decimals` is _only used for display purposes_. All arithmetic inside the contract is still performed on integers, and it is the different user interfaces (wallets, exchanges, etc.) that must adjust the displayed values according to `decimals`. The total token supply and balance of each account are not specified in `GLD`: you need to divide by `10^decimals` to get the actual `GLD` amount.

You’ll probably want to use a `decimals` value of `18`, just like Ether and most ERC20 token contracts in use, unless you have a very special reason not to. When minting tokens or transferring them around, you will be actually sending the number `num GLD * 10^decimals`.

So if you want to send `5` tokens using a token contract with 18 decimals, the the method to call will actually be:

    transfer(recipient, 5 * 10^18);

[← Tokens](/contracts/2.x/tokens)

[Creating Supply →](/contracts/2.x/erc20-supply)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

Access control—​that is, "who is allowed to do this thing"--is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Ownable](#ownable)
    
    *   [Quickstart](#quickstart)
        
    *   [Ownable library API](#ownable_library_api)
        
    *   [Ownable events](#ownable_events)
        
    
*   [AccessControl](#accesscontrol)
    
    *   [Usage](#usage)
        
    *   [Granting and revoking roles](#granting_and_revoking_roles)
        
    *   [Creating role identifiers](#creating_role_identifiers)
        
    *   [AccessControl library API](#accesscontrol_library_api)
        
    *   [AccessControl events](#accesscontrol_events)
        
    

[](#ownable)
Ownable
--------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 for implementing ownership in your contracts.

### [](#quickstart)
Quickstart

Integrating [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [initializer](#initializer)
 like this:

    from openzeppelin.access.ownable.library import Ownable
    
    @constructor
    func constructor{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(owner: felt):
        Ownable.initializer(owner)
        return ()
    end

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    from openzeppelin.access.ownable.library import Ownable
    
    func protected_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        Ownable.assert_only_owner()
        return ()
    end

### [](#ownable_library_api)
Ownable library API

    func initializer(owner: felt):
    end
    
    func assert_only_owner():
    end
    
    func owner() -> (owner: felt):
    end
    
    func transfer_ownership(new_owner: felt):
    end
    
    func renounce_ownership():
    end
    
    func _transfer_ownership(new_owner: felt):
    end

#### [](#initializer)
`initializer`

Initializes Ownable access control and should be called in the implementing contract’s constructor. Assigns `owner` as the initial owner address of the contract.

This must be called only once.

Parameters:

    owner: felt

Returns: None.

#### [](#assert_only_owner)
`assert_only_owner`

Reverts if called by any account other than the owner. In case of renounced ownership, any call from the default zero address will also be reverted.

Parameters: None.

Returns: None.

#### [](#owner)
`owner`

Returns the address of the current owner.

Parameters: None.

Returns:

    owner: felt

#### [](#transfer_ownership)
`transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

#### [](#renounce_ownership)
`renounce_ownership`

Leaves the contract without owner. It will not be possible to call functions with `assert_only_owner` anymore. Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters: None.

Returns: None.

#### [](#transfer-ownership-internal)
`_transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). [`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

### [](#ownable_events)
Ownable events

    func OwnershipTransferred(previousOwner: felt, newOwner: felt):
    end

#### [](#ownershiptransferred)
OwnershipTransferred

Emitted when ownership of a contract is transferred from `previousOwner` to `newOwner`.

Parameters:

    previousOwner: felt
    newOwner: felt

[](#accesscontrol)
AccessControl
--------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [assert\_only\_owner](#assert_only_owner)
. This check can be enforced through [assert\_only\_role](#assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role (see [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers).

Here’s a simple example of implementing `AccessControl` on a portion of an [ERC20 token contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 which defines and sets the 'minter' role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](#accesscontrol)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](#ownable)
. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens, and by using `assert_only_role`:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt,
            burner: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        AccessControl._grant_role(BURNER_ROLE, burner)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses `_grant_role`, an [`internal`](extensibility#the_pattern)
 function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `assert_only_role` check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the `grant_role` and `revoke_role` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_set_role_admin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    from openzeppelin.utils.constants import DEFAULT_ADMIN_ROLE
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            admin: felt,
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
    
        AccessControl._grant_role(DEFAULT_ADMIN_ROLE, admin)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

The following example uses the [AccessControl mock contract](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/AccessControl.cairo)
 which exposes the role management functions. To grant and revoke roles in Python, for example:

    MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    # grants MINTER_ROLE and BURNER_ROLE to account1 and account2 respectively
    await signer.send_transactions(
        admin, [\
            (accesscontrol.contract_address, 'grantRole', [MINTER_ROLE, account1.contract_address]),\
            (accesscontrol.contract_address, 'grantRole', [BURNER_ROLE, account2.contract_address])\
        ]
    )
    
    # revokes MINTER_ROLE from account1
    await signer.send_transaction(
        admin,
        accesscontrol.contract_address,
        'revokeRole',
        [MINTER_ROLE, account1.contract_address]
    )

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier. For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements store a maximum of 252 bits. Even further, a declared _constant_ field element in a StarkNet contract stores even less (see [cairo\_constants](https://github.com/starkware-libs/cairo-lang/blob/167b28bcd940fd25ea3816204fa882a0b0a49603/src/starkware/cairo/lang/cairo_constants.py#L1)
). With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   using the first or last 251 bits of keccak256 hash digests
    
*   using Cairo’s [hash2](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash.cairo)
    

### [](#accesscontrol_library_api)
AccessControl library API

    func initializer():
    end
    
    func assert_only_role(role: felt):
    end
    
    func has_role(role: felt, user: felt) -> (has_role: felt):
    end
    
    func get_role_admin(role: felt) -> (admin: felt):
    end
    
    func grant_role(role: felt, user: felt):
    end
    
    func revoke_role(role: felt, user: felt):
    end
    
    func renounce_role(role: felt, user: felt):
    end
    
    func _grant_role(role: felt, user: felt):
    end
    
    func _revoke_role(role: felt, user: felt):
    end
    
    func _set_role_admin(role: felt, admin_role: felt):
    end

#### [](#initializer-accesscontrol)
`initializer`

Initializes AccessControl and should be called in the implementing contract’s constructor.

This must only be called once.

Parameters: None.

Returns: None.

#### [](#assert_only_role)
`assert_only_role`

Checks that an account has a specific role. Reverts with a message including the required role.

Parameters:

    role: felt

Returns: None.

#### [](#has_role)
has\_role

Returns `TRUE` if `user` has been granted `role`, `FALSE` otherwise.

Parameters:

    role: felt
    user: felt

Returns:

    has_role: felt

#### [](#get_role_admin)
`get_role_admin`

Returns the admin role that controls `role`. See [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
.

To change a role’s admin, use [`_set_role_admin`](#set_role_admin)
.

Parameters:

    role: felt

Returns:

    admin: felt

#### [](#grant_role)
`grant_role`

Grants `role` to `user`.

If `user` had not been already granted `role`, emits a [RoleGranted](#rolegranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revoke_role)
`revoke_role`

Revokes `role` from `user`.

If `user` had been granted `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#renounce_role)
`renounce_role`

Revokes `role` from the calling `user`.

Roles are often managed via [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling `user` had been revoked `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must be `user`.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#grantrole-internal)
`_grant_role`

Grants `role` to `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleGranted](#rolegranted)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revokerole-internal)
`_revoke_role`

Revokes `role` from `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleRevoked](#rolerevoked)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#setroleadmin)
`_set_role_admin`

[`internal`](extensibility#the_pattern)
 function that sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#roleadminchanged)
 event.

Parameters:

    role: felt
    admin_role: felt

Returns: None.

### [](#accesscontrol_events)
AccessControl events

    func RoleGranted(role: felt, account: felt, sender: felt):
    end
    
    func RoleRevoked(role: felt, account: felt, sender: felt):
    end
    
    func RoleAdminChanged(
        role: felt,
        previousAdminRole: felt,
        newAdminRole: felt
      ):
    end

#### [](#rolegranted)
`RoleGranted`

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

Parameters:

    role: felt
    account: felt
    sender: felt

#### [](#rolerevoked)
`RoleRevoked`

Emitted when account is revoked role.

`sender` is the account that originated the contract call:

*   if using [revoke\_role](#revoke_role)
    , it is the admin role bearer
    
*   if using [renounce\_role](#renounce_role)
    , it is the role bearer (i.e. `account`).
    

    role: felt
    account: felt
    sender: felt

#### [](#roleadminchanged)
`RoleAdminChanged`

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite `RoleAdminChanged` not being emitted signaling this.

    role: felt
    previousAdminRole: felt
    newAdminRole: felt

[← Accounts](/contracts-cairo/0.3.0/accounts)

[ERC20 →](/contracts-cairo/0.3.0/erc20)




 Draft EIPs - OpenZeppelin Docs       

Draft EIPs
==========

This directory contains implementations of EIPs that are still in Draft status.

Due to their nature as drafts, the details of these contracts may change and we cannot guarantee their [stability](../releases-stability)
. Minor releases of OpenZeppelin Contracts may contain breaking changes for the contracts in this directory, which will be duly announced in the [changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md)
. The EIPs included here are used by projects in production and this may make them less likely to change significantly.

[](#cryptography)
Cryptography
------------------------------

### [](#EIP712)
`EIP712`

[EIP 712](https://eips.ethereum.org/EIPS/eip-712)
 is a standard for hashing and signing of typed structured data.

The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of `abi.encode` and `keccak256`.

This contract implements the EIP 712 domain separator ([`_domainSeparatorV4`](#EIP712-_domainSeparatorV4--)
) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA ([`_hashTypedDataV4`](#EIP712-_hashTypedDataV4-bytes32-)
).

The implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain id to protect against replay attacks on an eventual fork of the chain.

|     |     |
| --- | --- |
|     | This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method [`eth_signTypedDataV4` in MetaMask](https://docs.metamask.io/guide/signing-data.html)<br>. |

_Available since v3.4._

Functions

*   [`constructor(name, version)`](#EIP712-constructor-string-string-)
    
*   [`_domainSeparatorV4()`](#EIP712-_domainSeparatorV4--)
    
*   [`_hashTypedDataV4(structHash)`](#EIP712-_hashTypedDataV4-bytes32-)
    

#### [](#EIP712-constructor-string-string-)
`constructor(string name, string version)` internal

Initializes the domain separator and parameter caches.

The meaning of `name` and `version` is specified in [EIP 712](https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator)
:

*   `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
    
*   `version`: the current major version of the signing domain.
    

|     |     |
| --- | --- |
|     | These parameters cannot be changed except through a [smart contract upgrade](../../../learn/upgrading-smart-contracts)<br>. |

#### [](#EIP712-_domainSeparatorV4--)
`_domainSeparatorV4() → bytes32` internal

Returns the domain separator for the current chain.

#### [](#EIP712-_hashTypedDataV4-bytes32-)
`_hashTypedDataV4(bytes32 structHash) → bytes32` internal

Given an already [hashed struct](https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct)
, this function returns the hash of the fully encoded EIP712 message for this domain.

This hash can be used together with [`ECDSA.recover`](cryptography#ECDSA-recover-bytes32-uint8-bytes32-bytes32-)
 to obtain the signer of a message. For example:

    bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
        keccak256("Mail(address to,string contents)"),
        mailTo,
        keccak256(bytes(mailContents))
    )));
    address signer = ECDSA.recover(digest, signature);

[](#erc_20)
ERC 20
------------------

### [](#IERC20Permit)
`IERC20Permit`

Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612)
.

Adds the [`permit`](#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
 method, which can be used to change an account’s ERC20 allowance (see [`IERC20.allowance`](token/ERC20#IERC20-allowance-address-address-)
) by presenting a message signed by the account. By not relying on ``[`IERC20.approve`](token/ERC20#IERC20-approve-address-uint256-) ``, the token holder account doesn’t need to send a transaction, and thus is not required to hold Ether at all.

Functions

*   [`permit(owner, spender, value, deadline, v, r, s)`](#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
    
*   [`nonces(owner)`](#IERC20Permit-nonces-address-)
    
*   [`DOMAIN_SEPARATOR()`](#IERC20Permit-DOMAIN_SEPARATOR--)
    

#### [](#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
`permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)` external

Sets `value` as the allowance of `spender` over \`owner’s tokens, given \`owner’s signed approval.

|     |     |
| --- | --- |
|     | The same issues [`IERC20.approve`](token/ERC20#IERC20-approve-address-uint256-)<br> has related to transaction ordering also apply here. |

Emits an {Approval} event.

Requirements:

*   `spender` cannot be the zero address.
    
*   `deadline` must be a timestamp in the future.
    
*   `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments.
    
*   the signature must use `owner`'s current nonce (see [`nonces`](#IERC20Permit-nonces-address-)
    ).
    

For more information on the signature format, see the [relevant EIP section](https://eips.ethereum.org/EIPS/eip-2612#specification)
.

#### [](#IERC20Permit-nonces-address-)
`nonces(address owner) → uint256` external

Returns the current nonce for `owner`. This value must be included whenever a signature is generated for [`permit`](#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
.

Every successful call to [`permit`](#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
 increases `owner`'s nonce by one. This prevents a signature from being used multiple times.

#### [](#IERC20Permit-DOMAIN_SEPARATOR--)
`DOMAIN_SEPARATOR() → bytes32` external

Returns the domain separator used in the encoding of the signature for `permit`, as defined by [`EIP712`](#EIP712)
.

### [](#ERC20Permit)
`ERC20Permit`

Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612)
.

Adds the [`permit`](#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
 method, which can be used to change an account’s ERC20 allowance (see [`IERC20.allowance`](token/ERC20#IERC20-allowance-address-address-)
) by presenting a message signed by the account. By not relying on ``[`IERC20.approve`](token/ERC20#IERC20-approve-address-uint256-) ``, the token holder account doesn’t need to send a transaction, and thus is not required to hold Ether at all.

_Available since v3.4._

Functions

*   [`constructor(name)`](#ERC20Permit-constructor-string-)
    
*   [`permit(owner, spender, value, deadline, v, r, s)`](#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
    
*   [`nonces(owner)`](#ERC20Permit-nonces-address-)
    
*   [`DOMAIN_SEPARATOR()`](#ERC20Permit-DOMAIN_SEPARATOR--)
    

EIP712

*   [`_domainSeparatorV4()`](#EIP712-_domainSeparatorV4--)
    
*   [`_hashTypedDataV4(structHash)`](#EIP712-_hashTypedDataV4-bytes32-)
    

ERC20

*   [`name()`](token/ERC20#ERC20-name--)
    
*   [`symbol()`](token/ERC20#ERC20-symbol--)
    
*   [`decimals()`](token/ERC20#ERC20-decimals--)
    
*   [`totalSupply()`](token/ERC20#ERC20-totalSupply--)
    
*   [`balanceOf(account)`](token/ERC20#ERC20-balanceOf-address-)
    
*   [`transfer(recipient, amount)`](token/ERC20#ERC20-transfer-address-uint256-)
    
*   [`allowance(owner, spender)`](token/ERC20#ERC20-allowance-address-address-)
    
*   [`approve(spender, amount)`](token/ERC20#ERC20-approve-address-uint256-)
    
*   [`transferFrom(sender, recipient, amount)`](token/ERC20#ERC20-transferFrom-address-address-uint256-)
    
*   [`increaseAllowance(spender, addedValue)`](token/ERC20#ERC20-increaseAllowance-address-uint256-)
    
*   [`decreaseAllowance(spender, subtractedValue)`](token/ERC20#ERC20-decreaseAllowance-address-uint256-)
    
*   [`_transfer(sender, recipient, amount)`](token/ERC20#ERC20-_transfer-address-address-uint256-)
    
*   [`_mint(account, amount)`](token/ERC20#ERC20-_mint-address-uint256-)
    
*   [`_burn(account, amount)`](token/ERC20#ERC20-_burn-address-uint256-)
    
*   [`_approve(owner, spender, amount)`](token/ERC20#ERC20-_approve-address-address-uint256-)
    
*   [`_setupDecimals(decimals_)`](token/ERC20#ERC20-_setupDecimals-uint8-)
    
*   [`_beforeTokenTransfer(from, to, amount)`](token/ERC20#ERC20-_beforeTokenTransfer-address-address-uint256-)
    

Events

IERC20

*   [`Transfer(from, to, value)`](token/ERC20#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](token/ERC20#IERC20-Approval-address-address-uint256-)
    

#### [](#ERC20Permit-constructor-string-)
`constructor(string name)` internal

Initializes the [`EIP712`](#EIP712)
 domain separator using the `name` parameter, and setting `version` to `"1"`.

It’s a good idea to use the same `name` that is defined as the ERC20 token name.

#### [](#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
`permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)` public

See [`IERC20Permit.permit`](#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-)
.

#### [](#ERC20Permit-nonces-address-)
`nonces(address owner) → uint256` public

See [`IERC20Permit.nonces`](#IERC20Permit-nonces-address-)
.

#### [](#ERC20Permit-DOMAIN_SEPARATOR--)
`DOMAIN_SEPARATOR() → bytes32` external

See [`IERC20Permit.DOMAIN_SEPARATOR`](#IERC20Permit-DOMAIN_SEPARATOR--)
.

[← Cryptography](/contracts/3.x/api/cryptography)

[ERC 20 →](/contracts/3.x/api/token/ERC20)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are derived from a private key, all Starknet accounts are contracts. This means there’s no Externally Owned Account (EOA) concept on Starknet.

Instead, the network features native account abstraction and signature validation happens at the contract level.

For a general overview of account abstraction, see [Starknet’s documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/introduction/)
. A more detailed discussion on the topic can be found in [Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

|     |     |
| --- | --- |
|     | For detailed information on the usage and implementation check the [API Reference](api/account)<br> section. |

[](#standard_account_interface)
Standard Account Interface
----------------------------------------------------------

Accounts in Starknet are smart contracts, and so they can be deployed and interacted with like any other contract, and can be extended to implement any custom logic. However, an account is a special type of contract that is used to validate and execute transactions. For this reason, it must implement a set of entrypoints that the protocol uses for this execution flow. The [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 proposal defines a standard interface for accounts, supporting this execution flow and interoperability with DApps in the ecosystem.

### [](#isrc6_interface)
ISRC6 Interface

    /// Represents a call to a target contract function.
    struct Call {
        to: ContractAddress,
        selector: felt252,
        calldata: Array<felt252>
    }
    
    /// Standard Account Interface
    trait ISRC6 {
        /// Executes a transaction through the account.
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
    
        /// Asserts whether the transaction is valid to be executed.
        fn __validate__(calls: Array<Call>) -> felt252;
    
        /// Asserts whether a given signature for a given hash is valid.
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 adds the `is_valid_signature` method. This method is not used by the protocol, but it’s useful for DApps to verify the validity of signatures, supporting features like Sign In with Starknet.

SNIP-6 also defines that compliant accounts must implement the SRC5 interface following [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
, as a mechanism for detecting whether a contract is an account or not through introspection.

### [](#isrc5_interface)
ISRC5 Interface

    /// Standard Interface Detection
    trait ISRC5 {
        /// Queries if a contract implements a given interface.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 compliant accounts must return `true` when queried for the ISRC6 interface Id.

Even though these interfaces are not enforced by the protocol, it’s recommended to implement them for enabling interoperability with the ecosystem.

[](#protocol_level_methods)
Protocol-level methods
--------------------------------------------------

In this section we will describe the methods that the protocol uses for abstracting the accounts. The first two are required for enabling accounts to be used for executing transactions. The rest are optional:

1.  `__validate__` verifies the validity of the transaction to be executed. This is usually used to validate signatures, but the entrypoint implementation can be customized to feature any validation mechanism [with some limitations](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/validate_and_execute/#validate_limitations)
    .
    
2.  `__execute__` executes the transaction if the validation is successful.
    
3.  `__validate_declare__` optional entrypoint similar to `__validate__` but for transactions meant to declare other contracts.
    
4.  `__validate_deploy__` optional entrypoint similar to `__validate__` but meant for [counterfactual deployments](guides/deployment)
    .
    

|     |     |
| --- | --- |
|     | Although these entrypoints are available to the protocol for its regular transaction flow, they can also be called like any other method. |

[](#deploying_an_account)
Deploying an account
----------------------------------------------

In Starknet there are two ways of deploying smart contracts: using the `deploy_syscall` and doing counterfactual deployments. The former can be easily done with the [Universal Deployer Contract (UDC)](udc)
, a contract that wraps and exposes the `deploy_syscall` to provide arbitrary deployments through regular contract calls. But if you don’t have an account to invoke it, you will probably want to use the latter.

To do counterfactual deployments, you need to implement another protocol-level entrypoint named `__validate_deploy__`. Check the [counterfactual deployments](guides/deployment)
 guide to learn how.

[← API Reference](/contracts-cairo/0.8.1/api/access)

[API Reference →](/contracts-cairo/0.8.1/api/account)




 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/access/ownable/ownable.cairo)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#AccessControl-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::Ownable as ownable_component;
        use starknet::ContractAddress;
    
        component!(path: ownable_component, storage: ownable, event: OwnableEvent);
    
        #[abi(embed_v0)]
        impl OwnableImpl = ownable_component::OwnableImpl<ContractState>;
        #[abi(embed_v0)]
        impl OwnableCamelOnlyImpl =
            ownable_component::OwnableCamelOnlyImpl<ContractState>;
        impl InternalImpl = ownable_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: ownable_component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            OwnableEvent: ownable_component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `Ownable` implementation:

    trait IOwnable {
        /// Returns the current owner.
        fn owner() -> ContractAddress;
    
        /// Transfers the ownership from the current owner to a new owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#Ownable-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControl-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing `AccessControl` on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControl as accesscontrol_component;
        use openzeppelin::introspection::src5::SRC5 as src5_component;
        use openzeppelin::token::erc20::ERC20;
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: accesscontrol_component, storage: accesscontrol, event: AccessControlEvent);
        component!(path: src5_component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl AccessControlImpl =
            accesscontrol_component::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5Impl = src5_component::SRC5Impl<ContractState>;
        impl AccessControlInternalImpl = accesscontrol_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: accesscontrol_component::Storage,
            #[substorage(v0)]
            src5: src5_component::Storage,
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            AccessControlEvent: accesscontrol_component::Event,
            SRC5Event: src5_component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20 related initialization
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref erc20_state, name, symbol);
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, initial_supply);
    
            // AccessControl related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControl)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#Ownable)
. Where `AccessControl` shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControl as accesscontrol_component;
        use openzeppelin::introspection::src5::SRC5 as src5_component;
        use openzeppelin::token::erc20::ERC20;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: accesscontrol_component, storage: accesscontrol, event: AccessControlEvent);
        component!(path: src5_component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl AccessControlImpl =
            accesscontrol_component::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5Impl = src5_component::SRC5Impl<ContractState>;
        impl AccessControlInternalImpl = accesscontrol_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: accesscontrol_component::Storage,
            #[substorage(v0)]
            src5: src5_component::Storage,
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            AccessControlEvent: accesscontrol_component::Event,
            SRC5Event: src5_component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20 related initialization
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref erc20_state, name, symbol);
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, initial_supply);
    
            // AccessControl related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_burn(ref erc20_state, account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControl-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControl-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControl-grant_role)
 and [`revoke_role`](api/access#AccessControl-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControl-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControl as accesscontrol_component;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5 as src5_component;
        use openzeppelin::token::erc20::ERC20;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: accesscontrol_component, storage: accesscontrol, event: AccessControlEvent);
        component!(path: src5_component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl AccessControlImpl =
            accesscontrol_component::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5Impl = src5_component::SRC5Impl<ContractState>;
        impl AccessControlInternalImpl = accesscontrol_component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20 related initialization
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref erc20_state, name, symbol);
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, initial_supply);
    
            // AccessControl related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_mint(ref erc20_state, recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
    
            let mut erc20_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::_burn(ref erc20_state, account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControl` implementation:

    trait IAccessControl {
        /// Returns whether the account has the role or not.
        fn has_role(role: felt252, account: ContractAddress) -> bool;
    
        /// Returns the adming role that controls `role`.
        fn get_role_admin(role: felt252) -> felt252;
    
        /// Grants `role` to `account`.
        fn grant_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from `account`.
        fn revoke_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from self.
        fn renounce_role(role: felt252, account: ContractAddress);
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← API Reference](/contracts-cairo/0.8.0-beta.1/api/account)

[API Reference →](/contracts-cairo/0.8.0-beta.1/api/access)




 Introspection - OpenZeppelin Docs       

Introspection
=============

To smooth interoperability, often standards require smart contracts to implement [introspection mechanisms](https://en.wikipedia.org/wiki/Type_introspection)
.

In Ethereum, the [EIP165](https://eips.ethereum.org/EIPS/eip-165)
 standard defines how contracts should declare their support for a given interface, and how other contracts may query this support.

Starknet offers a similar mechanism for interface introspection defined by the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard.

[](#src5)
SRC5
--------------

Similar to its Ethereum counterpart, the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard requires contracts to implement the `supports_interface` function, which can be used by others to query if a given interface is supported:

    trait ISRC5 {
        /// Query if a contract implements an interface.
        /// Receives the interface identifier as specified in SRC-5.
        /// Returns `true` if the contract implements `interface_id`, `false` otherwise.
        fn supports_interface(interface_id: felt252) -> bool;
    }

### [](#computing_the_interface_id)
Computing the interface ID

The interface ID, as specified in the standard, is the [XOR](https://en.wikipedia.org/wiki/Exclusive_or)
 of all the [Extended Function Selectors](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#extended-function-selector)
 of the interface. We strongly advise reading the SNIP to understand the specifics of computing these extended function selectors. There are tools such as [src5-rs](https://github.com/ericnordelo/src5-rs)
 that can help with this process.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, we recommend using the SRC5 component to register support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            // Register the contract's support for the ISRC6 interface
            self.src5.register_interface(interface::ISRC6_ID);
        }
    
        (...)
    }

### [](#querying_interfaces)
Querying interfaces

Use the `supports_interface` function to query a contract’s support for a given interface.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::interface::ISRC5DispatcherTrait;
        use openzeppelin::introspection::interface::ISRC5Dispatcher;
        use starknet::ContractAddress;
    
        #[storage]
        struct Storage {}
    
        #[external(v0)]
        fn query_is_account(self: @ContractState, target: ContractAddress) -> bool {
            let dispatcher = ISRC5Dispatcher { contract_address: target };
            dispatcher.supports_interface(interface::ISRC6_ID)
        }
    }

|     |     |
| --- | --- |
|     | If you are unsure whether a contract implements SRC5 or not, you can follow the process described in [here](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#how-to-detect-if-a-contract-implements-src-5)<br>. |

[← API Reference](/contracts-cairo/0.8.1/api/account)

[Migrating ERC165 to SRC5 →](/contracts-cairo/0.8.1/guides/src5-migration)




 ERC 721 - OpenZeppelin Docs       

ERC 721
=======

|     |     |
| --- | --- |
|     | This document is better viewed at [https://docs.openzeppelin.com/contracts/api/token/erc721](https://docs.openzeppelin.com/contracts/api/token/erc721) |

This set of interfaces, contracts, and utilities are all related to the [ERC721 Non-Fungible Token Standard](https://eips.ethereum.org/EIPS/eip-721)
.

|     |     |
| --- | --- |
|     | For a walk through on how to create an ERC721 token read our [ERC721 guide](../../erc721)<br>. |

The EIP consists of three interfaces, found here as [`IERC721`](#IERC721)
, [`IERC721Metadata`](#IERC721Metadata)
, and [`IERC721Enumerable`](#IERC721Enumerable)
. Only the first one is required in a contract to be ERC721 compliant. However, all three are implemented in [`ERC721`](#ERC721)
.

Additionally, [`IERC721Receiver`](#IERC721Receiver)
 can be used to prevent tokens from becoming forever locked in contracts. Imagine sending an in-game item to an exchange address that can’t send it back!. When using [`safeTransferFrom`](#IERC721-safeTransferFrom)
, the token contract checks to see that the receiver is an [`IERC721Receiver`](#IERC721Receiver)
, which implies that it knows how to handle [`ERC721`](#ERC721)
 tokens. If you’re writing a contract that needs to receive [`ERC721`](#ERC721)
 tokens, you’ll want to include this interface.

Additionally there are multiple custom extensions, including:

*   designation of addresses that can pause token transfers for all users ([`ERC721Pausable`](#ERC721Pausable)
    ).
    
*   destruction of own tokens ([`ERC721Burnable`](#ERC721Burnable)
    ).
    

|     |     |
| --- | --- |
|     | This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC721 (such as [`_mint`](#ERC721-_mint-address-uint256-)<br>) and expose them as external functions in the way they prefer. On the other hand, [ERC721 Presets](../../erc721#Presets)<br> (such as [`ERC721PresetMinterPauserAutoId`](../presets#ERC721PresetMinterPauserAutoId)<br>) are designed using opinionated patterns to provide developers with ready to use, deployable contracts. |

[](#core)
Core
--------------

### [](#IERC721)
`IERC721`

Required interface of an ERC721 compliant contract.

Functions

*   [`balanceOf(owner)`](#IERC721-balanceOf-address-)
    
*   [`ownerOf(tokenId)`](#IERC721-ownerOf-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId)`](#IERC721-safeTransferFrom-address-address-uint256-)
    
*   [`transferFrom(from, to, tokenId)`](#IERC721-transferFrom-address-address-uint256-)
    
*   [`approve(to, tokenId)`](#IERC721-approve-address-uint256-)
    
*   [`getApproved(tokenId)`](#IERC721-getApproved-uint256-)
    
*   [`setApprovalForAll(operator, _approved)`](#IERC721-setApprovalForAll-address-bool-)
    
*   [`isApprovedForAll(owner, operator)`](#IERC721-isApprovedForAll-address-address-)
    
*   [`safeTransferFrom(from, to, tokenId, data)`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
    

IERC165

*   [`supportsInterface(interfaceId)`](../introspection#IERC165-supportsInterface-bytes4-)
    

Events

*   [`Transfer(from, to, tokenId)`](#IERC721-Transfer-address-address-uint256-)
    
*   [`Approval(owner, approved, tokenId)`](#IERC721-Approval-address-address-uint256-)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll-address-address-bool-)
    

#### [](#IERC721-balanceOf-address-)
`balanceOf(address owner) → uint256 balance` external

Returns the number of tokens in `owner`'s account.

#### [](#IERC721-ownerOf-uint256-)
`ownerOf(uint256 tokenId) → address owner` external

Returns the owner of the `tokenId` token.

Requirements:

*   `tokenId` must exist.
    

#### [](#IERC721-safeTransferFrom-address-address-uint256-)
`safeTransferFrom(address from, address to, uint256 tokenId)` external

Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.

Requirements:

*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    
*   `tokenId` token must exist and be owned by `from`.
    
*   If the caller is not `from`, it must be have been allowed to move this token by either [`approve`](#IERC721-approve-address-uint256-)
     or [`setApprovalForAll`](#IERC721-setApprovalForAll-address-bool-)
    .
    
*   If `to` refers to a smart contract, it must implement [`IERC721Receiver.onERC721Received`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
    , which is called upon a safe transfer.
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#IERC721-transferFrom-address-address-uint256-)
`transferFrom(address from, address to, uint256 tokenId)` external

Transfers `tokenId` token from `from` to `to`.

|     |     |
| --- | --- |
|     | Usage of this method is discouraged, use [`safeTransferFrom`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)<br> whenever possible. |

Requirements:

*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    
*   `tokenId` token must be owned by `from`.
    
*   If the caller is not `from`, it must be approved to move this token by either [`approve`](#IERC721-approve-address-uint256-)
     or [`setApprovalForAll`](#IERC721-setApprovalForAll-address-bool-)
    .
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#IERC721-approve-address-uint256-)
`approve(address to, uint256 tokenId)` external

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Only a single account can be approved at a time, so approving the zero address clears previous approvals.

Requirements:

*   The caller must own the token or be an approved operator.
    
*   `tokenId` must exist.
    

Emits an [`Approval`](#IERC721-Approval-address-address-uint256-)
 event.

#### [](#IERC721-getApproved-uint256-)
`getApproved(uint256 tokenId) → address operator` external

Returns the account approved for `tokenId` token.

Requirements:

*   `tokenId` must exist.
    

#### [](#IERC721-setApprovalForAll-address-bool-)
`setApprovalForAll(address operator, bool _approved)` external

Approve or remove `operator` as an operator for the caller. Operators can call [`transferFrom`](#IERC721-transferFrom-address-address-uint256-)
 or [`safeTransferFrom`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
 for any token owned by the caller.

Requirements:

*   The `operator` cannot be the caller.
    

Emits an [`ApprovalForAll`](#IERC721-ApprovalForAll-address-address-bool-)
 event.

#### [](#IERC721-isApprovedForAll-address-address-)
`isApprovedForAll(address owner, address operator) → bool` external

Returns if the `operator` is allowed to manage all of the assets of `owner`.

See [`setApprovalForAll`](#IERC721-setApprovalForAll-address-bool-)

#### [](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
`safeTransferFrom(address from, address to, uint256 tokenId, bytes data)` external

Safely transfers `tokenId` token from `from` to `to`.

Requirements:

*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    
*   `tokenId` token must exist and be owned by `from`.
    
*   If the caller is not `from`, it must be approved to move this token by either [`approve`](#IERC721-approve-address-uint256-)
     or [`setApprovalForAll`](#IERC721-setApprovalForAll-address-bool-)
    .
    
*   If `to` refers to a smart contract, it must implement [`IERC721Receiver.onERC721Received`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
    , which is called upon a safe transfer.
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#IERC721-Transfer-address-address-uint256-)
`Transfer(address from, address to, uint256 tokenId)` event

Emitted when `tokenId` token is transferred from `from` to `to`.

#### [](#IERC721-Approval-address-address-uint256-)
`Approval(address owner, address approved, uint256 tokenId)` event

Emitted when `owner` enables `approved` to manage the `tokenId` token.

#### [](#IERC721-ApprovalForAll-address-address-bool-)
`ApprovalForAll(address owner, address operator, bool approved)` event

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

### [](#IERC721Metadata)
`IERC721Metadata`

See [https://eips.ethereum.org/EIPS/eip-721](https://eips.ethereum.org/EIPS/eip-721)

Functions

*   [`name()`](#IERC721Metadata-name--)
    
*   [`symbol()`](#IERC721Metadata-symbol--)
    
*   [`tokenURI(tokenId)`](#IERC721Metadata-tokenURI-uint256-)
    

IERC721

*   [`balanceOf(owner)`](#IERC721-balanceOf-address-)
    
*   [`ownerOf(tokenId)`](#IERC721-ownerOf-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId)`](#IERC721-safeTransferFrom-address-address-uint256-)
    
*   [`transferFrom(from, to, tokenId)`](#IERC721-transferFrom-address-address-uint256-)
    
*   [`approve(to, tokenId)`](#IERC721-approve-address-uint256-)
    
*   [`getApproved(tokenId)`](#IERC721-getApproved-uint256-)
    
*   [`setApprovalForAll(operator, _approved)`](#IERC721-setApprovalForAll-address-bool-)
    
*   [`isApprovedForAll(owner, operator)`](#IERC721-isApprovedForAll-address-address-)
    
*   [`safeTransferFrom(from, to, tokenId, data)`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
    

IERC165

*   [`supportsInterface(interfaceId)`](../introspection#IERC165-supportsInterface-bytes4-)
    

Events

IERC721

*   [`Transfer(from, to, tokenId)`](#IERC721-Transfer-address-address-uint256-)
    
*   [`Approval(owner, approved, tokenId)`](#IERC721-Approval-address-address-uint256-)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll-address-address-bool-)
    

#### [](#IERC721Metadata-name--)
`name() → string` external

Returns the token collection name.

#### [](#IERC721Metadata-symbol--)
`symbol() → string` external

Returns the token collection symbol.

#### [](#IERC721Metadata-tokenURI-uint256-)
`tokenURI(uint256 tokenId) → string` external

Returns the Uniform Resource Identifier (URI) for `tokenId` token.

### [](#IERC721Enumerable)
`IERC721Enumerable`

See [https://eips.ethereum.org/EIPS/eip-721](https://eips.ethereum.org/EIPS/eip-721)

Functions

*   [`totalSupply()`](#IERC721Enumerable-totalSupply--)
    
*   [`tokenOfOwnerByIndex(owner, index)`](#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-)
    
*   [`tokenByIndex(index)`](#IERC721Enumerable-tokenByIndex-uint256-)
    

IERC721

*   [`balanceOf(owner)`](#IERC721-balanceOf-address-)
    
*   [`ownerOf(tokenId)`](#IERC721-ownerOf-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId)`](#IERC721-safeTransferFrom-address-address-uint256-)
    
*   [`transferFrom(from, to, tokenId)`](#IERC721-transferFrom-address-address-uint256-)
    
*   [`approve(to, tokenId)`](#IERC721-approve-address-uint256-)
    
*   [`getApproved(tokenId)`](#IERC721-getApproved-uint256-)
    
*   [`setApprovalForAll(operator, _approved)`](#IERC721-setApprovalForAll-address-bool-)
    
*   [`isApprovedForAll(owner, operator)`](#IERC721-isApprovedForAll-address-address-)
    
*   [`safeTransferFrom(from, to, tokenId, data)`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
    

IERC165

*   [`supportsInterface(interfaceId)`](../introspection#IERC165-supportsInterface-bytes4-)
    

Events

IERC721

*   [`Transfer(from, to, tokenId)`](#IERC721-Transfer-address-address-uint256-)
    
*   [`Approval(owner, approved, tokenId)`](#IERC721-Approval-address-address-uint256-)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll-address-address-bool-)
    

#### [](#IERC721Enumerable-totalSupply--)
`totalSupply() → uint256` external

Returns the total amount of tokens stored by the contract.

#### [](#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-)
`tokenOfOwnerByIndex(address owner, uint256 index) → uint256 tokenId` external

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [`balanceOf`](#IERC721-balanceOf-address-)
 to enumerate all of `owner`'s tokens.

#### [](#IERC721Enumerable-tokenByIndex-uint256-)
`tokenByIndex(uint256 index) → uint256` external

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [`totalSupply`](#IERC721Enumerable-totalSupply--)
 to enumerate all tokens.

### [](#ERC721)
`ERC721`

see [https://eips.ethereum.org/EIPS/eip-721](https://eips.ethereum.org/EIPS/eip-721)

Functions

*   [`constructor(name_, symbol_)`](#ERC721-constructor-string-string-)
    
*   [`balanceOf(owner)`](#ERC721-balanceOf-address-)
    
*   [`ownerOf(tokenId)`](#ERC721-ownerOf-uint256-)
    
*   [`name()`](#ERC721-name--)
    
*   [`symbol()`](#ERC721-symbol--)
    
*   [`tokenURI(tokenId)`](#ERC721-tokenURI-uint256-)
    
*   [`baseURI()`](#ERC721-baseURI--)
    
*   [`tokenOfOwnerByIndex(owner, index)`](#ERC721-tokenOfOwnerByIndex-address-uint256-)
    
*   [`totalSupply()`](#ERC721-totalSupply--)
    
*   [`tokenByIndex(index)`](#ERC721-tokenByIndex-uint256-)
    
*   [`approve(to, tokenId)`](#ERC721-approve-address-uint256-)
    
*   [`getApproved(tokenId)`](#ERC721-getApproved-uint256-)
    
*   [`setApprovalForAll(operator, approved)`](#ERC721-setApprovalForAll-address-bool-)
    
*   [`isApprovedForAll(owner, operator)`](#ERC721-isApprovedForAll-address-address-)
    
*   [`transferFrom(from, to, tokenId)`](#ERC721-transferFrom-address-address-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId)`](#ERC721-safeTransferFrom-address-address-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId, _data)`](#ERC721-safeTransferFrom-address-address-uint256-bytes-)
    
*   [`_safeTransfer(from, to, tokenId, _data)`](#ERC721-_safeTransfer-address-address-uint256-bytes-)
    
*   [`_exists(tokenId)`](#ERC721-_exists-uint256-)
    
*   [`_isApprovedOrOwner(spender, tokenId)`](#ERC721-_isApprovedOrOwner-address-uint256-)
    
*   [`_safeMint(to, tokenId)`](#ERC721-_safeMint-address-uint256-)
    
*   [`_safeMint(to, tokenId, _data)`](#ERC721-_safeMint-address-uint256-bytes-)
    
*   [`_mint(to, tokenId)`](#ERC721-_mint-address-uint256-)
    
*   [`_burn(tokenId)`](#ERC721-_burn-uint256-)
    
*   [`_transfer(from, to, tokenId)`](#ERC721-_transfer-address-address-uint256-)
    
*   [`_setTokenURI(tokenId, _tokenURI)`](#ERC721-_setTokenURI-uint256-string-)
    
*   [`_setBaseURI(baseURI_)`](#ERC721-_setBaseURI-string-)
    
*   [`_approve(to, tokenId)`](#ERC721-_approve-address-uint256-)
    
*   [`_beforeTokenTransfer(from, to, tokenId)`](#ERC721-_beforeTokenTransfer-address-address-uint256-)
    

ERC165

*   [`supportsInterface(interfaceId)`](../introspection#ERC165-supportsInterface-bytes4-)
    
*   [`_registerInterface(interfaceId)`](../introspection#ERC165-_registerInterface-bytes4-)
    

Events

IERC721

*   [`Transfer(from, to, tokenId)`](#IERC721-Transfer-address-address-uint256-)
    
*   [`Approval(owner, approved, tokenId)`](#IERC721-Approval-address-address-uint256-)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll-address-address-bool-)
    

#### [](#ERC721-constructor-string-string-)
`constructor(string name_, string symbol_)` public

Initializes the contract by setting a `name` and a `symbol` to the token collection.

#### [](#ERC721-balanceOf-address-)
`balanceOf(address owner) → uint256` public

See [`IERC721.balanceOf`](#IERC721-balanceOf-address-)
.

#### [](#ERC721-ownerOf-uint256-)
`ownerOf(uint256 tokenId) → address` public

See [`IERC721.ownerOf`](#IERC721-ownerOf-uint256-)
.

#### [](#ERC721-name--)
`name() → string` public

See [`IERC721Metadata.name`](#IERC721Metadata-name--)
.

#### [](#ERC721-symbol--)
`symbol() → string` public

See [`IERC721Metadata.symbol`](#IERC721Metadata-symbol--)
.

#### [](#ERC721-tokenURI-uint256-)
`tokenURI(uint256 tokenId) → string` public

See [`IERC721Metadata.tokenURI`](#IERC721Metadata-tokenURI-uint256-)
.

#### [](#ERC721-baseURI--)
`baseURI() → string` public

Returns the base URI set via [`_setBaseURI`](#ERC721-_setBaseURI-string-)
. This will be automatically added as a prefix in [`tokenURI`](#ERC721-tokenURI-uint256-)
 to each token’s URI, or to the token ID if no specific URI is set for that token ID.

#### [](#ERC721-tokenOfOwnerByIndex-address-uint256-)
`tokenOfOwnerByIndex(address owner, uint256 index) → uint256` public

See [`IERC721Enumerable.tokenOfOwnerByIndex`](#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-)
.

#### [](#ERC721-totalSupply--)
`totalSupply() → uint256` public

See [`IERC721Enumerable.totalSupply`](#IERC721Enumerable-totalSupply--)
.

#### [](#ERC721-tokenByIndex-uint256-)
`tokenByIndex(uint256 index) → uint256` public

See [`IERC721Enumerable.tokenByIndex`](#IERC721Enumerable-tokenByIndex-uint256-)
.

#### [](#ERC721-approve-address-uint256-)
`approve(address to, uint256 tokenId)` public

See [`IERC721.approve`](#IERC721-approve-address-uint256-)
.

#### [](#ERC721-getApproved-uint256-)
`getApproved(uint256 tokenId) → address` public

See [`IERC721.getApproved`](#IERC721-getApproved-uint256-)
.

#### [](#ERC721-setApprovalForAll-address-bool-)
`setApprovalForAll(address operator, bool approved)` public

See [`IERC721.setApprovalForAll`](#IERC721-setApprovalForAll-address-bool-)
.

#### [](#ERC721-isApprovedForAll-address-address-)
`isApprovedForAll(address owner, address operator) → bool` public

See [`IERC721.isApprovedForAll`](#IERC721-isApprovedForAll-address-address-)
.

#### [](#ERC721-transferFrom-address-address-uint256-)
`transferFrom(address from, address to, uint256 tokenId)` public

See [`IERC721.transferFrom`](#IERC721-transferFrom-address-address-uint256-)
.

#### [](#ERC721-safeTransferFrom-address-address-uint256-)
`safeTransferFrom(address from, address to, uint256 tokenId)` public

See [`IERC721.safeTransferFrom`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
.

#### [](#ERC721-safeTransferFrom-address-address-uint256-bytes-)
`safeTransferFrom(address from, address to, uint256 tokenId, bytes _data)` public

See [`IERC721.safeTransferFrom`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
.

#### [](#ERC721-_safeTransfer-address-address-uint256-bytes-)
`_safeTransfer(address from, address to, uint256 tokenId, bytes _data)` internal

Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.

`_data` is additional data, it has no specified format and it is sent in call to `to`.

This internal function is equivalent to [`safeTransferFrom`](#ERC721-safeTransferFrom-address-address-uint256-bytes-)
, and can be used to e.g. implement alternative mechanisms to perform token transfer, such as signature-based.

Requirements:

*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    
*   `tokenId` token must exist and be owned by `from`.
    
*   If `to` refers to a smart contract, it must implement [`IERC721Receiver.onERC721Received`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
    , which is called upon a safe transfer.
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#ERC721-_exists-uint256-)
`_exists(uint256 tokenId) → bool` internal

Returns whether `tokenId` exists.

Tokens can be managed by their owner or approved accounts via [`approve`](#ERC721-approve-address-uint256-)
 or [`setApprovalForAll`](#ERC721-setApprovalForAll-address-bool-)
.

Tokens start existing when they are minted (`_mint`), and stop existing when they are burned (`_burn`).

#### [](#ERC721-_isApprovedOrOwner-address-uint256-)
`_isApprovedOrOwner(address spender, uint256 tokenId) → bool` internal

Returns whether `spender` is allowed to manage `tokenId`.

Requirements:

*   `tokenId` must exist.
    

#### [](#ERC721-_safeMint-address-uint256-)
`_safeMint(address to, uint256 tokenId)` internal

Safely mints `tokenId` and transfers it to `to`.

Requirements: d\* - `tokenId` must not exist. - If `to` refers to a smart contract, it must implement [`IERC721Receiver.onERC721Received`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
, which is called upon a safe transfer.

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#ERC721-_safeMint-address-uint256-bytes-)
`_safeMint(address to, uint256 tokenId, bytes _data)` internal

Same as [`_safeMint`](#ERC721-_safeMint-address-uint256-)
, with an additional `data` parameter which is forwarded in [`IERC721Receiver.onERC721Received`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
 to contract recipients.

#### [](#ERC721-_mint-address-uint256-)
`_mint(address to, uint256 tokenId)` internal

Mints `tokenId` and transfers it to `to`.

|     |     |
| --- | --- |
|     | Usage of this method is discouraged, use [`_safeMint`](#ERC721-_safeMint-address-uint256-bytes-)<br> whenever possible |

Requirements:

*   `tokenId` must not exist.
    
*   `to` cannot be the zero address.
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#ERC721-_burn-uint256-)
`_burn(uint256 tokenId)` internal

Destroys `tokenId`. The approval is cleared when the token is burned.

Requirements:

*   `tokenId` must exist.
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#ERC721-_transfer-address-address-uint256-)
`_transfer(address from, address to, uint256 tokenId)` internal

Transfers `tokenId` from `from` to `to`. As opposed to [`transferFrom`](#ERC721-transferFrom-address-address-uint256-)
, this imposes no restrictions on msg.sender.

Requirements:

*   `to` cannot be the zero address.
    
*   `tokenId` token must be owned by `from`.
    

Emits a [`Transfer`](#IERC721-Transfer-address-address-uint256-)
 event.

#### [](#ERC721-_setTokenURI-uint256-string-)
`_setTokenURI(uint256 tokenId, string _tokenURI)` internal

Sets `_tokenURI` as the tokenURI of `tokenId`.

Requirements:

*   `tokenId` must exist.
    

#### [](#ERC721-_setBaseURI-string-)
`_setBaseURI(string baseURI_)` internal

Internal function to set the base URI for all token IDs. It is automatically added as a prefix to the value returned in [`tokenURI`](#ERC721-tokenURI-uint256-)
, or to the token ID if [`tokenURI`](#ERC721-tokenURI-uint256-)
 is empty.

#### [](#ERC721-_approve-address-uint256-)
`_approve(address to, uint256 tokenId)` internal

Approve `to` to operate on `tokenId`

Emits an [`Approval`](#IERC721-Approval-address-address-uint256-)
 event.

#### [](#ERC721-_beforeTokenTransfer-address-address-uint256-)
`_beforeTokenTransfer(address from, address to, uint256 tokenId)` internal

Hook that is called before any token transfer. This includes minting and burning.

Calling conditions:

*   When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`.
    
*   When `from` is zero, `tokenId` will be minted for `to`.
    
*   When `to` is zero, `from`'s `tokenId` will be burned.
    
*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    

To learn more about hooks, head to [Using Hooks](../../extending-contracts#using-hooks)
.

### [](#IERC721Receiver)
`IERC721Receiver`

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

Functions

*   [`onERC721Received(operator, from, tokenId, data)`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
    

#### [](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
`onERC721Received(address operator, address from, uint256 tokenId, bytes data) → bytes4` external

Whenever an [`IERC721`](#IERC721)
 `tokenId` token is transferred to this contract via [`IERC721.safeTransferFrom`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
 by `operator` from `from`, this function is called.

It must return its Solidity selector to confirm the token transfer. If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.

The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.

[](#extensions)
Extensions
--------------------------

### [](#ERC721Pausable)
`ERC721Pausable`

ERC721 token with pausable token transfers, minting and burning.

Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug.

Functions

*   [`_beforeTokenTransfer(from, to, tokenId)`](#ERC721Pausable-_beforeTokenTransfer-address-address-uint256-)
    

Pausable

*   [`constructor()`](../utils#Pausable-constructor--)
    
*   [`paused()`](../utils#Pausable-paused--)
    
*   [`_pause()`](../utils#Pausable-_pause--)
    
*   [`_unpause()`](../utils#Pausable-_unpause--)
    

ERC721

*   [`balanceOf(owner)`](#ERC721-balanceOf-address-)
    
*   [`ownerOf(tokenId)`](#ERC721-ownerOf-uint256-)
    
*   [`name()`](#ERC721-name--)
    
*   [`symbol()`](#ERC721-symbol--)
    
*   [`tokenURI(tokenId)`](#ERC721-tokenURI-uint256-)
    
*   [`baseURI()`](#ERC721-baseURI--)
    
*   [`tokenOfOwnerByIndex(owner, index)`](#ERC721-tokenOfOwnerByIndex-address-uint256-)
    
*   [`totalSupply()`](#ERC721-totalSupply--)
    
*   [`tokenByIndex(index)`](#ERC721-tokenByIndex-uint256-)
    
*   [`approve(to, tokenId)`](#ERC721-approve-address-uint256-)
    
*   [`getApproved(tokenId)`](#ERC721-getApproved-uint256-)
    
*   [`setApprovalForAll(operator, approved)`](#ERC721-setApprovalForAll-address-bool-)
    
*   [`isApprovedForAll(owner, operator)`](#ERC721-isApprovedForAll-address-address-)
    
*   [`transferFrom(from, to, tokenId)`](#ERC721-transferFrom-address-address-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId)`](#ERC721-safeTransferFrom-address-address-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId, _data)`](#ERC721-safeTransferFrom-address-address-uint256-bytes-)
    
*   [`_safeTransfer(from, to, tokenId, _data)`](#ERC721-_safeTransfer-address-address-uint256-bytes-)
    
*   [`_exists(tokenId)`](#ERC721-_exists-uint256-)
    
*   [`_isApprovedOrOwner(spender, tokenId)`](#ERC721-_isApprovedOrOwner-address-uint256-)
    
*   [`_safeMint(to, tokenId)`](#ERC721-_safeMint-address-uint256-)
    
*   [`_safeMint(to, tokenId, _data)`](#ERC721-_safeMint-address-uint256-bytes-)
    
*   [`_mint(to, tokenId)`](#ERC721-_mint-address-uint256-)
    
*   [`_burn(tokenId)`](#ERC721-_burn-uint256-)
    
*   [`_transfer(from, to, tokenId)`](#ERC721-_transfer-address-address-uint256-)
    
*   [`_setTokenURI(tokenId, _tokenURI)`](#ERC721-_setTokenURI-uint256-string-)
    
*   [`_setBaseURI(baseURI_)`](#ERC721-_setBaseURI-string-)
    
*   [`_approve(to, tokenId)`](#ERC721-_approve-address-uint256-)
    

ERC165

*   [`supportsInterface(interfaceId)`](../introspection#ERC165-supportsInterface-bytes4-)
    
*   [`_registerInterface(interfaceId)`](../introspection#ERC165-_registerInterface-bytes4-)
    

Events

Pausable

*   [`Paused(account)`](../utils#Pausable-Paused-address-)
    
*   [`Unpaused(account)`](../utils#Pausable-Unpaused-address-)
    

IERC721

*   [`Transfer(from, to, tokenId)`](#IERC721-Transfer-address-address-uint256-)
    
*   [`Approval(owner, approved, tokenId)`](#IERC721-Approval-address-address-uint256-)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll-address-address-bool-)
    

#### [](#ERC721Pausable-_beforeTokenTransfer-address-address-uint256-)
`_beforeTokenTransfer(address from, address to, uint256 tokenId)` internal

See [`ERC721._beforeTokenTransfer`](#ERC721-_beforeTokenTransfer-address-address-uint256-)
.

Requirements:

*   the contract must not be paused.
    

### [](#ERC721Burnable)
`ERC721Burnable`

ERC721 Token that can be irreversibly burned (destroyed).

Functions

*   [`burn(tokenId)`](#ERC721Burnable-burn-uint256-)
    

ERC721

*   [`constructor(name_, symbol_)`](#ERC721-constructor-string-string-)
    
*   [`balanceOf(owner)`](#ERC721-balanceOf-address-)
    
*   [`ownerOf(tokenId)`](#ERC721-ownerOf-uint256-)
    
*   [`name()`](#ERC721-name--)
    
*   [`symbol()`](#ERC721-symbol--)
    
*   [`tokenURI(tokenId)`](#ERC721-tokenURI-uint256-)
    
*   [`baseURI()`](#ERC721-baseURI--)
    
*   [`tokenOfOwnerByIndex(owner, index)`](#ERC721-tokenOfOwnerByIndex-address-uint256-)
    
*   [`totalSupply()`](#ERC721-totalSupply--)
    
*   [`tokenByIndex(index)`](#ERC721-tokenByIndex-uint256-)
    
*   [`approve(to, tokenId)`](#ERC721-approve-address-uint256-)
    
*   [`getApproved(tokenId)`](#ERC721-getApproved-uint256-)
    
*   [`setApprovalForAll(operator, approved)`](#ERC721-setApprovalForAll-address-bool-)
    
*   [`isApprovedForAll(owner, operator)`](#ERC721-isApprovedForAll-address-address-)
    
*   [`transferFrom(from, to, tokenId)`](#ERC721-transferFrom-address-address-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId)`](#ERC721-safeTransferFrom-address-address-uint256-)
    
*   [`safeTransferFrom(from, to, tokenId, _data)`](#ERC721-safeTransferFrom-address-address-uint256-bytes-)
    
*   [`_safeTransfer(from, to, tokenId, _data)`](#ERC721-_safeTransfer-address-address-uint256-bytes-)
    
*   [`_exists(tokenId)`](#ERC721-_exists-uint256-)
    
*   [`_isApprovedOrOwner(spender, tokenId)`](#ERC721-_isApprovedOrOwner-address-uint256-)
    
*   [`_safeMint(to, tokenId)`](#ERC721-_safeMint-address-uint256-)
    
*   [`_safeMint(to, tokenId, _data)`](#ERC721-_safeMint-address-uint256-bytes-)
    
*   [`_mint(to, tokenId)`](#ERC721-_mint-address-uint256-)
    
*   [`_burn(tokenId)`](#ERC721-_burn-uint256-)
    
*   [`_transfer(from, to, tokenId)`](#ERC721-_transfer-address-address-uint256-)
    
*   [`_setTokenURI(tokenId, _tokenURI)`](#ERC721-_setTokenURI-uint256-string-)
    
*   [`_setBaseURI(baseURI_)`](#ERC721-_setBaseURI-string-)
    
*   [`_approve(to, tokenId)`](#ERC721-_approve-address-uint256-)
    
*   [`_beforeTokenTransfer(from, to, tokenId)`](#ERC721-_beforeTokenTransfer-address-address-uint256-)
    

ERC165

*   [`supportsInterface(interfaceId)`](../introspection#ERC165-supportsInterface-bytes4-)
    
*   [`_registerInterface(interfaceId)`](../introspection#ERC165-_registerInterface-bytes4-)
    

Events

IERC721

*   [`Transfer(from, to, tokenId)`](#IERC721-Transfer-address-address-uint256-)
    
*   [`Approval(owner, approved, tokenId)`](#IERC721-Approval-address-address-uint256-)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll-address-address-bool-)
    

#### [](#ERC721Burnable-burn-uint256-)
`burn(uint256 tokenId)` public

Burns `tokenId`. See [`ERC721._burn`](#ERC721-_burn-uint256-)
.

Requirements:

*   The caller must own `tokenId` or be an approved operator.
    

[](#convenience)
Convenience
----------------------------

### [](#ERC721Holder)
`ERC721Holder`

Implementation of the [`IERC721Receiver`](#IERC721Receiver)
 interface.

Accepts all token transfers. Make sure the contract is able to use its token with [`IERC721.safeTransferFrom`](#IERC721-safeTransferFrom-address-address-uint256-bytes-)
, [`IERC721.approve`](#IERC721-approve-address-uint256-)
 or [`IERC721.setApprovalForAll`](#IERC721-setApprovalForAll-address-bool-)
.

Functions

*   [`onERC721Received(_, _, _, _)`](#ERC721Holder-onERC721Received-address-address-uint256-bytes-)
    

#### [](#ERC721Holder-onERC721Received-address-address-uint256-bytes-)
`onERC721Received(address, address, uint256, bytes) → bytes4` public

See [`IERC721Receiver.onERC721Received`](#IERC721Receiver-onERC721Received-address-address-uint256-bytes-)
.

Always returns `IERC721Receiver.onERC721Received.selector`.

[← ERC 20](/contracts/3.x/api/token/ERC20)

[ERC 777 →](/contracts/3.x/api/token/ERC777)




 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#OwnableComponent)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControlComponent)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#OwnableComponent)
`OwnableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::OwnableComponent;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

Embeddable Implementations

OwnableImpl

*   [`owner(self)`](#OwnableComponent-owner)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-renounce_ownership)
    

Embeddable Implementations (camelCase)

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#OwnableComponent-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-renounceOwnership)
    

Internal Implementations

InternalImpl

*   [`initializer(self, owner)`](#OwnableComponent-initializer)
    
*   [`assert_only_owner(self)`](#OwnableComponent-assert_only_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#OwnableComponent-_transfer_ownership)
    

Events

*   [`OwnershipTransferred(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferred)
    

#### [](#OwnableComponent-Embeddable-Functions)
Embeddable Functions

#### [](#OwnableComponent-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-camelCase-Support)
camelCase Support

#### [](#OwnableComponent-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#OwnableComponent-transfer_ownership)
.

#### [](#OwnableComponent-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#OwnableComponent-renounce_ownership)
.

#### [](#OwnableComponent-Internal-Functions)
Internal Functions

#### [](#OwnableComponent-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#OwnableComponent-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-Events)
Events

#### [](#OwnableComponent-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/access/accesscontrol/interface.cairo)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControlComponent)
`AccessControlComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControlComponent;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControlComponent-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

Embeddable Implementations

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControlComponent-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControlComponent-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControlComponent-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControlComponent-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControlComponent-renounce_role)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](#AccessControlComponent-supports_interface)
    

Embeddable Implementations (camelCase)

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControlComponent-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControlComponent-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControlComponent-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControlComponent-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControlComponent-renounceRole)
    

Internal Implementations

InternalImpl

*   [`initializer(self)`](#AccessControlComponent-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControlComponent-assert_only_role)
    
*   [`_set_role_admin(self, role, admin_role)`](#AccessControlComponent-_set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControlComponent-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControlComponent-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControlComponent-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControlComponent-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControlComponent-RoleRevoked)
    

#### [](#AccessControlComponent-Embeddable-Functions)
Embeddable Functions

#### [](#AccessControlComponent-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControlComponent-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#AccessControlComponent-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControlComponent-camelCase-Support)
camelCase Support

#### [](#AccessControlComponent-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControlComponent-has_role)
.

#### [](#AccessControlComponent-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControlComponent-get_role_admin)
.

#### [](#AccessControlComponent-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControlComponent-grant_role)
.

#### [](#AccessControlComponent-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControlComponent-revoke_role)
.

#### [](#AccessControlComponent-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControlComponent-renounce_role)
.

#### [](#AccessControlComponent-Internal-Functions)
Internal Functions

#### [](#AccessControlComponent-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControlComponent-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControlComponent-_set_role_admin)
`_set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControlComponent-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-Events)
Events

#### [](#AccessControlComponent-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControlComponent-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControlComponent-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access Control](/contracts-cairo/0.8.0/access)

[Accounts →](/contracts-cairo/0.8.0/accounts)




 Account - OpenZeppelin Docs       

Account
=======

Reference of interfaces, presets, and utilities related to account contracts.

[](#core)
Core
--------------

### [](#ISRC6)
`ISRC6`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/account/interface.cairo#L12)

    use openzeppelin::account::interface::ISRC6;

Interface of the SRC6 Standard Account as defined in the [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
.

[SRC5 ID](introspection#ISRC5)

0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd

Functions

*   [`__execute__(calls)`](#ISRC6-__execute__)
    
*   [`__validate__(calls)`](#ISRC6-__validate__)
    
*   [`is_valid_signature(hash, signature)`](#ISRC6-is_valid_signature)
    

#### [](#ISRC6-Functions)
Functions

#### [](#ISRC6-__execute__)
`__execute__(calls: Array<Call>) → Array<Span<felt252>>` external

Executes the list of calls as a transaction after validation.

Returns an array with each call’s output.

|     |     |
| --- | --- |
|     | The `Call` struct is defined in [corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3)<br>. |

#### [](#ISRC6-__validate__)
`__validate__(calls: Array<Call>) → felt252` external

Validates a transaction before execution.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#ISRC6-is_valid_signature)
`is_valid_signature(hash: felt252, signature: Array<felt252>) → felt252` external

Validates whether a signature is valid or not for the given message hash.

Returns the short string `'VALID'` if valid, otherwise it reverts.

### [](#Account)
`Account`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/account/account.cairo#L27)

    use openzeppelin::account::Account;

Account contract implementation extending [`ISRC6`](#ISRC6)
.

Constructor

*   [`constructor(self, _public_key)`](#Account-constructor)
    

External Functions

*   [`__validate_deploy__(self, hash, signature)`](#Account-__validate_deploy__)
    

SRC6Impl

*   [`__execute__(self, calls)`](#Account-__execute__)
    
*   [`__validate__(self, calls)`](#Account-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#Account-is_valid_signature)
    

SRC5Impl

*   [`supports_interface(self, interface_id)`](#Account-supports_interface)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#Account-__validate_declare__)
    

PublicKeyImpl

*   [`set_public_key(self, new_public_key)`](#Account-set_public_key)
    
*   [`get_public_key(self)`](#Account-get_public_key)
    

Internal Functions

InternalImpl

*   [`initializer(self, _public_key)`](#Account-initializer)
    
*   [`validate_transaction(self)`](#Account-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#Account-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#Account-_is_valid_signature)
    
*   [`assert_only_self(self)`](#Account-assert_only_self)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#Account-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#Account-OwnerRemoved)
    

#### [](#Account-Constructor)
Constructor

#### [](#Account-constructor)
`constructor(ref self: ContractState, _public_key: felt252)` constructor

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#Account-OwnerAdded)
 event.

#### [](#Account-External-Functions)
External Functions

#### [](#Account-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, _public_key: felt252) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#Account-__execute__)
`__execute__(ref self: ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#Account-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#Account-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#Account-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#Account-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#Account-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: felt252)` external

Sets a new public key for the account. Only accesible by the account calling itself through `__execute__`.

Emits both an [OwnerRemoved](#Account-OwnerRemoved)
 and an [OwnerAdded](#Account-OwnerAdded)
 event.

#### [](#Account-get_public_key)
`get_public_key(self: @ContractState) → felt252` external

Returns the current public key of the account.

#### [](#Account-Internal-Functions)
Internal Functions

#### [](#Account-initializer)
`initializer(ref self: ContractState, _public_key: felt252)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#Account-OwnerAdded)
 event.

#### [](#Account-validate_transaction)
`validate_transaction(self: @ContractState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#Account-_set_public_key)
`_set_public_key(ref self: ContractState, new_public_key: felt252)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#Account-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#Account-_is_valid_signature)
`_is_valid_signature(self: @ContractState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account current public key.

#### [](#Account-assert_only_self)
`assert_only_self(self: @ContractState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#Account-Events)
Events

#### [](#Account-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#Account-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

[← Counterfactual deployments](/contracts-cairo/0.8.0-beta.1/guides/deployment)

[Access Control →](/contracts-cairo/0.8.0-beta.1/access)









 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0/src/access/ownable/ownable.cairo)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#AccessControlComponent-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        #[abi(embed_v0)]
        impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
        #[abi(embed_v0)]
        impl OwnableCamelOnlyImpl =
            OwnableComponent::OwnableCamelOnlyImpl<ContractState>;
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `Ownable` implementation:

    trait IOwnable {
        /// Returns the current owner.
        fn owner() -> ContractAddress;
    
        /// Transfers the ownership from the current owner to a new owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#OwnableComponent-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing `AccessControl` on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControlComponent)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#OwnableComponent)
. Where `AccessControl` shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControlComponent-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControlComponent-grant_role)
 and [`revoke_role`](api/access#AccessControlComponent-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControlComponent-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControl` implementation:

    trait IAccessControl {
        /// Returns whether the account has the role or not.
        fn has_role(role: felt252, account: ContractAddress) -> bool;
    
        /// Returns the adming role that controls `role`.
        fn get_role_admin(role: felt252) -> felt252;
    
        /// Grants `role` to `account`.
        fn grant_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from `account`.
        fn revoke_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from self.
        fn renounce_role(role: felt252, account: ContractAddress);
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← Counterfactual deployments](/contracts-cairo/0.8.0/guides/deployment)

[API Reference →](/contracts-cairo/0.8.0/api/access)




 Introspection - OpenZeppelin Docs       

Introspection
=============

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [ERC165](#erc165)
    
    *   [Interface calculations](#interface_calculations)
        
    *   [Registering interfaces](#registering_interfaces)
        
    *   [Querying interfaces](#querying_interfaces)
        
    *   [IERC165](#ierc165)
        
    *   [IERC165 API Specification](#ierc165_api_specification)
        
        *   [`supportsInterface`](#supportsinterface)
            
        
    *   [ERC165 Library Functions](#erc165_library_functions)
        
        *   [`supports_interface`](#supportsinterface2)
            
        *   [`register_interface`](#register_interface)
            
        
    

[](#erc165)
ERC165
------------------

The ERC165 standard allows smart contracts to exercise [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
 on other contracts, that is, examining which functions can be called on them. This is usually referred to as a contract’s interface.

Cairo contracts, like Ethereum contracts, have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. ERC20 tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract declaring its interface can be very helpful in preventing errors.

It should be noted that the [constants library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 includes constant variables referencing all of the interface ids used in these contracts. This allows for more legible code i.e. using `IERC165_ID` instead of `0x01ffc9a7`.

### [](#interface_calculations)
Interface calculations

In order to ensure EVM/StarkNet compatibility, interface identifiers are not calculated on StarkNet. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, the contract should import the ERC165 library and register its support. It’s recommended to register interface support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    from openzeppelin.introspection.erc165.library import ERC165
    
    INTERFACE_ID = 0x12345678
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        ERC165.register_interface(INTERFACE_ID)
        return ()
    end

### [](#querying_interfaces)
Querying interfaces

To query a target contract’s support for an interface, the querying contract should call `supportsInterface` through IERC165 with the target contract’s address and the queried interface id. Here’s an example:

    from openzeppelin.introspection.erc265.IERC165 import IERC165
    
    INTERFACE_ID = 0x12345678
    
    func check_support{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            target_contract: felt,
        ) -> (success: felt):
        let (is_supported) = IERC165.supportsInterface(target_contract, INTERFACE_ID)
        return (is_supported)
    end

|     |     |
| --- | --- |
|     | `supportsInterface` is camelCased because it is an exposed contract method as part of ERC165’s interface. This differs from library methods (such as `supports_interface` from the [ERC165 library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/introspection/erc165/library.cairo)<br>) which are snake\_cased and not exposed. See the [Function names and coding style](extensibility#function_names_and_coding_style)<br> for more details. |

### [](#ierc165)
IERC165

    @contract_interface
    namespace IERC165:
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#ierc165_api_specification)
IERC165 API Specification

    func supportsInterface(interfaceId: felt) -> (success: felt):
    end

#### [](#supportsinterface)
`supportsInterface`

Returns true if this contract implements the interface defined by `interfaceId`.

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#erc165_library_functions)
ERC165 Library Functions

    func supports_interface(interface_id: felt) -> (success: felt):
    end
    
    func register_interface(interface_id: felt):
    end

#### [](#supportsinterface2)
`supports_interface`

Returns true if this contract implements the interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns:

    success: felt

#### [](#register_interface)
`register_interface`

Calling contract declares support for a specific interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns: None.

[← Security](/contracts-cairo/0.4.0b/security)

[Utilities →](/contracts-cairo/0.4.0b/utilities)




 Tokens - OpenZeppelin Docs       

Tokens
======

Ah, the "token": blockchain’s most powerful and most misunderstood tool.

A token is a _representation of something in the blockchain_. This something can be money, time, services, shares in a company, a virtual pet, anything. By representing things as tokens, we can allow smart contracts to interact with them, exchange them, create or destroy them.

[](#but_first_coffee_a_primer_on_token_contracts)
But First, Coffee a Primer on Token Contracts
-----------------------------------------------------------------------------------------------

Much of the confusion surrounding tokens comes from two concepts getting mixed up: _token contracts_ and the actual _tokens_.

A _token contract_ is simply an Ethereum smart contract. "Sending tokens" actually means "calling a method on a smart contract that someone wrote and deployed". At the end of the day, a token contract is not much more a mapping of addresses to balances, plus some methods to add and subtract from those balances.

It is these balances that represent the _tokens_ themselves. Someone "has tokens" when their balance in the token contract is non-zero. That’s it! These balances could be considered money, experience points in a game, deeds of ownership, or voting rights, and each of these tokens would be stored in different token contracts.

[](#different-kinds-of-tokens)
Different Kinds of Tokens
--------------------------------------------------------

Note that there’s a big difference between having two voting rights and two deeds of ownership: each vote is equal to all others, but houses usually are not! This is called [fungibility](https://en.wikipedia.org/wiki/Fungibility)
. _Fungible goods_ are equivalent and interchangeable, like Ether, fiat currencies, and voting rights. _Non-fungible_ goods are unique and distinct, like deeds of ownership, or collectibles.

In a nutshell, when dealing with non-fungibles (like your house) you care about _which ones_ you have, while in fungible assets (like your bank account statement) what matters is _how much_ you have.

[](#standards)
Standards
------------------------

Even though the concept of a token is simple, they have a variety of complexities in the implementation. Because everything in Ethereum is just a smart contract, and there are no rules about what smart contracts have to do, the community has developed a variety of **standards** (called EIPs or ERCs) for documenting how a contract can interoperate with other contracts.

You’ve probably heard of the ERC20 or ERC721 token standards, and that’s why you’re here. Head to our specialized guides to learn more about these:

*   [ERC20](erc20)
    : the most widespread token standard for fungible assets, albeit somewhat limited by its simplicity.
    
*   [ERC721](erc721)
    : the de-facto solution for non-fungible tokens, often used for collectibles and games.
    
*   [ERC777](erc777)
    : a richer standard for fungible tokens, enabling new use cases and building on past learnings. Backwards compatible with ERC20.
    

[← Access Control](/contracts/2.x/access-control)

[ERC20 →](/contracts/2.x/erc20)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, _public_key: felt252
        ) -> felt252;
    }

[← Accounts](/contracts-cairo/0.8.0-beta.0/accounts)

[API Reference →](/contracts-cairo/0.8.0-beta.0/api/account)




 Cryptography - OpenZeppelin Docs       

Cryptography
============

|     |     |
| --- | --- |
|     | This document is better viewed at [https://docs.openzeppelin.com/contracts/api/cryptography](https://docs.openzeppelin.com/contracts/api/cryptography) |

This collection of libraries provides simple and safe ways to use different cryptographic primitives.

The following related EIPs are in draft status and can be found in the drafts directory.

*   [`EIP712`](drafts#EIP712)
    

[](#libraries)
Libraries
------------------------

### [](#ECDSA)
`ECDSA`

Elliptic Curve Digital Signature Algorithm (ECDSA) operations.

These functions can be used to verify that a message was signed by the holder of the private keys of a given address.

Functions

*   [`recover(hash, signature)`](#ECDSA-recover-bytes32-bytes-)
    
*   [`recover(hash, v, r, s)`](#ECDSA-recover-bytes32-uint8-bytes32-bytes32-)
    
*   [`toEthSignedMessageHash(hash)`](#ECDSA-toEthSignedMessageHash-bytes32-)
    

#### [](#ECDSA-recover-bytes32-bytes-)
`recover(bytes32 hash, bytes signature) → address` internal

Returns the address that signed a hashed message (`hash`) with `signature`. This address can then be used for verification purposes.

The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: this function rejects them by requiring the `s` value to be in the lower half order, and the `v` value to be either 27 or 28.

|     |     |
| --- | --- |
|     | `hash` _must_ be the result of a hash operation for the verification to be secure: it is possible to craft signatures that recover to arbitrary addresses for non-hashed data. A safe way to ensure this is by receiving a hash of the original message (which may otherwise be too long), and then calling [`toEthSignedMessageHash`](#ECDSA-toEthSignedMessageHash-bytes32-)<br> on it. |

#### [](#ECDSA-recover-bytes32-uint8-bytes32-bytes32-)
`recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) → address` internal

Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`, `r` and `s` signature fields separately.

#### [](#ECDSA-toEthSignedMessageHash-bytes32-)
`toEthSignedMessageHash(bytes32 hash) → bytes32` internal

Returns an Ethereum Signed Message, created from a `hash`. This replicates the behavior of the [`eth_sign`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign)
 JSON-RPC method.

See [`recover`](#ECDSA-recover-bytes32-uint8-bytes32-bytes32-)
. /

### [](#MerkleProof)
`MerkleProof`

These functions deal with verification of Merkle trees (hash trees),

Functions

*   [`verify(proof, root, leaf)`](#MerkleProof-verify-bytes32---bytes32-bytes32-)
    

#### [](#MerkleProof-verify-bytes32---bytes32-bytes32-)
`verify(bytes32[] proof, bytes32 root, bytes32 leaf) → bool` internal

Returns true if a `leaf` can be proved to be a part of a Merkle tree defined by `root`. For this, a `proof` must be provided, containing sibling hashes on the branch from the leaf to the root of the tree. Each pair of leaves and each pair of pre-images are assumed to be sorted.

[← Access](/contracts/3.x/api/access)

[Drafts →](/contracts/3.x/api/drafts)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. The `ERC721.cairo` contract implements an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC721](#ierc721)
    
*   [ERC721 Compatibility](#erc721_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC721 URIs](#interpreting_erc721_uris)
        
    *   [ERC721Received](#erc721received)
        
        *   [IERC721Receiver](#ierc721receiver)
            
        
    *   [Supporting Interfaces](#supporting_interfaces)
        
    *   [Ready\_to\_Use Presets](#ready_to_use_presets)
        
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC721MintableBurnable](#erc721mintableburnable)
        
    *   [ERC721MintablePausable](#erc721mintablepausable)
        
    *   [ERC721EnumerableMintableBurnable](#erc721enumerablemintableburnable)
        
        *   [IERC721Enumerable](#ierc721enumerable)
            
        
    *   [ERC721Metadata](#erc721metadata)
        
        *   [IERC721Metadata](#ierc721metadata)
            
        
    
*   [Utilities](#utilities)
    
    *   [ERC721Holder](#erc721_holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC721`](#ierc721_api)
        
        *   [`balanceOf`](#balanceof)
            
        *   [`ownerOf`](#ownerof)
            
        *   [`safeTransferFrom`](#safetransferfrom)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        *   [`setApprovalForAll`](#setapprovalforall)
            
        *   [`getApproved`](#getapproved)
            
        *   [`isApprovedForAll`](#isapprovedforall)
            
        
    *   [Events](#events)
        
        *   [`Approval (event)`](#approval_event)
            
        *   [`ApprovalForAll (event)`](#approvalforall_event)
            
        *   [`Transfer (event)`](#transfer_event)
            
        
    *   [`IERC721Metadata`](#ierc721metadata)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`tokenURI`](#tokenuri)
            
        
    *   [`IERC721Enumerable`](#ierc721enumerable)
        
        *   [`totalSupply`](#totalsupply)
            
        *   [`tokenByIndex`](#tokenbyindex)
            
        *   [`tokenOfOwnerByIndex`](#tokenofownerbyindex)
            
        
    *   [`IERC721Receiver`](#ierc721receiver_api)
        
        *   [`onERC721Received`](#onerc721received)
            
        
    

[](#ierc721)
IERC721
--------------------

    @contract_interface
    namespace IERC721:
        func balanceOf(owner: felt) -> (balance: Uint256):
        end
    
        func ownerOf(tokenId: Uint256) -> (owner: felt):
        end
    
        func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    
        func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
        func approve(approved: felt, tokenId: Uint256):
        end
    
        func setApprovalForAll(operator: felt, approved: felt):
        end
    
        func getApproved(tokenId: Uint256) -> (approved: felt):
        end
    
        func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
        end
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#erc721_compatibility)
ERC721 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `tokenURI` returns a felt representation of the queried token’s URI. The EIP721 standard, however, states that the return value should be of type string. If a token’s URI is not set, the returned value is `0`. Note that URIs cannot exceed 31 characters. See [Interpreting ERC721 URIs](#interpreting_erc721_uris)
    
*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Solidity’s selector calculations. See [Supporting Interfaces](#supporting_interfaces)
    
*   `safeTransferFrom` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721. The difference between both functions consists of accepting `data` as an argument. Because function overloading is currently not possible in Cairo, `safeTransferFrom` by default accepts the `data` argument. If `data` is not used, simply insert `0`.
    
*   `safeTransferFrom` is specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, it accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`
    
*   `ERC165.register_interface` allows contracts to set and communicate which interfaces they support. This follows OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) must support ERC165 by registering the `IERC721Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC721 transfers
    
*   `ERC721Enumerable` tracks the total number of tokens with the `all_tokens` and `all_tokens_len` storage variables mimicking the array of the Solidity implementation.
    

[](#usage)
Usage
----------------

Use cases go from artwork, digital collectibles, physical property, and many more.

To show a standard use case, we’ll use the `ERC721Mintable` preset which allows for only the owner to `mint` and `burn` tokens. To create a token you need to first deploy both Account and ERC721 contracts respectively. As most StarkNet contracts, ERC721 expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it.

Considering that the ERC721 constructor method looks like this:

    func constructor(
        name: felt,          # Token name as Cairo short string
        symbol: felt,        # Token symbol as Cairo short string
        owner: felt          # Address designated as the contract owner
    ):

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc721 = await starknet.deploy(
        "contracts/token/erc721/presets/ERC721Mintable.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),                       # name\
            str_to_felt("TKN"),                         # symbol\
            account.contract_address                    # owner\
        ]
    )

To mint a non-fungible token, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    tokenId = uint(1)
    
    await signer.send_transaction(
        account, erc721.contract_address, 'mint', [\
            recipient_address,\
            *tokenId\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `transferFrom` and `safeTransferFrom` to transfer NFTs. If using `transferFrom`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.**

The `safeTransferFrom` method incorporates the following conditional logic:

1.  if the calling address is an account contract, the token transfer will behave as if `transferFrom` was called
    
2.  if the calling address is not an account contract, the safe function will check that the contract supports ERC721 tokens
    

The current implementation of `safeTansferFrom` checks for `onERC721Received` and requires that the recipient contract supports ERC165 and exposes the `supportsInterface` method. See [ERC721Received](#erc721received)
.

### [](#interpreting_erc721_uris)
Interpreting ERC721 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard set in [EIP721](https://eips.ethereum.org/EIPS/eip-721)<br>. Therefore, this library’s ERC721 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC721, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc721.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc721.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc721received)
ERC721Received

In order to be sure a contract can safely accept ERC721 tokens, said contract must implement the `ERC721_Receiver` interface (as expressed in the EIP721 specification). Methods such as `safeTransferFrom` and `safeMint` call the recipient contract’s `onERC721Received` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. `safeTransferFrom` requires a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC721 implementation requires that all contracts that support safe ERC721 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC721Receiver` magic value `0x150b7a02` (which invokes `onERC721Received`). If the recipient contract supports the `IAccount` magic value `0x50b70dcb`, `supportsInterface` should return `TRUE`. Otherwise, `safeTransferFrom` should fail.

#### [](#ierc721receiver)
IERC721Receiver

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

    @contract_interface
    namespace IERC721Receiver:
        func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
        end
    end

### [](#supporting_interfaces)
Supporting Interfaces

In order to ensure EVM/StarkNet compatibility, this ERC721 implementation does not calculate interface identifiers. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

Further, this implementation stores supported interfaces in a mapping (similar to OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
).

### [](#ready_to_use_presets)
Ready-to-Use Presets

ERC721 presets have been created to allow for quick deployments as-is. To be as explicit as possible, each preset includes the additional features they offer in the contract name. For example:

*   `ERC721MintableBurnable` includes `mint` and `burn`
    
*   `ERC721MintablePausable` includes `mint`, `pause`, and `unpause`
    
*   `ERC721EnumerableMintableBurnable` includes `mint`, `burn`, and [IERC721Enumerable](#ierc721enumerable)
     methods
    

Ready-to-use presets are a great option for testing and prototyping. See [Presets](#presets)
.

[](#extensibility)
Extensibility
--------------------------------

Following the [contracts extensibility pattern](extensibility)
, this implementation is set up to include all ERC721 related storage and business logic under a namespace. Developers should be mindful of manually exposing the required methods from the namespace to comply with the standard interface. This is already done in the [preset contracts](#presets)
; however, additional functionality can be added. For instance, you could:

*   Implement a pausing mechanism
    
*   Add roles such as _owner_ or _minter_
    
*   Modify the `transferFrom` function to mimic the [`_beforeTokenTransfer` and `_afterTokenTransfer` hooks](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L335)
    

Just be sure that the exposed `external` methods invoke their imported function logic a la `approve` invokes `ERC721.approve`. As an example, see below.

    from openzeppelin.token.erc721.library import ERC721
    
    @external
    func approve{
            pedersen_ptr: HashBuiltin*,
            syscall_ptr: felt*,
            range_check_ptr
        }(to: felt, tokenId: Uint256):
        ERC721.approve(to, tokenId)
        return()
    end

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset includes a contract owner, which is set in the `constructor`, to offer simple access control on sensitive methods such as `mint` and `burn`.

### [](#erc721mintableburnable)
ERC721MintableBurnable

The `ERC721MintableBurnable` preset offers a quick and easy setup for creating NFTs. The contract owner can create tokens with `mint`, whereas token owners can destroy their tokens with `burn`.

### [](#erc721mintablepausable)
ERC721MintablePausable

The `ERC721MintablePausable` preset creates a contract with pausable token transfers and minting capabilities. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug. In this preset, only the contract owner can `mint`, `pause`, and `unpause`.

### [](#erc721enumerablemintableburnable)
ERC721EnumerableMintableBurnable

The `ERC721EnumerableMintableBurnable` preset adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This allows contracts to publish its full list of NFTs and make them discoverable.

In regard to implementation, contracts should expose the following view methods:

*   `ERC721Enumerable.total_supply`
    
*   `ERC721Enumerable.token_by_index`
    
*   `ERC721Enumerable.token_of_owner_by_index`
    

In order for the tokens to be correctly indexed, the contract should also use the following methods (which supercede some of the base `ERC721` methods):

*   `ERC721Enumerable.transfer_from`
    
*   `ERC721Enumerable.safe_transfer_from`
    
*   `ERC721Enumerable._mint`
    
*   `ERC721Enumerable._burn`
    

#### [](#ierc721enumerable)
IERC721Enumerable

    @contract_interface
    namespace IERC721Enumerable:
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
        end
    
        func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
        end
    end

### [](#erc721metadata)
ERC721Metadata

The `ERC721Metadata` extension allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

We follow OpenZeppelin’s Solidity approach of integrating the Metadata methods `name`, `symbol`, and `tokenURI` into all ERC721 implementations. If preferred, a contract can be created that does not import the Metadata methods from the `ERC721` library. Note that the `IERC721Metadata` interface id should be removed from the constructor as well.

#### [](#ierc721metadata)
IERC721Metadata

    @contract_interface
    namespace IERC721Metadata:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
        end
    end

[](#utilities)
Utilities
------------------------

### [](#erc721holder)
ERC721Holder

Implementation of the `IERC721Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC721.safeTransferFrom`, `IERC721.approve` or `IERC721.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC721Received](#erc721received)

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc721_api)
IERC721 API

    func balanceOf(owner: felt) -> (balance: Uint256):
    end
    
    func ownerOf(tokenId: Uint256) -> (owner: felt):
    end
    
    func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    end
    
    func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
    func approve(approved: felt, tokenId: Uint256):
    end
    
    func setApprovalForAll(operator: felt, approved: felt):
    end
    
    func getApproved(tokenId: Uint256) -> (approved: felt):
    end
    
    func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
    end

#### [](#balanceof)
`balanceOf`

Returns the number of tokens in `owner`'s account.

Parameters:

    owner: felt

Returns:

    balance: Uint256

#### [](#ownerof)
`ownerOf`

Returns the owner of the `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    owner: felt

#### [](#safetransferfrom)
`safeTransferFrom`

Safely transfers `tokenId` token from `from_` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [ERC721Received](#erc721received)
.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#transferfrom)
`transferFrom`

Transfers `tokenId` token from `from_` to `to`. **The caller is responsible to confirm that `to` is capable of receiving NFTs or else they may be permanently lost**.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

Returns: None.

#### [](#approve)
`approve`

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Emits an [Approval](#approval_event)
 event.

Parameters:

    to: felt
    tokenId: Uint256

Returns: None.

#### [](#getapproved)
`getApproved`

Returns the account approved for `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    operator: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.

Emits an [ApprovalForAll](#approvalforall_event)
 event.

Parameters:

    operator: felt

Returns: None.

#### [](#isapprovedforall)
`isApprovedForAll`

Returns if the `operator` is allowed to manage all of the assets of `owner`.

Parameters:

    owner: felt
    operator: felt

Returns:

    isApproved: felt

### [](#events)
Events

#### [](#approval_event)
`Approval (Event)`

Emitted when `owner` enables `approved` to manage the `tokenId` token.

Parameters:

    owner: felt
    approved: felt
    tokenId: Uint256

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    owner: felt
    operator: felt
    approved: felt

#### [](#transfer_event)
`Transfer (Event)`

Emitted when `tokenId` token is transferred from `from_` to `to`.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

* * *

### [](#ierc721metadata_api)
IERC721Metadata API

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
    end

#### [](#name)
`name`

Returns the token collection name.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the token collection symbol.

Parameters: None.

Returns:

    symbol: felt

#### [](#tokenuri)
`tokenURI`

Returns the Uniform Resource Identifier (URI) for `tokenID` token. If the URI is not set for the `tokenId`, the return value will be `0`.

Parameters:

    tokenId: Uint256

Returns:

    tokenURI: felt

* * *

### [](#ierc721enumerable_api)
IERC721Enumerable API

    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
    end
    
    func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
    end

#### [](#totalsupply)
`totalSupply`

Returns the total amount of tokens stored by the contract.

Parameters: None

Returns:

    totalSupply: Uint256

#### [](#tokenbyindex)
`tokenByIndex`

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [balanceOf](#balanceof)
 to enumerate all of `owner`'s tokens.

Parameters:

    index: Uint256

Returns:

    tokenId: Uint256

#### [](#tokenofownerbyindex)
`tokenOfOwnerByIndex`

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [totalSupply](#totalsupply)
 to enumerate all tokens.

Parameters:

    owner: felt
    index: Uint256

Returns:

    tokenId: Uint256

* * *

### [](#ierc721receiver_api)
IERC721Receiver API

    func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
    end

#### [](#onerc721received)
`onERC721Received`

Whenever an IERC721 `tokenId` token is transferred to this non-account contract via `safeTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC20](/contracts-cairo/0.4.0b/erc20)

[Security →](/contracts-cairo/0.4.0b/security)




 Access Control - OpenZeppelin Docs       

Access Control
==============

Access control—that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore **critical** to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7)
.

[](#ownership-and-ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of _ownership_: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin provides [`Ownable`](api/ownership#Ownable)
 for implementing ownership in your contracts.

    pragma solidity ^0.5.0;
    
    import "@openzeppelin/contracts/ownership/Ownable.sol";
    
    contract MyContract is Ownable {
        function normalThing() public {
            // anyone can call this normalThing()
        }
    
        function specialThing() public onlyOwner {
            // only the owner can call specialThing()!
        }
    }

By default, the [`owner`](api/ownership#Ownable-owner--)
 of an `Ownable` contract is the account that deployed it, which is usually exactly what you want.

Ownable also lets you:

*   [`transferOwnership`](api/ownership#Ownable-transferOwnership-address-)
     from the owner account to a new one, and
    
*   [`renounceOwnership`](api/ownership#Ownable-renounceOwnership--)
     for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `onlyOwner` will no longer be callable! |

Note that **a contract can also be the owner of another one**! This opens the door to using, for example, a [Gnosis Multisig](https://github.com/gnosis/MultiSigWallet)
 or [Gnosis Safe](https://safe.gnosis.io)
, an [Aragon DAO](https://aragon.org)
, an [ERC725/uPort](https://www.uport.me)
 identity contract, or a totally custom contract that _you_ create.

In this way you can use _composability_ to add additional layers of access control complexity to your contracts. Instead of having a single regular Ethereum account (Externally Owned Account, or EOA) as the owner, you could use a 2-of-3 multisig run by your project leads, for example. Prominent projects in the space, such as [MakerDAO](https://makerdao.com)
, use systems similar to this one.

[](#role-based-access-control)
Role-Based Access Control
--------------------------------------------------------

While the simplicity of _ownership_ can be useful for simple systems or quick prototyping, different levels of authorization are often needed. An account may be able to ban users from a system, but not create new tokens. _Role-Based Access Control (RBAC)_ offers flexibility in this regard.

In essence, we will be defining multiple _roles_, each allowed to perform different sets of actions. Instead of `onlyOwner` everywhere - you will use, for example, `onlyAdminRole` in some places, and `onlyModeratorRole` in others. Separately, you will be able to define rules for how accounts can be assignned a role, transfer it, and more.

Most of software development uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#using-roles)
Using `Roles`

OpenZeppelin provides [`Roles`](api/access#Roles)
 for implementing role-based access control. Its usage is straightforward: for each role that you want to define, you’ll store a variable of type `Role`, which will hold the list of accounts with that role.

Here’s a simple example of using `Roles` in an [`ERC20` token](tokens#ERC20)
: we’ll define two roles, `minters` and `burners`, that will be able to mint new tokens, and burn them, respectively.

    pragma solidity ^0.5.0;
    
    import "@openzeppelin/contracts/access/Roles.sol";
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
    
    contract MyToken is ERC20, ERC20Detailed {
        using Roles for Roles.Role;
    
        Roles.Role private _minters;
        Roles.Role private _burners;
    
        constructor(address[] memory minters, address[] memory burners)
            ERC20Detailed("MyToken", "MTKN", 18)
            public
        {
            for (uint256 i = 0; i < minters.length; ++i) {
                _minters.add(minters[i]);
            }
    
            for (uint256 i = 0; i < burners.length; ++i) {
                _burners.add(burners[i]);
            }
        }
    
        function mint(address to, uint256 amount) public {
            // Only minters can mint
            require(_minters.has(msg.sender), "DOES_NOT_HAVE_MINTER_ROLE");
    
            _mint(to, amount);
        }
    
        function burn(address from, uint256 amount) public {
            // Only burners can burn
            require(_burners.has(msg.sender), "DOES_NOT_HAVE_BURNER_ROLE");
    
           _burn(from, amount);
        }
    }

So clean! By splitting concerns this way, much more granular levels of permission may be implemented than were possible with the simpler _ownership_ approach to access control. Note that an account may have more than one role, if desired.

OpenZeppelin uses `Roles` extensively with predefined contracts that encode rules for each specific role. A few examples are: [`ERC20Mintable`](api/token/ERC20#ERC20Mintable)
 which uses the [`MinterRole`](api/access#MinterRole)
 to determine who can mint tokens, and [`WhitelistCrowdsale`](api/crowdsale#WhitelistCrowdsale)
 which uses both [`WhitelistAdminRole`](api/access#WhitelistAdminRole)
 and [`WhitelistedRole`](api/access#WhitelistedRole)
 to create a set of accounts that can purchase tokens.

This flexibility allows for interesting setups: for example, a [`MintedCrowdsale`](api/crowdsale#MintedCrowdsale)
 expects to be given the `MinterRole` of an `ERC20Mintable` in order to work, but the token contract could also extend [`ERC20Pausable`](api/token/ERC20#ERC20Pausable)
 and assign the [`PauserRole`](api/access#PauserRole)
 to a DAO that serves as a contingency mechanism in case a vulnerability is discovered in the contract code. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice.

[](#usage-in-openzeppelin)
Usage in OpenZeppelin
------------------------------------------------

You’ll notice that none of the OpenZeppelin contracts use `Ownable`. `Roles` is a prefferred solution, because it provides the user of the library with enough flexibility to adapt the provided contracts to their needs.

There are some cases, however, where there’s a direct relationship between contracts. For example, [`RefundableCrowdsale`](api/crowdsale#RefundableCrowdsale)
 deploys a [`RefundEscrow`](api/payment#RefundEscrow)
 on construction, to hold its funds. For those cases, we’ll use [`Secondary`](api/ownership#Secondary)
 to create a _secondary_ contract that allows a _primary_ contract to manage it. You could also think of these as _auxiliary_ contracts.

[← Overview](/contracts/2.x/)

[Tokens →](/contracts/2.x/tokens)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides context, reasoning, and examples for methods and constants found in `tests/utils.py`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Constants](#constants)
    
*   [Strings](#strings)
    
    *   [`str_to_felt`](#str_to_felt)
        
    *   [`felt_to_str`](#felt_to_str)
        
    
*   [Uint256](#uint256)
    
    *   [`uint`](#uint)
        
    *   [`to_uint`](#to_uint)
        
    *   [`from_uint`](#from_uint)
        
    *   [`add_uint`](#add_uint)
        
    *   [`sub_uint`](#sub_uint)
        
    
*   [Assertions](#assertions)
    
    *   [`assert_revert`](#assert_revert)
        
    *   [`assert_revert_entry_point`](#assert_revert_entry_point)
        
    *   [`assert_events_emitted`](#assert_event_emitted)
        
    
*   [Memoization](#memoization)
    
    *   [`get_contract_class`](#get_contract_class)
        
    *   [`cached_contract`](#cached_contract)
        
    
*   [State](#state)
    
*   [Account](#account)
    
*   [MockSigner](#mocksigner)
    

[](#constants)
Constants
------------------------

To ease the readability of Cairo contracts, this project includes reusable [constant variables](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 like `UINT8_MAX`, or EIP165 interface IDs such as `IERC165_ID` or `IERC721_ID`. For more information on how interface ids are calculated, see the [ERC165 documentation](introspection#interface_calculations)
.

[](#strings)
Strings
--------------------

Cairo currently only provides support for short string literals (less than 32 characters). Note that short strings aren’t really strings, rather, they’re representations of Cairo field elements. The following methods provide a simple conversion to/from field elements.

### [](#str_to_felt)
`str_to_felt`

Takes an ASCII string and converts it to a field element via big endian representation.

### [](#felt_to_str)
`felt_to_str`

Takes an integer and converts it to an ASCII string by trimming the null bytes and decoding the remaining bits.

[](#uint256)
Uint256
--------------------

Cairo’s native data type is a field element (felt). Felts equate to 252 bits which poses a problem regarding 256-bit integer integration. To resolve the bit discrepancy, Cairo represents 256-bit integers as a struct of two 128-bit integers. Further, the low bits precede the high bits e.g.

    1 = (1, 0)
    1 << 128 = (0, 1)
    (1 << 128) - 1 = (340282366920938463463374607431768211455, 0)

### [](#uint)
`uint`

Converts a simple integer into a uint256-ish tuple.

> Note `to_uint` should be used in favor of `uint`, as `uint` only returns the low bits of the tuple.

### [](#to_uint)
`to_uint`

Converts an integer into a uint256-ish tuple.

    x = to_uint(340282366920938463463374607431768211456)
    print(x)
    # prints (0, 1)

### [](#from_uint)
`from_uint`

Converts a uint256-ish tuple into an integer.

    x = (0, 1)
    y = from_uint(x)
    print(y)
    # prints 340282366920938463463374607431768211456

### [](#add_uint)
`add_uint`

Performs addition between two uint256-ish tuples and returns the sum as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = add_uint(x, y)
    print(z)
    # prints (1, 1)

### [](#sub_uint)
`sub_uint`

Performs subtraction between two uint256-ish tuples and returns the difference as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = sub_uint(x, y)
    print(z)
    # prints (340282366920938463463374607431768211455, 0)

### [](#mul_uint)
`mul_uint`

Performs multiplication between two uint256-ish tuples and returns the product as a uint256-ish tuple.

    x = (0, 10)
    y = (2, 0)
    z = mul_uint(x, y)
    print(z)
    # prints (0, 20)

### [](#div_rem_uint)
`div_rem_uint`

Performs division between two uint256-ish tuples and returns both the quotient and remainder as uint256-ish tuples respectively.

    x = (1, 100)
    y = (0, 25)
    z = div_rem_uint(x, y)
    print(z)
    # prints ((4, 0), (1, 0))

[](#assertions)
Assertions
--------------------------

In order to abstract away some of the verbosity regarding test assertions on StarkNet transactions, this project includes the following helper methods:

### [](#assert_revert)
`assert_revert`

An asynchronous wrapper method that executes a try-except pattern for transactions that should fail. Note that this wrapper does not check for a StarkNet error code. This allows for more flexibility in checking that a transaction simply failed. If you wanted to check for an exact error code, you could use StarkNet’s [error\_codes module](https://github.com/starkware-libs/cairo-lang/blob/ed6cf8d6cec50a6ad95fa36d1eb4a7f48538019e/src/starkware/starknet/definitions/error_codes.py)
 and implement additional logic to the `assert_revert` method.

To successfully use this wrapper, the transaction method should be wrapped with `assert_revert`; however, `await` should precede the wrapper itself like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    )

This wrapper also includes the option to check that an error message was included in the reversion. To check that the reversion sends the correct error message, add the `reverted_with` keyword argument outside of the actual transaction (but still inside the wrapper) like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ]),
        reverted_with="insert error message here"
    )

### [](#assert_revert_entry_point)
`assert_revert_entry_point`

An extension of `assert_revert` that asserts an entry point error occurs with the given `invalid_selector` parameter. This assertion is especially useful in checking proxy/implementation contracts. To use `assert_revert_entry_point`:

    await assert_revert_entry_point(
        signer.send_transaction(
            account, contract.contract_address, 'nonexistent_selector', []
        ),
        invalid_selector='nonexistent_selector'
    )

### [](#assert_event_emitted)
`assert_event_emitted`

A helper method that checks a transaction receipt for the contract emitting the event (`from_address`), the emitted event itself (`name`), and the arguments emitted (`data`). To use `assert_event_emitted`:

    # capture the tx receipt
    tx_exec_info = await signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    
    # insert arguments to assert
    assert_event_emitted(
        tx_exec_info,
        from_address=contract.contract_address,
        name='Foo_emitted',
        data=[\
            account.contract_address,\
            recipient,\
            *token\
        ]
    )

[](#memoization)
Memoization
----------------------------

Memoizing functions allow for quicker and computationally cheaper calculations which is immensely beneficial while testing smart contracts.

### [](#get_contract_class)
`get_contract_class`

A helper method that returns the contract class from the contract’s name. To capture the contract class, simply add the contract’s name as an argument like this:

    contract_class = get_contract_class('ContractName')

If multiple contracts exist with the same name, then the contract’s path must be passed along with the `is_path` flag instead of the name. To pass the contract’s path:

    contract_class = get_contract_class('path/to/Contract.cairo', is_path=True)

### [](#cached_contract)
`cached_contract`

A helper method that returns the cached state of a given contract. It’s recommended to first deploy all the relevant contracts before caching the state. The requisite contracts in the testing module should each be instantiated with `cached_contract` in a fixture after the state has been copied. The memoization pattern with `cached_contract` should look something like this:

    # get contract classes
    @pytest.fixture(scope='module')
    def contract_classes():
      foo_cls = get_contract_class('Foo')
      return foo_cls
    
    # deploy contracts
    @pytest.fixture(scope='module')
    async def foo_init(contract_classes):
        foo_cls = contract_classes
        starknet = await Starknet.empty()
        foo = await starknet.deploy(
            contract_class=foo_cls,
            constructor_calldata=[]
        )
        return starknet.state, foo  # return state and all deployed contracts
    
    # memoization
    @pytest.fixture(scope='module')
    def foo_factory(contract_classes, foo_init):
        foo_cls = contract_classes                          # contract classes
        state, foo = foo_init                               # state and deployed contracts
        _state = state.copy()                               # copy the state
        cached_foo = cached_contract(_state, foo_cls, foo)  # cache contracts
        return cached_foo                                   # return cached contracts

[](#state)
State
----------------

The `State` class provides a wrapper for initializing the StarkNet state which acts as a helper for the `Account` class. This wrapper allows `Account` deployments to share the same initialized state without explicitly passing the instantiated StarkNet state to `Account`. Initializing the state should look like this:

    from utils import State
    
    starknet = await State.init()

[](#account)
Account
--------------------

The `Account` class abstracts away most of the boilerplate for deploying accounts. Instantiating accounts with this class requires the StarkNet state to be instantiated first with the `State.init()` method like this:

    from utils import State, Account
    
    starknet = await State.init()
    account1 = await Account.deploy(public_key)
    account2 = await Account.deploy(public_key)

The Account class also provides access to the account contract class which is useful for following the [Memoization](#memoization)
 pattern. To fetch the account contract class:

    fetch_class = Account.get_class

[](#mocksigner)
MockSigner
--------------------------

`MockSigner` is used to perform transactions with an instance of [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 on a given Account, crafting the transaction and managing nonces. The `Signer` instance manages signatures and is leveraged by `MockSigner` to operate with the Account contract’s `__execute__` method. See [MockSigner utility](accounts#mocksigner_utility)
 for more information.

[← Introspection](/contracts-cairo/0.3.0/introspection)

[Contracts for Solidity →](/contracts/5.x/)




 Migrating ERC165 to SRC5 - OpenZeppelin Docs       

Migrating ERC165 to SRC5
========================

In the smart contract ecosystem, having the ability to query if a contract supports a given interface is an extremely important feature. The initial introspection design for Contracts for Cairo before version v0.7.0 followed Ethereum’s [EIP-165](https://eips.ethereum.org/EIPS/eip-165)
. Since the Cairo language evolved introducing native types, we needed an introspection solution tailored to the Cairo ecosystem: the [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard. SNIP-5 allows interface ID calculations to use Cairo types and the Starknet keccak (`sn_keccak`) function. For more information on the decision, see the [Starknet Shamans proposal](https://community.starknet.io/t/starknet-standard-interface-detection/92664)
 or the [Dual Introspection Detection](https://github.com/OpenZeppelin/cairo-contracts/discussions/640)
 discussion.

[](#how_to_migrate)
How to migrate
----------------------------------

Migrating from ERC165 to SRC5 involves four major steps:

1.  Integrate SRC5 into the contract.
    
2.  Register SRC5 IDs.
    
3.  Add a `migrate` function to apply introspection changes.
    
4.  Upgrade the contract and call `migrate`.
    

The following guide will go through the steps with examples.

### [](#component_integration)
Component integration

The first step is to integrate the necessary components into the new contract. The contract should include the new introspection mechanism, [SRC5Component](../api/introspection#SRC5Component)
. It should also include the [InitializableComponent](../api/security#InitializableComponent)
 which will be used in the `migrate` function. Here’s the setup:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::security::initializable::InitializableComponent;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5CamelOnlyImpl = SRC5Component::SRC5CamelImpl<ContractState>;
        impl SRC5InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        // Initializable
        impl InitializableInternalImpl = InitializableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

### [](#interface_registration)
Interface registration

To successfully migrate ERC165 to SRC5, the contract needs to register the interface IDs that the contract supports with SRC5.

For this example, let’s say that this contract supports the [IERC721](../api/erc721#IERC721)
 and [IERC721Metadata](../api/erc721#IERC721Metadata)
 interfaces. The contract should implement an `InternalImpl` and add a function to register those interfaces like this:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID};
    
        (...)
    
        #[generate_trait]
        impl InternalImpl of InternalTrait {
            // Register SRC5 interfaces
            fn register_src5_interfaces(ref self: ContractState) {
                self.src5.register_interface(IERC721_ID);
                self.src5.register_interface(IERC721_METADATA_ID);
            }
        }
    }

Since the new contract integrates `SRC5Component`, it can leverage SRC5’s [register\_interface](../api/introspection#SRC5Component-register_interface)
 function to register the supported interfaces.

### [](#migration_initializer)
Migration initializer

Next, the contract should define and expose a migration function that will invoke the `register_src5_interfaces` function. Since the `migrate` function will be publicly callable, it should include some sort of [Access Control](../access)
 so that only permitted addresses can execute the migration. Finally, `migrate` should include a reinitialization check to ensure that it cannot be called more than once.

|     |     |
| --- | --- |
|     | If the original contract implemented `Initializable` at any point and called the `initialize` method, the `InitializableComponent` will not be usable at this time. Instead, the contract can take inspiration from `InitializableComponent` and create its own initialization mechanism. |

    #[starknet::contract]
    mod MigratingContract {
        (...)
    
        #[external(v0)]
        fn migrate(ref self: ContractState) {
            // WARNING: Missing Access Control mechanism. Make sure to add one
    
            // WARNING: If the contract ever implemented `Initializable` in the past,
            // this will not work. Make sure to create a new initialization mechanism
            self.initializable.initialize();
    
            // Register SRC5 interfaces
            self.register_src5_interfaces();
        }
    }

### [](#execute_migration)
Execute migration

Once the new contract is prepared for migration and **rigorously tested**, all that’s left is to migrate! Simply upgrade the contract and then call `migrate`.

[← Introspection](/contracts-cairo/0.8.1/introspection)

[API Reference →](/contracts-cairo/0.8.1/api/introspection)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides context, reasoning, and examples for methods and constants found in `tests/utils.py`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Constants](#constants)
    
*   [Strings](#strings)
    
    *   [`str_to_felt`](#str_to_felt)
        
    *   [`felt_to_str`](#felt_to_str)
        
    
*   [Uint256](#uint256)
    
    *   [`uint`](#uint)
        
    *   [`to_uint`](#to_uint)
        
    *   [`from_uint`](#from_uint)
        
    *   [`add_uint`](#add_uint)
        
    *   [`sub_uint`](#sub_uint)
        
    
*   [Assertions](#assertions)
    
    *   [`assert_revert`](#assert_revert)
        
    *   [`assert_revert_entry_point`](#assert_revert_entry_point)
        
    *   [`assert_events_emitted`](#assert_event_emitted)
        
    
*   [Memoization](#memoization)
    
    *   [`get_contract_class`](#get_contract_class)
        
    *   [`cached_contract`](#cached_contract)
        
    
*   [State](#state)
    
*   [Account](#account)
    
*   [MockSigner](#mocksigner)
    

[](#constants)
Constants
------------------------

To ease the readability of Cairo contracts, this project includes reusable [constant variables](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 like `UINT8_MAX`, or EIP165 interface IDs such as `IERC165_ID` or `IERC721_ID`. For more information on how interface ids are calculated, see the [ERC165 documentation](introspection#interface_calculations)
.

[](#strings)
Strings
--------------------

Cairo currently only provides support for short string literals (less than 32 characters). Note that short strings aren’t really strings, rather, they’re representations of Cairo field elements. The following methods provide a simple conversion to/from field elements.

### [](#str_to_felt)
`str_to_felt`

Takes an ASCII string and converts it to a field element via big endian representation.

### [](#felt_to_str)
`felt_to_str`

Takes an integer and converts it to an ASCII string by trimming the null bytes and decoding the remaining bits.

[](#uint256)
Uint256
--------------------

Cairo’s native data type is a field element (felt). Felts equate to 252 bits which poses a problem regarding 256-bit integer integration. To resolve the bit discrepancy, Cairo represents 256-bit integers as a struct of two 128-bit integers. Further, the low bits precede the high bits e.g.

    1 = (1, 0)
    1 << 128 = (0, 1)
    (1 << 128) - 1 = (340282366920938463463374607431768211455, 0)

### [](#uint)
`uint`

Converts a simple integer into a uint256-ish tuple.

> Note `to_uint` should be used in favor of `uint`, as `uint` only returns the low bits of the tuple.

### [](#to_uint)
`to_uint`

Converts an integer into a uint256-ish tuple.

    x = to_uint(340282366920938463463374607431768211456)
    print(x)
    # prints (0, 1)

### [](#from_uint)
`from_uint`

Converts a uint256-ish tuple into an integer.

    x = (0, 1)
    y = from_uint(x)
    print(y)
    # prints 340282366920938463463374607431768211456

### [](#add_uint)
`add_uint`

Performs addition between two uint256-ish tuples and returns the sum as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = add_uint(x, y)
    print(z)
    # prints (1, 1)

### [](#sub_uint)
`sub_uint`

Performs subtraction between two uint256-ish tuples and returns the difference as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = sub_uint(x, y)
    print(z)
    # prints (340282366920938463463374607431768211455, 0)

### [](#mul_uint)
`mul_uint`

Performs multiplication between two uint256-ish tuples and returns the product as a uint256-ish tuple.

    x = (0, 10)
    y = (2, 0)
    z = mul_uint(x, y)
    print(z)
    # prints (0, 20)

### [](#div_rem_uint)
`div_rem_uint`

Performs division between two uint256-ish tuples and returns both the quotient and remainder as uint256-ish tuples respectively.

    x = (1, 100)
    y = (0, 25)
    z = div_rem_uint(x, y)
    print(z)
    # prints ((4, 0), (1, 0))

[](#assertions)
Assertions
--------------------------

In order to abstract away some of the verbosity regarding test assertions on StarkNet transactions, this project includes the following helper methods:

### [](#assert_revert)
`assert_revert`

An asynchronous wrapper method that executes a try-except pattern for transactions that should fail. Note that this wrapper does not check for a StarkNet error code. This allows for more flexibility in checking that a transaction simply failed. If you wanted to check for an exact error code, you could use StarkNet’s [error\_codes module](https://github.com/starkware-libs/cairo-lang/blob/ed6cf8d6cec50a6ad95fa36d1eb4a7f48538019e/src/starkware/starknet/definitions/error_codes.py)
 and implement additional logic to the `assert_revert` method.

To successfully use this wrapper, the transaction method should be wrapped with `assert_revert`; however, `await` should precede the wrapper itself like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    )

This wrapper also includes the option to check that an error message was included in the reversion. To check that the reversion sends the correct error message, add the `reverted_with` keyword argument outside of the actual transaction (but still inside the wrapper) like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ]),
        reverted_with="insert error message here"
    )

### [](#assert_revert_entry_point)
`assert_revert_entry_point`

An extension of `assert_revert` that asserts an entry point error occurs with the given `invalid_selector` parameter. This assertion is especially useful in checking proxy/implementation contracts. To use `assert_revert_entry_point`:

    await assert_revert_entry_point(
        signer.send_transaction(
            account, contract.contract_address, 'nonexistent_selector', []
        ),
        invalid_selector='nonexistent_selector'
    )

### [](#assert_event_emitted)
`assert_event_emitted`

A helper method that checks a transaction receipt for the contract emitting the event (`from_address`), the emitted event itself (`name`), and the arguments emitted (`data`). To use `assert_event_emitted`:

    # capture the tx receipt
    tx_exec_info = await signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    
    # insert arguments to assert
    assert_event_emitted(
        tx_exec_info,
        from_address=contract.contract_address,
        name='Foo_emitted',
        data=[\
            account.contract_address,\
            recipient,\
            *token\
        ]
    )

[](#memoization)
Memoization
----------------------------

Memoizing functions allow for quicker and computationally cheaper calculations which is immensely beneficial while testing smart contracts.

### [](#get_contract_class)
`get_contract_class`

A helper method that returns the contract class from the contract’s name. To capture the contract class, simply add the contract’s name as an argument like this:

    contract_class = get_contract_class('ContractName')

If multiple contracts exist with the same name, then the contract’s path must be passed along with the `is_path` flag instead of the name. To pass the contract’s path:

    contract_class = get_contract_class('path/to/Contract.cairo', is_path=True)

### [](#cached_contract)
`cached_contract`

A helper method that returns the cached state of a given contract. It’s recommended to first deploy all the relevant contracts before caching the state. The requisite contracts in the testing module should each be instantiated with `cached_contract` in a fixture after the state has been copied. The memoization pattern with `cached_contract` should look something like this:

    # get contract classes
    @pytest.fixture(scope='module')
    def contract_classes():
      foo_cls = get_contract_class('Foo')
      return foo_cls
    
    # deploy contracts
    @pytest.fixture(scope='module')
    async def foo_init(contract_classes):
        foo_cls = contract_classes
        starknet = await Starknet.empty()
        foo = await starknet.deploy(
            contract_class=foo_cls,
            constructor_calldata=[]
        )
        return starknet.state, foo  # return state and all deployed contracts
    
    # memoization
    @pytest.fixture(scope='module')
    def foo_factory(contract_classes, foo_init):
        foo_cls = contract_classes                          # contract classes
        state, foo = foo_init                               # state and deployed contracts
        _state = state.copy()                               # copy the state
        cached_foo = cached_contract(_state, foo_cls, foo)  # cache contracts
        return cached_foo                                   # return cached contracts

[](#state)
State
----------------

The `State` class provides a wrapper for initializing the StarkNet state which acts as a helper for the `Account` class. This wrapper allows `Account` deployments to share the same initialized state without explicitly passing the instantiated StarkNet state to `Account`. Initializing the state should look like this:

    from utils import State
    
    starknet = await State.init()

[](#account)
Account
--------------------

The `Account` class abstracts away most of the boilerplate for deploying accounts. Instantiating accounts with this class requires the StarkNet state to be instantiated first with the `State.init()` method like this:

    from utils import State, Account
    
    starknet = await State.init()
    account1 = await Account.deploy(public_key)
    account2 = await Account.deploy(public_key)

The Account class also provides access to the account contract class which is useful for following the [Memoization](#memoization)
 pattern. To fetch the account contract class:

    fetch_class = Account.get_class

[](#mocksigner)
MockSigner
--------------------------

`MockSigner` is used to perform transactions with an instance of [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 on a given Account, crafting the transaction and managing nonces. The `Signer` instance manages signatures and is leveraged by `MockSigner` to operate with the Account contract’s `__execute__` method. See [MockSigner utility](accounts#mocksigner_utility)
 for more information.

[← Introspection](/contracts-cairo/0.4.0b/introspection)

[Contracts for Solidity →](/contracts/5.x/)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are derived from a private key, all Starknet accounts are contracts. This means there’s no Externally Owned Account (EOA) concept on Starknet.

Instead, the network features native account abstraction and signature validation happens at the contract level.

For a general overview of account abstraction, see [Starknet’s documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/introduction/)
. A more detailed discussion on the topic can be found in [Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

|     |     |
| --- | --- |
|     | For detailed information on the usage and implementation check the [API Reference](api/account)<br> section. |

[](#standard_account_interface)
Standard Account Interface
----------------------------------------------------------

Accounts in Starknet are smart contracts, and so they can be deployed and interacted with like any other contract, and can be extended to implement any custom logic. However, an account is a special type of contract that is used to validate and execute transactions. For this reason, it must implement a set of entrypoints that the protocol uses for this execution flow. The [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 proposal defines a standard interface for accounts, supporting this execution flow and interoperability with DApps in the ecosystem.

### [](#isrc6_interface)
ISRC6 Interface

    /// Represents a call to a target contract function.
    struct Call {
        to: ContractAddress,
        selector: felt252,
        calldata: Array<felt252>
    }
    
    /// Standard Account Interface
    trait ISRC6 {
        /// Executes a transaction through the account.
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
    
        /// Asserts whether the transaction is valid to be executed.
        fn __validate__(calls: Array<Call>) -> felt252;
    
        /// Asserts whether a given signature for a given hash is valid.
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 adds the `is_valid_signature` method. This method is not used by the protocol, but it’s useful for DApps to verify the validity of signatures, supporting features like Sign In with Starknet.

SNIP-6 also defines that compliant accounts must implement the SRC5 interface following [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
, as a mechanism for detecting whether a contract is an account or not through introspection.

### [](#isrc5_interface)
ISRC5 Interface

    /// Standard Interface Detection
    trait ISRC5 {
        /// Queries if a contract implements a given interface.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 compliant accounts must return `true` when queried for the ISRC6 interface Id.

Even though these interfaces are not enforced by the protocol, it’s recommended to implement them for enabling interoperability with the ecosystem.

[](#protocol_level_methods)
Protocol-level methods
--------------------------------------------------

In this section we will describe the methods that the protocol uses for abstracting the accounts. The first two are required for enabling accounts to be used for executing transactions. The rest are optional:

1.  `__validate__` verifies the validity of the transaction to be executed. This is usually used to validate signatures, but the entrypoint implementation can be customized to feature any validation mechanism [with some limitations](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/validate_and_execute/#validate_limitations)
    .
    
2.  `__execute__` executes the transaction if the validation is successful.
    
3.  `__validate_declare__` optional entrypoint similar to `__validate__` but for transactions meant to declare other contracts.
    
4.  `__validate_deploy__` optional entrypoint similar to `__validate__` but meant for [counterfactual deployments](guides/deployment)
    .
    

|     |     |
| --- | --- |
|     | Although these entrypoints are available to the protocol for its regular transaction flow, they can also be called like any other method. |

[](#deploying_an_account)
Deploying an account
----------------------------------------------

In Starknet there are two ways of deploying smart contracts: using the `deploy_syscall` and doing counterfactual deployments. The former can be easily done with the [Universal Deployer Contract (UDC)](udc)
, a contract that wraps and exposes the `deploy_syscall` to provide arbitrary deployments through regular contract calls. But if you don’t have an account to invoke it, you will probably want to use the latter.

To do counterfactual deployments, you need to implement another protocol-level entrypoint named `__validate_deploy__`. Check the [counterfactual deployments](guides/deployment)
 guide to learn how.

[← API Reference](/contracts-cairo/0.8.0/api/access)

[API Reference →](/contracts-cairo/0.8.0/api/account)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | This document is better viewed at [https://docs.openzeppelin.com/contracts/api/access](https://docs.openzeppelin.com/contracts/api/access) |

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [`AccessControl`](#AccessControl)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    
*   [`Ownable`](#Ownable)
     is a simpler mechanism with a single owner "role" that can be assigned to a single account. This simpler mechanism can be useful for quick tests but projects with production concerns are likely to outgrow it.
    
*   [`TimelockController`](#TimelockController)
     is used in combination with one of the above two mechanisms. By assigning a role to an instance of the `TimelockController` contract, the access to the functions controlled by that role will be delayed by some amount of time.
    

[](#authorization)
Authorization
--------------------------------

### [](#Ownable)
`Ownable`

Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions.

By default, the owner account will be the one that deploys the contract. This can later be changed with [`transferOwnership`](#Ownable-transferOwnership-address-)
.

This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.

Modifiers

*   [`onlyOwner()`](#Ownable-onlyOwner--)
    

Functions

*   [`constructor()`](#Ownable-constructor--)
    
*   [`owner()`](#Ownable-owner--)
    
*   [`renounceOwnership()`](#Ownable-renounceOwnership--)
    
*   [`transferOwnership(newOwner)`](#Ownable-transferOwnership-address-)
    

Events

*   [`OwnershipTransferred(previousOwner, newOwner)`](#Ownable-OwnershipTransferred-address-address-)
    

#### [](#Ownable-onlyOwner--)
`onlyOwner()` modifier

Throws if called by any account other than the owner.

#### [](#Ownable-constructor--)
`constructor()` internal

Initializes the contract setting the deployer as the initial owner.

#### [](#Ownable-owner--)
`owner() → address` public

Returns the address of the current owner.

#### [](#Ownable-renounceOwnership--)
`renounceOwnership()` public

Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#Ownable-transferOwnership-address-)
`transferOwnership(address newOwner)` public

Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.

#### [](#Ownable-OwnershipTransferred-address-address-)
`OwnershipTransferred(address previousOwner, address newOwner)` event

### [](#AccessControl)
`AccessControl`

Contract module that allows children to implement role-based access control mechanisms.

Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests:

    bytes32 public constant MY_ROLE = keccak256("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`hasRole`](#AccessControl-hasRole-bytes32-address-)
:

    function foo() public {
        require(hasRole(MY_ROLE, msg.sender));
        ...
    }

Roles can be granted and revoked dynamically via the [`grantRole`](#AccessControl-grantRole-bytes32-address-)
 and [`revokeRole`](#AccessControl-revokeRole-bytes32-address-)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [`grantRole`](#AccessControl-grantRole-bytes32-address-)
 and [`revokeRole`](#AccessControl-revokeRole-bytes32-address-)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [`_setRoleAdmin`](#AccessControl-_setRoleAdmin-bytes32-bytes32-)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

Functions

*   [`hasRole(role, account)`](#AccessControl-hasRole-bytes32-address-)
    
*   [`getRoleMemberCount(role)`](#AccessControl-getRoleMemberCount-bytes32-)
    
*   [`getRoleMember(role, index)`](#AccessControl-getRoleMember-bytes32-uint256-)
    
*   [`getRoleAdmin(role)`](#AccessControl-getRoleAdmin-bytes32-)
    
*   [`grantRole(role, account)`](#AccessControl-grantRole-bytes32-address-)
    
*   [`revokeRole(role, account)`](#AccessControl-revokeRole-bytes32-address-)
    
*   [`renounceRole(role, account)`](#AccessControl-renounceRole-bytes32-address-)
    
*   [`_setupRole(role, account)`](#AccessControl-_setupRole-bytes32-address-)
    
*   [`_setRoleAdmin(role, adminRole)`](#AccessControl-_setRoleAdmin-bytes32-bytes32-)
    

Events

*   [`RoleAdminChanged(role, previousAdminRole, newAdminRole)`](#AccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-)
    
*   [`RoleGranted(role, account, sender)`](#AccessControl-RoleGranted-bytes32-address-address-)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControl-RoleRevoked-bytes32-address-address-)
    

#### [](#AccessControl-hasRole-bytes32-address-)
`hasRole(bytes32 role, address account) → bool` public

Returns `true` if `account` has been granted `role`.

#### [](#AccessControl-getRoleMemberCount-bytes32-)
`getRoleMemberCount(bytes32 role) → uint256` public

Returns the number of accounts that have `role`. Can be used together with [`getRoleMember`](#AccessControl-getRoleMember-bytes32-uint256-)
 to enumerate all bearers of a role.

#### [](#AccessControl-getRoleMember-bytes32-uint256-)
`getRoleMember(bytes32 role, uint256 index) → address` public

Returns one of the accounts that have `role`. `index` must be a value between 0 and [`getRoleMemberCount`](#AccessControl-getRoleMemberCount-bytes32-)
, non-inclusive.

Role bearers are not sorted in any particular way, and their ordering may change at any point.

|     |     |
| --- | --- |
|     | When using [`getRoleMember`](#AccessControl-getRoleMember-bytes32-uint256-)<br> and [`getRoleMemberCount`](#AccessControl-getRoleMemberCount-bytes32-)<br>, make sure you perform all queries on the same block. See the following [forum post](https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296)<br> for more information. |

#### [](#AccessControl-getRoleAdmin-bytes32-)
`getRoleAdmin(bytes32 role) → bytes32` public

Returns the admin role that controls `role`. See [`grantRole`](#AccessControl-grantRole-bytes32-address-)
 and [`revokeRole`](#AccessControl-revokeRole-bytes32-address-)
.

To change a role’s admin, use [`_setRoleAdmin`](#AccessControl-_setRoleAdmin-bytes32-bytes32-)
.

#### [](#AccessControl-grantRole-bytes32-address-)
`grantRole(bytes32 role, address account)` public

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [`RoleGranted`](#AccessControl-RoleGranted-bytes32-address-address-)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#AccessControl-revokeRole-bytes32-address-)
`revokeRole(bytes32 role, address account)` public

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [`RoleRevoked`](#AccessControl-RoleRevoked-bytes32-address-address-)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#AccessControl-renounceRole-bytes32-address-)
`renounceRole(bytes32 role, address account)` public

Revokes `role` from the calling account.

Roles are often managed via [`grantRole`](#AccessControl-grantRole-bytes32-address-)
 and [`revokeRole`](#AccessControl-revokeRole-bytes32-address-)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [`RoleRevoked`](#AccessControl-RoleRevoked-bytes32-address-address-)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#AccessControl-_setupRole-bytes32-address-)
`_setupRole(bytes32 role, address account)` internal

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [`RoleGranted`](#AccessControl-RoleGranted-bytes32-address-address-)
 event. Note that unlike [`grantRole`](#AccessControl-grantRole-bytes32-address-)
, this function doesn’t perform any checks on the calling account.

|     |     |
| --- | --- |
|     | This function should only be called from the constructor when setting up the initial roles for the system.<br><br>Using this function in any other way is effectively circumventing the admin system imposed by [`AccessControl`](#AccessControl)<br>. |

#### [](#AccessControl-_setRoleAdmin-bytes32-bytes32-)
`_setRoleAdmin(bytes32 role, bytes32 adminRole)` internal

Sets `adminRole` as `role`'s admin role.

Emits a [`RoleAdminChanged`](#AccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-)
 event.

#### [](#AccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-)
`RoleAdminChanged(bytes32 role, bytes32 previousAdminRole, bytes32 newAdminRole)` event

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [`RoleAdminChanged`](#AccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-)
 not being emitted signaling this.

_Available since v3.1._

#### [](#AccessControl-RoleGranted-bytes32-address-address-)
`RoleGranted(bytes32 role, address account, address sender)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer except when using [`_setupRole`](#AccessControl-_setupRole-bytes32-address-)
.

#### [](#AccessControl-RoleRevoked-bytes32-address-address-)
`RoleRevoked(bytes32 role, address account, address sender)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)

[](#timelock)
Timelock
----------------------

### [](#TimelockController)
`TimelockController`

Contract module which acts as a timelocked controller. When set as the owner of an `Ownable` smart contract, it enforces a timelock on all `onlyOwner` maintenance operations. This gives time for users of the controlled contract to exit before a potentially dangerous maintenance operation is applied.

By default, this contract is self administered, meaning administration tasks have to go through the timelock process. The proposer (resp executor) role is in charge of proposing (resp executing) operations. A common use case is to position this [`TimelockController`](#TimelockController)
 as the owner of a smart contract, with a multisig or a DAO as the sole proposer.

_Available since v3.3._

Modifiers

*   [`onlyRole(role)`](#TimelockController-onlyRole-bytes32-)
    

Functions

*   [`constructor(minDelay, proposers, executors)`](#TimelockController-constructor-uint256-address---address---)
    
*   [`receive()`](#TimelockController-receive--)
    
*   [`isOperation(id)`](#TimelockController-isOperation-bytes32-)
    
*   [`isOperationPending(id)`](#TimelockController-isOperationPending-bytes32-)
    
*   [`isOperationReady(id)`](#TimelockController-isOperationReady-bytes32-)
    
*   [`isOperationDone(id)`](#TimelockController-isOperationDone-bytes32-)
    
*   [`getTimestamp(id)`](#TimelockController-getTimestamp-bytes32-)
    
*   [`getMinDelay()`](#TimelockController-getMinDelay--)
    
*   [`hashOperation(target, value, data, predecessor, salt)`](#TimelockController-hashOperation-address-uint256-bytes-bytes32-bytes32-)
    
*   [`hashOperationBatch(targets, values, datas, predecessor, salt)`](#TimelockController-hashOperationBatch-address---uint256---bytes---bytes32-bytes32-)
    
*   [`schedule(target, value, data, predecessor, salt, delay)`](#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-)
    
*   [`scheduleBatch(targets, values, datas, predecessor, salt, delay)`](#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-)
    
*   [`cancel(id)`](#TimelockController-cancel-bytes32-)
    
*   [`execute(target, value, data, predecessor, salt)`](#TimelockController-execute-address-uint256-bytes-bytes32-bytes32-)
    
*   [`executeBatch(targets, values, datas, predecessor, salt)`](#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-)
    
*   [`updateDelay(newDelay)`](#TimelockController-updateDelay-uint256-)
    

AccessControl

*   [`hasRole(role, account)`](#AccessControl-hasRole-bytes32-address-)
    
*   [`getRoleMemberCount(role)`](#AccessControl-getRoleMemberCount-bytes32-)
    
*   [`getRoleMember(role, index)`](#AccessControl-getRoleMember-bytes32-uint256-)
    
*   [`getRoleAdmin(role)`](#AccessControl-getRoleAdmin-bytes32-)
    
*   [`grantRole(role, account)`](#AccessControl-grantRole-bytes32-address-)
    
*   [`revokeRole(role, account)`](#AccessControl-revokeRole-bytes32-address-)
    
*   [`renounceRole(role, account)`](#AccessControl-renounceRole-bytes32-address-)
    
*   [`_setupRole(role, account)`](#AccessControl-_setupRole-bytes32-address-)
    
*   [`_setRoleAdmin(role, adminRole)`](#AccessControl-_setRoleAdmin-bytes32-bytes32-)
    

Events

*   [`CallScheduled(id, index, target, value, data, predecessor, delay)`](#TimelockController-CallScheduled-bytes32-uint256-address-uint256-bytes-bytes32-uint256-)
    
*   [`CallExecuted(id, index, target, value, data)`](#TimelockController-CallExecuted-bytes32-uint256-address-uint256-bytes-)
    
*   [`Cancelled(id)`](#TimelockController-Cancelled-bytes32-)
    
*   [`MinDelayChange(oldDuration, newDuration)`](#TimelockController-MinDelayChange-uint256-uint256-)
    

AccessControl

*   [`RoleAdminChanged(role, previousAdminRole, newAdminRole)`](#AccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-)
    
*   [`RoleGranted(role, account, sender)`](#AccessControl-RoleGranted-bytes32-address-address-)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControl-RoleRevoked-bytes32-address-address-)
    

#### [](#TimelockController-onlyRole-bytes32-)
`onlyRole(bytes32 role)` modifier

Modifier to make a function callable only by a certain role. In addition to checking the sender’s role, `address(0)` 's role is also considered. Granting a role to `address(0)` is equivalent to enabling this role for everyone.

#### [](#TimelockController-constructor-uint256-address---address---)
`constructor(uint256 minDelay, address[] proposers, address[] executors)` public

Initializes the contract with a given `minDelay`.

#### [](#TimelockController-receive--)
`receive()` external

Contract might receive/hold ETH as part of the maintenance process.

#### [](#TimelockController-isOperation-bytes32-)
`isOperation(bytes32 id) → bool pending` public

Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.

#### [](#TimelockController-isOperationPending-bytes32-)
`isOperationPending(bytes32 id) → bool pending` public

Returns whether an operation is pending or not.

#### [](#TimelockController-isOperationReady-bytes32-)
`isOperationReady(bytes32 id) → bool ready` public

Returns whether an operation is ready or not.

#### [](#TimelockController-isOperationDone-bytes32-)
`isOperationDone(bytes32 id) → bool done` public

Returns whether an operation is done or not.

#### [](#TimelockController-getTimestamp-bytes32-)
`getTimestamp(bytes32 id) → uint256 timestamp` public

Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations).

#### [](#TimelockController-getMinDelay--)
`getMinDelay() → uint256 duration` public

Returns the minimum delay for an operation to become valid.

This value can be changed by executing an operation that calls `updateDelay`.

#### [](#TimelockController-hashOperation-address-uint256-bytes-bytes32-bytes32-)
`hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) → bytes32 hash` public

Returns the identifier of an operation containing a single transaction.

#### [](#TimelockController-hashOperationBatch-address---uint256---bytes---bytes32-bytes32-)
`hashOperationBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) → bytes32 hash` public

Returns the identifier of an operation containing a batch of transactions.

#### [](#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-)
`schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay)` public

Schedule an operation containing a single transaction.

Emits a [`CallScheduled`](#TimelockController-CallScheduled-bytes32-uint256-address-uint256-bytes-bytes32-uint256-)
 event.

Requirements:

*   the caller must have the 'proposer' role.
    

#### [](#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-)
`scheduleBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt, uint256 delay)` public

Schedule an operation containing a batch of transactions.

Emits one [`CallScheduled`](#TimelockController-CallScheduled-bytes32-uint256-address-uint256-bytes-bytes32-uint256-)
 event per transaction in the batch.

Requirements:

*   the caller must have the 'proposer' role.
    

#### [](#TimelockController-cancel-bytes32-)
`cancel(bytes32 id)` public

Cancel an operation.

Requirements:

*   the caller must have the 'proposer' role.
    

#### [](#TimelockController-execute-address-uint256-bytes-bytes32-bytes32-)
`execute(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt)` public

Execute an (ready) operation containing a single transaction.

Emits a [`CallExecuted`](#TimelockController-CallExecuted-bytes32-uint256-address-uint256-bytes-)
 event.

Requirements:

*   the caller must have the 'executor' role.
    

#### [](#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-)
`executeBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt)` public

Execute an (ready) operation containing a batch of transactions.

Emits one [`CallExecuted`](#TimelockController-CallExecuted-bytes32-uint256-address-uint256-bytes-)
 event per transaction in the batch.

Requirements:

*   the caller must have the 'executor' role.
    

#### [](#TimelockController-updateDelay-uint256-)
`updateDelay(uint256 newDelay)` external

Changes the minimum timelock duration for future operations.

Emits a [`MinDelayChange`](#TimelockController-MinDelayChange-uint256-uint256-)
 event.

Requirements:

*   the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.
    

#### [](#TimelockController-CallScheduled-bytes32-uint256-address-uint256-bytes-bytes32-uint256-)
`CallScheduled(bytes32 id, uint256 index, address target, uint256 value, bytes data, bytes32 predecessor, uint256 delay)` event

Emitted when a call is scheduled as part of operation `id`.

#### [](#TimelockController-CallExecuted-bytes32-uint256-address-uint256-bytes-)
`CallExecuted(bytes32 id, uint256 index, address target, uint256 value, bytes data)` event

Emitted when a call is performed as part of operation `id`.

#### [](#TimelockController-Cancelled-bytes32-)
`Cancelled(bytes32 id)` event

Emitted when operation `id` is cancelled.

#### [](#TimelockController-MinDelayChange-uint256-uint256-)
`MinDelayChange(uint256 oldDuration, uint256 newDuration)` event

Emitted when the minimum delay for future operations is modified.

#### [](#timelock-terminology)
Terminology

*   **Operation:** A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see [operation lifecycle](#access-control.adoc#operation_lifecycle)
    ). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content.
    
*   **Operation status:**
    
    *   **Unset:** An operation that is not part of the timelock mechanism.
        
    *   **Pending:** An operation that has been scheduled, before the timer expires.
        
    *   **Ready:** An operation that has been scheduled, after the timer expires.
        
    *   **Done:** An operation that has been executed.
        
    
*   **Predecessor**: An (optional) dependency between operations. An operation can depend on another operation (its predecessor), forcing the execution order of these two operations.
    
*   **Role**:
    
    *   **Proposer:** An address (smart contract or EOA) that is in charge of scheduling (and cancelling) operations.
        
    *   **Executor:** An address (smart contract or EOA) that is in charge of executing operations.
        
    

#### [](#timelock-operation)
Operation structure

Operation executed by the [`TimelockControler`](#TimelockController)
 can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations.

Both operations contain:

*   **Target**, the address of the smart contract that the timelock should operate on.
    
*   **Value**, in wei, that should be sent with the transaction. Most of the time this will be 0. Ether can be deposited before-end or passed along when executing the transaction.
    
*   **Data**, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role `ROLE` to `ACCOUNT` can be encode using web3js as follows:
    

    const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI()

*   **Predecessor**, that specifies a dependency between operations. This dependency is optional. Use `bytes32(0)` if the operation does not have any dependency.
    
*   **Salt**, used to disambiguate two otherwise identical operations. This can be any random value.
    

In the case of batched operations, `target`, `value` and `data` are specified as arrays, which must be of the same length.

#### [](#timelock-operation-lifecycle)
Operation lifecycle

Timelocked operations are identified by a unique id (their hash) and follow a specific lifecycle:

`Unset` → `Pending` → `Pending` + `Ready` → `Done`

*   By calling [`schedule`](#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-)
     (or [`scheduleBatch`](#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-)
    ), a proposer moves the operation from the `Unset` to the `Pending` state. This starts a timer that must be longer than the minimum delay. The timer expires at a timestamp accessible through the [`getTimestamp`](#TimelockController-getTimestamp-bytes32-)
     method.
    
*   Once the timer expires, the operation automatically gets the `Ready` state. At this point, it can be executed.
    
*   By calling [`execute`](#TimelockController-TimelockController-execute-address-uint256-bytes-bytes32-bytes32-)
     (or [`executeBatch`](#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-)
    ), an executor triggers the operation’s underlying transactions and moves it to the `Done` state. If the operation has a predecessor, it has to be in the `Done` state for this transition to succeed.
    
*   [`cancel`](#TimelockController-TimelockController-cancel-bytes32-)
     allows proposers to cancel any `Pending` operation. This resets the operation to the `Unset` state. It is thus possible for a proposer to re-schedule an operation that has been cancelled. In this case, the timer restarts when the operation is re-scheduled.
    

Operations status can be queried using the functions:

*   [`isOperationPending(bytes32)`](#TimelockController-isOperationPending-bytes32-)
    
*   [`isOperationReady(bytes32)`](#TimelockController-isOperationReady-bytes32-)
    
*   [`isOperationDone(bytes32)`](#TimelockController-isOperationDone-bytes32-)
    

#### [](#timelock-roles)
Roles

##### [](#timelock-admin)
Admin

The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, both the timelock and the deployer have this role. After further configuration and testing, the deployer can renounce this role such that all further maintenance operations have to go through the timelock process.

This role is identified by the **TIMELOCK\_ADMIN\_ROLE** value: `0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5`

##### [](#timelock-proposer)
Proposer

The proposers are in charge of scheduling (and cancelling) operations. This is a critical role, that should be given to governing entities. This could be an EOA, a multisig, or a DAO.

|     |     |
| --- | --- |
|     | **Proposer fight:** Having multiple proposers, while providing redundancy in case one becomes unavailable, can be dangerous. As proposer have their say on all operations, they could cancel operations they disagree with, including operations to remove them for the proposers. |

This role is identified by the **PROPOSER\_ROLE** value: `0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1`

##### [](#timelock-executor)
Executor

The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executor can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers.

This role is identified by the **EXECUTOR\_ROLE** value: `0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63`

|     |     |
| --- | --- |
|     | A live contract without at least one proposer and one executor is locked. Make sure these roles are filled by reliable entities before the deployer renounces its administrative rights in favour of the timelock contract itself. See the [`AccessControl`](#AccessControl)<br> documentation to learn more about role management. |

[← Utilities](/contracts/3.x/utilities)

[Cryptography →](/contracts/3.x/api/cryptography)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, _public_key: felt252
        ) -> felt252;
    }

[← Accounts](/contracts-cairo/0.8.0-beta.1/accounts)

[API Reference →](/contracts-cairo/0.8.0-beta.1/api/account)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of methods and constants found in `openzeppelin/security/`.

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Initializable](#initializable)
    
*   [Pausable](#pausable)
    
*   [Reentrancy Guard](#reentrancy_guard)
    
*   [SafeMath](#safemath)
    
    *   [SafeUint256](#safeuint256)
        
    

[](#initializable)
Initializable
--------------------------------

The Initializable library provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to setup a contract’s initial state when a constructor cannot be used.

The recommended pattern with Initializable is to include a check that the Initializable state is `False` and invoke `initialize` in the target function like this:

    from openzeppelin.security.initializable.library import Initializable
    
    @external
    func foo{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        let (initialized) = Initializable.initialized()
        assert initialized = FALSE
    
        Initializable.initialize()
        return ()
    end

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used on one function. |

[](#pausable)
Pausable
----------------------

The Pausable library allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To use the Pausable library, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when not paused, insert `assert_not_paused`. For methods that should be available only when paused, insert `assert_paused`. For example:

    from openzeppelin.security.pausable.library import Pausable
    
    @external
    func whenNotPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_not_paused()
    
        # function body
        return ()
    end
    
    @external
    func whenPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_paused()
    
        # function body
        return ()
    end

|     |     |
| --- | --- |
|     | `pause` and `unpause` already include these assertions. In other words, `pause` cannot be invoked when already paused and vice versa. |

For a list of full implementations utilizing the Pausable library, see:

*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [`reentrancy guard`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/reentrancyguard/library.cairo)
 library exposes two methods `_start` and `_end` to protect functions against reentrancy attacks. The protected function must call `ReentrancyGuard._start` before the first function statement, and `ReentrancyGuard._end` before the return statement, as shown below:

    from openzeppelin.security.reentrancyguard.library import ReentrancyGuard
    
    func test_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
       ReentrancyGuard._start()
       # function body
       ReentrancyGuard._end()
       return ()
    end

[](#safemath)
SafeMath
----------------------

### [](#safeuint256)
SafeUint256

The SafeUint256 namespace in the [SafeMath library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/safemath/library.cairo)
 offers arithmetic for unsigned 256-bit integers (uint256) by leveraging Cairo’s Uint256 library and integrating overflow checks. Some of Cairo’s Uint256 functions do not revert upon overflows. For instance, `uint256_add` will return a bit carry when the sum exceeds 256 bits. This library includes an additional assertion ensuring values do not overflow.

Using SafeUint256 methods is rather straightforward. Simply import SafeUint256 and insert the arithmetic method like this:

    from openzeppelin.security.safemath.library import SafeUint256
    
    func add_two_uints{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        } (a: Uint256, b: Uint256) -> (c: Uint256):
        let (c: Uint256) = SafeUint256.add(a, b)
        return (c)
    end

[← ERC721](/contracts-cairo/0.3.0/erc721)

[Introspection →](/contracts-cairo/0.3.0/introspection)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are derived from a private key, all Starknet accounts are contracts. This means there’s no Externally Owned Account (EOA) concept on Starknet.

Instead, the network features native account abstraction and signature validation happens at the contract level.

For a general overview of account abstraction, see [Starknet’s documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/introduction/)
. A more detailed discussion on the topic can be found in [Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

|     |     |
| --- | --- |
|     | For detailed information on the usage and implementation check the [API Reference](api/account)<br> section. |

[](#standard_account_interface)
Standard Account Interface
----------------------------------------------------------

Accounts in Starknet are smart contracts, and so they can be deployed and interacted with like any other contract, and can be extended to implement any custom logic. However, an account is a special type of contract that is used to validate and execute transactions. For this reason, it must implement a set of entrypoints that the protocol uses for this execution flow. The [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 proposal defines a standard interface for accounts, supporting this execution flow and interoperability with DApps in the ecosystem.

### [](#isrc6_interface)
ISRC6 Interface

    /// Represents a call to a target contract function.
    struct Call {
        to: ContractAddress,
        selector: felt252,
        calldata: Array<felt252>
    }
    
    /// Standard Account Interface
    trait ISRC6 {
        /// Executes a transaction through the account.
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
    
        /// Asserts whether the transaction is valid to be executed.
        fn __validate__(calls: Array<Call>) -> felt252;
    
        /// Asserts whether a given signature for a given hash is valid.
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 adds the `is_valid_signature` method. This method is not used by the protocol, but it’s useful for DApps to verify the validity of signatures, supporting features like Sign In with Starknet.

SNIP-6 also defines that compliant accounts must implement the SRC5 interface following [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
, as a mechanism for detecting whether a contract is an account or not through introspection.

### [](#isrc5_interface)
ISRC5 Interface

    /// Standard Interface Detection
    trait ISRC5 {
        /// Queries if a contract implements a given interface.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 compliant accounts must return `true` when queried for the ISRC6 interface Id.

Even though these interfaces are not enforced by the protocol, it’s recommended to implement them for enabling interoperability with the ecosystem.

[](#protocol_level_methods)
Protocol-level methods
--------------------------------------------------

In this section we will describe the methods that the protocol uses for abstracting the accounts. The first two are required for enabling accounts to be used for executing transactions. The rest are optional:

1.  `__validate__` verifies the validity of the transaction to be executed. This is usually used to validate signatures, but the entrypoint implementation can be customized to feature any validation mechanism [with some limitations](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/validate_and_execute/#validate_limitations)
    .
    
2.  `__execute__` executes the transaction if the validation is successful.
    
3.  `__validate_declare__` optional entrypoint similar to `__validate__` but for transactions meant to declare other contracts.
    
4.  `__validate_deploy__` optional entrypoint similar to `__validate__` but meant for [Counterfactual Deployments](guides/deployment)
    .
    

|     |     |
| --- | --- |
|     | Although these entrypoints are available to the protocol for its regular transaction flow, they can also be called like any other method. |

[](#deploying_an_account)
Deploying an account
----------------------------------------------

In Starknet there are two ways of deploying smart contracts: using the `deploy_syscall` and doing counterfactual deployments. The former can be easily done with the [Universal Deployer Contract (UDC)](udc)
, a contract that wraps and exposes the `deploy_syscall` to provide arbitrary deployments through regular contract calls. But if you don’t have an account to invoke it, you will probably want to use the latter.

To do counterfactual deployments, you need to implement another protocol-level entrypoint named `__validate_deploy__`. Check the [Counterfactual Deployments](guides/deployment)
 guide to learn how.

[← API Reference](/contracts-cairo/0.8.0-beta.1/api/upgrades)

[Counterfactual deployments →](/contracts-cairo/0.8.0-beta.1/guides/deployment)




 Account - OpenZeppelin Docs       

Account
=======

Reference of interfaces, presets, and utilities related to account contracts.

[](#core)
Core
--------------

### [](#ISRC6)
`ISRC6`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/account/interface.cairo#L12)

    use openzeppelin::account::interface::ISRC6;

Interface of the SRC6 Standard Account as defined in the [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
.

[SRC5 ID](introspection#ISRC5)

0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd

Functions

*   [`__execute__(calls)`](#ISRC6-__execute__)
    
*   [`__validate__(calls)`](#ISRC6-__validate__)
    
*   [`is_valid_signature(hash, signature)`](#ISRC6-is_valid_signature)
    

#### [](#ISRC6-Functions)
Functions

#### [](#ISRC6-__execute__)
`__execute__(calls: Array<Call>) → Array<Span<felt252>>` external

Executes the list of calls as a transaction after validation.

Returns an array with each call’s output.

|     |     |
| --- | --- |
|     | The `Call` struct is defined in [corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3)<br>. |

#### [](#ISRC6-__validate__)
`__validate__(calls: Array<Call>) → felt252` external

Validates a transaction before execution.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#ISRC6-is_valid_signature)
`is_valid_signature(hash: felt252, signature: Array<felt252>) → felt252` external

Validates whether a signature is valid or not for the given message hash.

Returns the short string `'VALID'` if valid, otherwise it reverts.

### [](#Account)
`Account`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/account/account.cairo#L27)

    use openzeppelin::account::Account;

Account contract implementation extending [`ISRC6`](#ISRC6)
.

Constructor

*   [`constructor(self, _public_key)`](#Account-constructor)
    

External Functions

*   [`__validate_deploy__(self, hash, signature)`](#Account-__validate_deploy__)
    

SRC6Impl

*   [`__execute__(self, calls)`](#Account-__execute__)
    
*   [`__validate__(self, calls)`](#Account-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#Account-is_valid_signature)
    

SRC5Impl

*   [`supports_interface(self, interface_id)`](#Account-supports_interface)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#Account-__validate_declare__)
    

PublicKeyImpl

*   [`set_public_key(self, new_public_key)`](#Account-set_public_key)
    
*   [`get_public_key(self)`](#Account-get_public_key)
    

Internal Functions

InternalImpl

*   [`initializer(self, _public_key)`](#Account-initializer)
    
*   [`validate_transaction(self)`](#Account-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#Account-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#Account-_is_valid_signature)
    
*   [`assert_only_self(self)`](#Account-assert_only_self)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#Account-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#Account-OwnerRemoved)
    

#### [](#Account-Constructor)
Constructor

#### [](#Account-constructor)
`constructor(ref self: ContractState, _public_key: felt252)` constructor

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#Account-OwnerAdded)
 event.

#### [](#Account-External-Functions)
External Functions

#### [](#Account-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, _public_key: felt252) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#Account-__execute__)
`__execute__(ref self: ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#Account-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#Account-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#Account-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#Account-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#Account-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: felt252)` external

Sets a new public key for the account. Only accesible by the account calling itself through `__execute__`.

Emits both an [OwnerRemoved](#Account-OwnerRemoved)
 and an [OwnerAdded](#Account-OwnerAdded)
 event.

#### [](#Account-get_public_key)
`get_public_key(self: @ContractState) → felt252` external

Returns the current public key of the account.

#### [](#Account-Internal-Functions)
Internal Functions

#### [](#Account-initializer)
`initializer(ref self: ContractState, _public_key: felt252)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#Account-OwnerAdded)
 event.

#### [](#Account-validate_transaction)
`validate_transaction(self: @ContractState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#Account-_set_public_key)
`_set_public_key(ref self: ContractState, new_public_key: felt252)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#Account-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#Account-_is_valid_signature)
`_is_valid_signature(self: @ContractState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account current public key.

#### [](#Account-assert_only_self)
`assert_only_self(self: @ContractState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#Account-Events)
Events

#### [](#Account-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#Account-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

[← Counterfactual deployments](/contracts-cairo/0.8.0-beta.0/guides/deployment)

[Access Control →](/contracts-cairo/0.8.0-beta.0/access)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are derived from a private key, all Starknet accounts are contracts. This means there’s no Externally Owned Account (EOA) concept on Starknet.

Instead, the network features native account abstraction and signature validation happens at the contract level.

For a general overview of account abstraction, see [Starknet’s documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/introduction/)
. A more detailed discussion on the topic can be found in [Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

|     |     |
| --- | --- |
|     | For detailed information on the usage and implementation check the [API Reference](api/account)<br> section. |

[](#standard_account_interface)
Standard Account Interface
----------------------------------------------------------

Accounts in Starknet are smart contracts, and so they can be deployed and interacted with like any other contract, and can be extended to implement any custom logic. However, an account is a special type of contract that is used to validate and execute transactions. For this reason, it must implement a set of entrypoints that the protocol uses for this execution flow. The [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 proposal defines a standard interface for accounts, supporting this execution flow and interoperability with DApps in the ecosystem.

### [](#isrc6_interface)
ISRC6 Interface

    /// Represents a call to a target contract function.
    struct Call {
        to: ContractAddress,
        selector: felt252,
        calldata: Array<felt252>
    }
    
    /// Standard Account Interface
    trait ISRC6 {
        /// Executes a transaction through the account.
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
    
        /// Asserts whether the transaction is valid to be executed.
        fn __validate__(calls: Array<Call>) -> felt252;
    
        /// Asserts whether a given signature for a given hash is valid.
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 adds the `is_valid_signature` method. This method is not used by the protocol, but it’s useful for DApps to verify the validity of signatures, supporting features like Sign In with Starknet.

SNIP-6 also defines that compliant accounts must implement the SRC5 interface following [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
, as a mechanism for detecting whether a contract is an account or not through introspection.

### [](#isrc5_interface)
ISRC5 Interface

    /// Standard Interface Detection
    trait ISRC5 {
        /// Queries if a contract implements a given interface.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 compliant accounts must return `true` when queried for the ISRC6 interface Id.

Even though these interfaces are not enforced by the protocol, it’s recommended to implement them for enabling interoperability with the ecosystem.

[](#protocol_level_methods)
Protocol-level methods
--------------------------------------------------

In this section we will describe the methods that the protocol uses for abstracting the accounts. The first two are required for enabling accounts to be used for executing transactions. The rest are optional:

1.  `__validate__` verifies the validity of the transaction to be executed. This is usually used to validate signatures, but the entrypoint implementation can be customized to feature any validation mechanism [with some limitations](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/validate_and_execute/#validate_limitations)
    .
    
2.  `__execute__` executes the transaction if the validation is successful.
    
3.  `__validate_declare__` optional entrypoint similar to `__validate__` but for transactions meant to declare other contracts.
    
4.  `__validate_deploy__` optional entrypoint similar to `__validate__` but meant for [Counterfactual Deployments](guides/deployment)
    .
    

|     |     |
| --- | --- |
|     | Although these entrypoints are available to the protocol for its regular transaction flow, they can also be called like any other method. |

[](#deploying_an_account)
Deploying an account
----------------------------------------------

In Starknet there are two ways of deploying smart contracts: using the `deploy_syscall` and doing counterfactual deployments. The former can be easily done with the [Universal Deployer Contract (UDC)](udc)
, a contract that wraps and exposes the `deploy_syscall` to provide arbitrary deployments through regular contract calls. But if you don’t have an account to invoke it, you will probably want to use the latter.

To do counterfactual deployments, you need to implement another protocol-level entrypoint named `__validate_deploy__`. Check the [Counterfactual Deployments](guides/deployment)
 guide to learn how.

[← API Reference](/contracts-cairo/0.8.0-beta.0/api/upgrades)

[Counterfactual deployments →](/contracts-cairo/0.8.0-beta.0/guides/deployment)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

Access control—​that is, "who is allowed to do this thing"--is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Ownable](#ownable)
    
    *   [Quickstart](#quickstart)
        
    *   [Ownable library API](#ownable_library_api)
        
    *   [Ownable events](#ownable_events)
        
    
*   [AccessControl](#accesscontrol)
    
    *   [Usage](#usage)
        
    *   [Granting and revoking roles](#granting_and_revoking_roles)
        
    *   [Creating role identifiers](#creating_role_identifiers)
        
    *   [AccessControl library API](#accesscontrol_library_api)
        
    *   [AccessControl events](#accesscontrol_events)
        
    

[](#ownable)
Ownable
--------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 for implementing ownership in your contracts.

### [](#quickstart)
Quickstart

Integrating [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [initializer](#initializer)
 like this:

    from openzeppelin.access.ownable.library import Ownable
    
    @constructor
    func constructor{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(owner: felt):
        Ownable.initializer(owner)
        return ()
    end

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    from openzeppelin.access.ownable.library import Ownable
    
    func protected_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        Ownable.assert_only_owner()
        return ()
    end

### [](#ownable_library_api)
Ownable library API

    func initializer(owner: felt):
    end
    
    func assert_only_owner():
    end
    
    func owner() -> (owner: felt):
    end
    
    func transfer_ownership(new_owner: felt):
    end
    
    func renounce_ownership():
    end
    
    func _transfer_ownership(new_owner: felt):
    end

#### [](#initializer)
`initializer`

Initializes Ownable access control and should be called in the implementing contract’s constructor. Assigns `owner` as the initial owner address of the contract.

This must be called only once.

Parameters:

    owner: felt

Returns: None.

#### [](#assert_only_owner)
`assert_only_owner`

Reverts if called by any account other than the owner. In case of renounced ownership, any call from the default zero address will also be reverted.

Parameters: None.

Returns: None.

#### [](#owner)
`owner`

Returns the address of the current owner.

Parameters: None.

Returns:

    owner: felt

#### [](#transfer_ownership)
`transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

#### [](#renounce_ownership)
`renounce_ownership`

Leaves the contract without owner. It will not be possible to call functions with `assert_only_owner` anymore. Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters: None.

Returns: None.

#### [](#transfer-ownership-internal)
`_transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). [`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

### [](#ownable_events)
Ownable events

    func OwnershipTransferred(previousOwner: felt, newOwner: felt):
    end

#### [](#ownershiptransferred)
OwnershipTransferred

Emitted when ownership of a contract is transferred from `previousOwner` to `newOwner`.

Parameters:

    previousOwner: felt
    newOwner: felt

[](#accesscontrol)
AccessControl
--------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [assert\_only\_owner](#assert_only_owner)
. This check can be enforced through [assert\_only\_role](#assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role (see [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers).

Here’s a simple example of implementing `AccessControl` on a portion of an [ERC20 token contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 which defines and sets the 'minter' role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](#accesscontrol)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](#ownable)
. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens, and by using `assert_only_role`:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt,
            burner: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        AccessControl._grant_role(BURNER_ROLE, burner)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses `_grant_role`, an [`internal`](extensibility#the_pattern)
 function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `assert_only_role` check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the `grant_role` and `revoke_role` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_set_role_admin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    from openzeppelin.utils.constants import DEFAULT_ADMIN_ROLE
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            admin: felt,
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
    
        AccessControl._grant_role(DEFAULT_ADMIN_ROLE, admin)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

The following example uses the [AccessControl mock contract](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/AccessControl.cairo)
 which exposes the role management functions. To grant and revoke roles in Python, for example:

    MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    # grants MINTER_ROLE and BURNER_ROLE to account1 and account2 respectively
    await signer.send_transactions(
        admin, [\
            (accesscontrol.contract_address, 'grantRole', [MINTER_ROLE, account1.contract_address]),\
            (accesscontrol.contract_address, 'grantRole', [BURNER_ROLE, account2.contract_address])\
        ]
    )
    
    # revokes MINTER_ROLE from account1
    await signer.send_transaction(
        admin,
        accesscontrol.contract_address,
        'revokeRole',
        [MINTER_ROLE, account1.contract_address]
    )

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier. For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements store a maximum of 252 bits. Even further, a declared _constant_ field element in a StarkNet contract stores even less (see [cairo\_constants](https://github.com/starkware-libs/cairo-lang/blob/167b28bcd940fd25ea3816204fa882a0b0a49603/src/starkware/cairo/lang/cairo_constants.py#L1)
). With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   using the first or last 251 bits of keccak256 hash digests
    
*   using Cairo’s [hash2](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash.cairo)
    

### [](#accesscontrol_library_api)
AccessControl library API

    func initializer():
    end
    
    func assert_only_role(role: felt):
    end
    
    func has_role(role: felt, user: felt) -> (has_role: felt):
    end
    
    func get_role_admin(role: felt) -> (admin: felt):
    end
    
    func grant_role(role: felt, user: felt):
    end
    
    func revoke_role(role: felt, user: felt):
    end
    
    func renounce_role(role: felt, user: felt):
    end
    
    func _grant_role(role: felt, user: felt):
    end
    
    func _revoke_role(role: felt, user: felt):
    end
    
    func _set_role_admin(role: felt, admin_role: felt):
    end

#### [](#initializer-accesscontrol)
`initializer`

Initializes AccessControl and should be called in the implementing contract’s constructor.

This must only be called once.

Parameters: None.

Returns: None.

#### [](#assert_only_role)
`assert_only_role`

Checks that an account has a specific role. Reverts with a message including the required role.

Parameters:

    role: felt

Returns: None.

#### [](#has_role)
has\_role

Returns `TRUE` if `user` has been granted `role`, `FALSE` otherwise.

Parameters:

    role: felt
    user: felt

Returns:

    has_role: felt

#### [](#get_role_admin)
`get_role_admin`

Returns the admin role that controls `role`. See [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
.

To change a role’s admin, use [`_set_role_admin`](#set_role_admin)
.

Parameters:

    role: felt

Returns:

    admin: felt

#### [](#grant_role)
`grant_role`

Grants `role` to `user`.

If `user` had not been already granted `role`, emits a [RoleGranted](#rolegranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revoke_role)
`revoke_role`

Revokes `role` from `user`.

If `user` had been granted `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#renounce_role)
`renounce_role`

Revokes `role` from the calling `user`.

Roles are often managed via [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling `user` had been revoked `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must be `user`.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#grantrole-internal)
`_grant_role`

Grants `role` to `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleGranted](#rolegranted)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revokerole-internal)
`_revoke_role`

Revokes `role` from `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleRevoked](#rolerevoked)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#setroleadmin)
`_set_role_admin`

[`internal`](extensibility#the_pattern)
 function that sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#roleadminchanged)
 event.

Parameters:

    role: felt
    admin_role: felt

Returns: None.

### [](#accesscontrol_events)
AccessControl events

    func RoleGranted(role: felt, account: felt, sender: felt):
    end
    
    func RoleRevoked(role: felt, account: felt, sender: felt):
    end
    
    func RoleAdminChanged(
        role: felt,
        previousAdminRole: felt,
        newAdminRole: felt
      ):
    end

#### [](#rolegranted)
`RoleGranted`

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

Parameters:

    role: felt
    account: felt
    sender: felt

#### [](#rolerevoked)
`RoleRevoked`

Emitted when account is revoked role.

`sender` is the account that originated the contract call:

*   if using [revoke\_role](#revoke_role)
    , it is the admin role bearer
    
*   if using [renounce\_role](#renounce_role)
    , it is the role bearer (i.e. `account`).
    

    role: felt
    account: felt
    sender: felt

#### [](#roleadminchanged)
`RoleAdminChanged`

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite `RoleAdminChanged` not being emitted signaling this.

    role: felt
    previousAdminRole: felt
    newAdminRole: felt

[← Accounts](/contracts-cairo/0.3.1/accounts)

[ERC20 →](/contracts-cairo/0.3.1/erc20)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of methods and constants found in `openzeppelin/security/`.

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Initializable](#initializable)
    
*   [Pausable](#pausable)
    
*   [Reentrancy Guard](#reentrancy_guard)
    
*   [SafeMath](#safemath)
    
    *   [SafeUint256](#safeuint256)
        
    

[](#initializable)
Initializable
--------------------------------

The Initializable library provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to setup a contract’s initial state when a constructor cannot be used.

The recommended pattern with Initializable is to include a check that the Initializable state is `False` and invoke `initialize` in the target function like this:

    from openzeppelin.security.initializable.library import Initializable
    
    @external
    func foo{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        let (initialized) = Initializable.initialized()
        assert initialized = FALSE
    
        Initializable.initialize()
        return ()
    end

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used on one function. |

[](#pausable)
Pausable
----------------------

The Pausable library allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To use the Pausable library, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when not paused, insert `assert_not_paused`. For methods that should be available only when paused, insert `assert_paused`. For example:

    from openzeppelin.security.pausable.library import Pausable
    
    @external
    func whenNotPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_not_paused()
    
        # function body
        return ()
    end
    
    @external
    func whenPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_paused()
    
        # function body
        return ()
    end

|     |     |
| --- | --- |
|     | `pause` and `unpause` already include these assertions. In other words, `pause` cannot be invoked when already paused and vice versa. |

For a list of full implementations utilizing the Pausable library, see:

*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [`reentrancy guard`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/reentrancyguard/library.cairo)
 library exposes two methods `_start` and `_end` to protect functions against reentrancy attacks. The protected function must call `ReentrancyGuard._start` before the first function statement, and `ReentrancyGuard._end` before the return statement, as shown below:

    from openzeppelin.security.reentrancyguard.library import ReentrancyGuard
    
    func test_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
       ReentrancyGuard._start()
       # function body
       ReentrancyGuard._end()
       return ()
    end

[](#safemath)
SafeMath
----------------------

### [](#safeuint256)
SafeUint256

The SafeUint256 namespace in the [SafeMath library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/safemath/library.cairo)
 offers arithmetic for unsigned 256-bit integers (uint256) by leveraging Cairo’s Uint256 library and integrating overflow checks. Some of Cairo’s Uint256 functions do not revert upon overflows. For instance, `uint256_add` will return a bit carry when the sum exceeds 256 bits. This library includes an additional assertion ensuring values do not overflow.

Using SafeUint256 methods is rather straightforward. Simply import SafeUint256 and insert the arithmetic method like this:

    from openzeppelin.security.safemath.library import SafeUint256
    
    func add_two_uints{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        } (a: Uint256, b: Uint256) -> (c: Uint256):
        let (c: Uint256) = SafeUint256.add(a, b)
        return (c)
    end

[← ERC721](/contracts-cairo/0.4.0b/erc721)

[Introspection →](/contracts-cairo/0.4.0b/introspection)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `ERC20.cairo` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Interface](#interface)
    
    *   [ERC20 compatibility](#erc20_compatibility)
        
    
*   [Usage](#usage)
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC20 (basic)](#erc20_basic)
        
    *   [ERC20Mintable](#erc20mintable)
        
    *   [ERC20Pausable](#erc20pausable)
        
    *   [ERC20Upgradeable](#erc20upgradeable)
        
    
*   [API Specification](#api_specification)
    
    *   [Methods](#methods)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`decimals`](#decimals)
            
        *   [`totalSupply`](#totalsupply)
            
        *   [`balanceOf`](#balanceof)
            
        *   [`allowance`](#allowance)
            
        *   [`transfer`](#transfer)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        
    *   [Events](#events)
        
        *   [`Transfer (event)`](#transfer_event)
            
        *   [`Approval (event)`](#approval_event)
            
        
    

[](#interface)
Interface
------------------------

    @contract_interface
    namespace IERC20:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func decimals() -> (decimals: felt):
        end
    
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func balanceOf(account: felt) -> (balance: Uint256):
        end
    
        func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
        end
    
        func transfer(recipient: felt, amount: Uint256) -> (success: felt):
        end
    
        func transferFrom(
                sender: felt,
                recipient: felt,
                amount: Uint256
            ) -> (success: felt):
        end
    
        func approve(spender: felt, amount: Uint256) -> (success: felt):
        end
    end

### [](#erc20_compatibility)
ERC20 compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard, in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it accepts a `felt` argument for `decimals` in the constructor calldata with a max value of 2^8 (imitating `uint8` type)
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `transfer`, `transferFrom` and `approve` will never return anything different from `TRUE` because they will revert on any error
    
*   function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo-lang/blob/7712b21fc3b1cb02321a58d0c0579f5370147a8b/src/starkware/starknet/public/abi.py#L25)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    

[](#usage)
Usage
----------------

Use cases go from medium of exchange currency to voting rights, staking, and more.

Considering that the constructor method looks like this:

    func constructor(
        name: felt,               # Token name as Cairo short string
        symbol: felt,             # Token symbol as Cairo short string
        decimals: felt            # Token decimals (usually 18)
        initial_supply: Uint256,  # Amount to be minted
        recipient: felt           # Address where to send initial supply to
    ):

To create a token you need to deploy it like this:

    erc20 = await starknet.deploy(
        "openzeppelin/token/erc20/presets/ERC20.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),     # name\
            str_to_felt("TKN"),       # symbol\
            18,                       # decimals\
            (1000, 0),                # initial supply\
            account.contract_address  # recipient\
        ]
    )

As most StarkNet contracts, it expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it. For example:

    signer = MockSigner(PRIVATE_KEY)
    amount = uint(100)
    
    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    await signer.send_transaction(account, erc20.contract_address, 'transfer', [recipient_address, *amount])

[](#extensibility)
Extensibility
--------------------------------

ERC20 contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
. The basic idea behind integrating the pattern is to import the requisite ERC20 methods from the ERC20 library and incorporate the extended logic thereafter. For example, let’s say you wanted to implement a pausing mechanism. The contract should first import the ERC20 methods and the extended logic from the [Pausable library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/pausable/library.cairo)
 i.e. `Pausable.pause`, `Pausable.unpause`. Next, the contract should expose the methods with the extended logic therein like this:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()          # imported extended logic
        ERC20.transfer(recipient, amount)     # imported library method
        return (TRUE)
    end

Note that extensibility does not have to be only library-based like in the above example. For instance, an ERC20 contract with a pausing mechanism can define the pausing methods directly in the contract or even import the `pausable` methods from the library and tailor them further.

Some other ways to extend ERC20 contracts may include:

*   Implementing a minting mechanism
    
*   Creating a timelock
    
*   Adding roles such as owner or minter
    

For full examples of the extensibility pattern being used in ERC20 contracts, see [Presets](#presets)
.

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset mints an initial supply which is especially necessary for presets that do not expose a `mint` method.

### [](#erc20_basic)
ERC20 (basic)

The [`ERC20`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 preset offers a quick and easy setup for deploying a basic ERC20 token.

### [](#erc20mintable)
ERC20Mintable

The [`ERC20Mintable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
 preset allows the contract owner to mint new tokens.

### [](#erc20pausable)
ERC20Pausable

The [`ERC20Pausable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
 preset allows the contract owner to pause/unpause all state-modifying methods i.e. `transfer`, `approve`, etc. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug.

### [](#erc20upgradeable)
ERC20Upgradeable

The [`ERC20Upgradeable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
 preset allows the contract owner to upgrade a contract by deploying a new ERC20 implementation contract while also maintaing the contract’s state. This preset proves useful for scenarios such as eliminating bugs and adding new features. For more on upgradeability, see [Contract upgrades](proxies#contract_upgrades)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#methods)
Methods

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func decimals() -> (decimals: felt):
    end
    
    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func balanceOf(account: felt) -> (balance: Uint256):
    end
    
    func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
    end
    
    func transfer(recipient: felt, amount: Uint256) -> (success: felt):
    end
    
    func transferFrom(
            sender: felt,
            recipient: felt,
            amount: Uint256
        ) -> (success: felt):
    end
    
    func approve(spender: felt, amount: Uint256) -> (success: felt):
    end

#### [](#name)
`name`

Returns the name of the token.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the ticker symbol of the token.

Parameters: None.

Returns:

    symbol: felt

#### [](#decimals)
`decimals`

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user representation.

Parameters: None.

Returns:

    decimals: felt

#### [](#totalsupply)
`totalSupply`

Returns the amount of tokens in existence.

Parameters: None.

Returns:

    totalSupply: Uint256

#### [](#balanceof)
`balanceOf`

Returns the amount of tokens owned by `account`.

Parameters:

    account: felt

Returns:

    balance: Uint256

#### [](#allowance)
`allowance`

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through `transferFrom`. This is zero by default.

This value changes when `approve` or `transferFrom` are called.

Parameters:

    owner: felt
    spender: felt

Returns:

    remaining: Uint256

#### [](#transfer)
`transfer`

Moves `amount` tokens from the caller’s account to `recipient`. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#transferfrom)
`transferFrom`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    sender: felt
    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#approve)
`approve`

Sets `amount` as the allowance of `spender` over the caller’s tokens. It returns `1` representing a bool if it succeeds.

Emits an [Approval](#approval_event)
 event.

Parameters:

    spender: felt
    amount: Uint256

Returns:

    success: felt

### [](#events)
Events

    func Transfer(from_: felt, to: felt, value: Uint256):
    end
    
    func Approval(owner: felt, spender: felt, value: Uint256):
    end

#### [](#transfer_event)
`Transfer (event)`

Emitted when `value` tokens are moved from one account (`from_`) to another (`to`).

Note that `value` may be zero.

Parameters:

    from_: felt
    to: felt
    value: Uint256

#### [](#approval_event)
`Approval (event)`

Emitted when the allowance of a `spender` for an `owner` is set by a call to [approve](#approve)
. `value` is the new allowance.

Parameters:

    owner: felt
    spender: felt
    value: Uint256

[← Access Control](/contracts-cairo/0.4.0b/access)

[ERC721 →](/contracts-cairo/0.4.0b/erc721)




 Introspection - OpenZeppelin Docs       

Introspection
=============

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [ERC165](#erc165)
    
    *   [Interface calculations](#interface_calculations)
        
    *   [Registering interfaces](#registering_interfaces)
        
    *   [Querying interfaces](#querying_interfaces)
        
    *   [IERC165](#ierc165)
        
    *   [IERC165 API Specification](#ierc165_api_specification)
        
        *   [`supportsInterface`](#supportsinterface)
            
        
    *   [ERC165 Library Functions](#erc165_library_functions)
        
        *   [`supports_interface`](#supportsinterface2)
            
        *   [`register_interface`](#register_interface)
            
        
    

[](#erc165)
ERC165
------------------

The ERC165 standard allows smart contracts to exercise [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
 on other contracts, that is, examining which functions can be called on them. This is usually referred to as a contract’s interface.

Cairo contracts, like Ethereum contracts, have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. ERC20 tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract declaring its interface can be very helpful in preventing errors.

It should be noted that the [constants library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 includes constant variables referencing all of the interface ids used in these contracts. This allows for more legible code i.e. using `IERC165_ID` instead of `0x01ffc9a7`.

### [](#interface_calculations)
Interface calculations

In order to ensure EVM/StarkNet compatibility, interface identifiers are not calculated on StarkNet. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, the contract should import the ERC165 library and register its support. It’s recommended to register interface support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    from openzeppelin.introspection.erc165.library import ERC165
    
    INTERFACE_ID = 0x12345678
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        ERC165.register_interface(INTERFACE_ID)
        return ()
    end

### [](#querying_interfaces)
Querying interfaces

To query a target contract’s support for an interface, the querying contract should call `supportsInterface` through IERC165 with the target contract’s address and the queried interface id. Here’s an example:

    from openzeppelin.introspection.erc265.IERC165 import IERC165
    
    INTERFACE_ID = 0x12345678
    
    func check_support{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            target_contract: felt,
        ) -> (success: felt):
        let (is_supported) = IERC165.supportsInterface(target_contract, INTERFACE_ID)
        return (is_supported)
    end

|     |     |
| --- | --- |
|     | `supportsInterface` is camelCased because it is an exposed contract method as part of ERC165’s interface. This differs from library methods (such as `supports_interface` from the [ERC165 library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/introspection/erc165/library.cairo)<br>) which are snake\_cased and not exposed. See the [Function names and coding style](extensibility#function_names_and_coding_style)<br> for more details. |

### [](#ierc165)
IERC165

    @contract_interface
    namespace IERC165:
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#ierc165_api_specification)
IERC165 API Specification

    func supportsInterface(interfaceId: felt) -> (success: felt):
    end

#### [](#supportsinterface)
`supportsInterface`

Returns true if this contract implements the interface defined by `interfaceId`.

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#erc165_library_functions)
ERC165 Library Functions

    func supports_interface(interface_id: felt) -> (success: felt):
    end
    
    func register_interface(interface_id: felt):
    end

#### [](#supportsinterface2)
`supports_interface`

Returns true if this contract implements the interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns:

    success: felt

#### [](#register_interface)
`register_interface`

Calling contract declares support for a specific interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns: None.

[← Security](/contracts-cairo/0.3.0/security)

[Utilities →](/contracts-cairo/0.3.0/utilities)




 Account - OpenZeppelin Docs       

Account
=======

Reference of interfaces, presets, and utilities related to account contracts.

[](#core)
Core
--------------

### [](#ISRC6)
`ISRC6`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/account/interface.cairo)

    use openzeppelin::account::interface::ISRC6;

Interface of the SRC6 Standard Account as defined in the [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
.

[SRC5 ID](introspection#ISRC5)

0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd

Functions

*   [`__execute__(calls)`](#ISRC6-__execute__)
    
*   [`__validate__(calls)`](#ISRC6-__validate__)
    
*   [`is_valid_signature(hash, signature)`](#ISRC6-is_valid_signature)
    

#### [](#ISRC6-Functions)
Functions

#### [](#ISRC6-__execute__)
`__execute__(calls: Array<Call>) → Array<Span<felt252>>` external

Executes the list of calls as a transaction after validation.

Returns an array with each call’s output.

|     |     |
| --- | --- |
|     | The `Call` struct is defined in [corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3)<br>. |

#### [](#ISRC6-__validate__)
`__validate__(calls: Array<Call>) → felt252` external

Validates a transaction before execution.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#ISRC6-is_valid_signature)
`is_valid_signature(hash: felt252, signature: Array<felt252>) → felt252` external

Validates whether a signature is valid or not for the given message hash.

Returns the short string `'VALID'` if valid, otherwise it reverts.

### [](#AccountComponent)
`AccountComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/account/account.cairo)

    use openzeppelin::account::AccountComponent;

Account component implementing [`ISRC6`](#ISRC6)
 for signatures over the [Starknet curve](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/stark-curve/)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

[Embeddable Mixin Implementations](../components#mixins)

AccountMixinImpl

*   [`SRC6Impl`](#AccountComponent-Embeddable-Impls-SRC6Impl)
    
*   [`DeclarerImpl`](#AccountComponent-Embeddable-Impls-DeclarerImpl)
    
*   [`DeployableImpl`](#AccountComponent-Embeddable-Impls-DeployableImpl)
    
*   [`PublicKeyImpl`](#AccountComponent-Embeddable-Impls-PublicKeyImpl)
    
*   [`SRC6CamelOnlyImpl`](#AccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl)
    
*   [`PublicKeyCamelImpl`](#AccountComponent-Embeddable-Impls-PublicKeyCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

SRC6Impl

*   [`__execute__(self, calls)`](#AccountComponent-__execute__)
    
*   [`__validate__(self, calls)`](#AccountComponent-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#AccountComponent-is_valid_signature)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#AccountComponent-__validate_declare__)
    

DeployableImpl

*   [`__validate_deploy__(self, hash, signature)`](#AccountComponent-__validate_deploy__)
    

PublicKeyImpl

*   [`get_public_key(self)`](#AccountComponent-get_public_key)
    
*   [`set_public_key(self, new_public_key, signature)`](#AccountComponent-set_public_key)
    

SRC6CamelOnlyImpl

*   [`isValidSignature(self, hash, signature)`](#AccountComponent-isValidSignature)
    

PublicKeyCamelImpl

*   [`getPublicKey(self)`](#AccountComponent-getPublicKey)
    
*   [`setPublicKey(self, newPublicKey, signature)`](#AccountComponent-setPublicKey)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self, public_key)`](#AccountComponent-initializer)
    
*   [`assert_only_self(self)`](#AccountComponent-assert_only_self)
    
*   [`assert_valid_new_owner(self, current_owner, new_owner, signature)`](#AccountComponent-assert_valid_new_owner)
    
*   [`validate_transaction(self)`](#AccountComponent-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#AccountComponent-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#AccountComponent-_is_valid_signature)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#AccountComponent-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#AccountComponent-OwnerRemoved)
    

#### [](#AccountComponent-Embeddable-Functions)
Embeddable functions

#### [](#AccountComponent-__execute__)
`__execute__(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#AccountComponent-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#AccountComponent-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: felt252) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-get_public_key)
`get_public_key(self: @ContractState) → felt252` external

Returns the current public key of the account.

#### [](#AccountComponent-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: felt252, signature: Span<felt252>)` external

Sets a new public key for the account. Only accessible by the account calling itself through `__execute__`.

Requirements:

*   The caller must be the contract itself.
    
*   The signature must be valid for the new owner.
    

Emits both an [OwnerRemoved](#AccountComponent-OwnerRemoved)
 and an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The message to be signed is computed in Cairo as follows:<br><br>    let message_hash = PoseidonTrait::new()<br>            .update_with('StarkNet Message')<br>            .update_with('accept_ownership')<br>            .update_with(get_contract_address())<br>            .update_with(current_owner)<br>            .finalize(); |

#### [](#AccountComponent-isValidSignature)
`isValidSignature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-getPublicKey)
`getPublicKey(self: @ContractState) → felt252` external

See [get\_public\_key](#AccountComponent-get_public_key)
.

#### [](#AccountComponent-setPublicKey)
`setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span<felt252>)` external

See [set\_public\_key](#AccountComponent-set_public_key)
.

#### [](#AccountComponent-Internal-Functions)
Internal functions

#### [](#AccountComponent-initializer)
`initializer(ref self: ComponentState, public_key: felt252)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

#### [](#AccountComponent-assert_only_self)
`assert_only_self(self: @ComponentState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#AccountComponent-assert_valid_new_owner)
`assert_valid_new_owner(self: @ComponentState, current_owner: felt252, new_owner: felt252, signature: Span<felt252>)` internal

Validates that `new_owner` accepted the ownership of the contract through a signature.

Requirements:

*   `signature` must be valid for the new owner.
    

|     |     |
| --- | --- |
|     | This function assumes that `current_owner` is the current owner of the contract, and does not validate this assumption. |

#### [](#AccountComponent-validate_transaction)
`validate_transaction(self: @ComponentState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-_set_public_key)
`_set_public_key(ref self: ComponentState, new_public_key: felt252)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#AccountComponent-_is_valid_signature)
`_is_valid_signature(self: @ComponentState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account’s current public key.

#### [](#AccountComponent-Events)
Events

#### [](#AccountComponent-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#AccountComponent-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

### [](#EthAccountComponent)
`EthAccountComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/account/eth_account.cairo)

    use openzeppelin::account::eth_account::EthAccountComponent;

Account component implementing [`ISRC6`](#ISRC6)
 for signatures over the [Secp256k1 curve](https://en.bitcoin.it/wiki/Secp256k1)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

|     |     |
| --- | --- |
|     | The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`. |

[Embeddable Mixin Implementations](../components#mixins)

EthAccountMixinImpl

*   [`SRC6Impl`](#EthAccountComponent-Embeddable-Impls-SRC6Impl)
    
*   [`DeclarerImpl`](#EthAccountComponent-Embeddable-Impls-DeclarerImpl)
    
*   [`DeployableImpl`](#EthAccountComponent-Embeddable-Impls-DeployableImpl)
    
*   [`PublicKeyImpl`](#EthAccountComponent-Embeddable-Impls-PublicKeyImpl)
    
*   [`SRC6CamelOnlyImpl`](#EthAccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl)
    
*   [`PublicKeyCamelImpl`](#EthAccountComponent-Embeddable-Impls-PublicKeyCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

SRC6Impl

*   [`__execute__(self, calls)`](#EthAccountComponent-__execute__)
    
*   [`__validate__(self, calls)`](#EthAccountComponent-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#EthAccountComponent-is_valid_signature)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#EthAccountComponent-__validate_declare__)
    

DeployableImpl

*   [`__validate_deploy__(self, hash, signature)`](#EthAccountComponent-__validate_deploy__)
    

PublicKeyImpl

*   [`get_public_key(self)`](#EthAccountComponent-get_public_key)
    
*   [`set_public_key(self, new_public_key, signature)`](#EthAccountComponent-set_public_key)
    

SRC6CamelOnlyImpl

*   [`isValidSignature(self, hash, signature)`](#EthAccountComponent-isValidSignature)
    

PublicKeyCamelImpl

*   [`getPublicKey(self)`](#EthAccountComponent-getPublicKey)
    
*   [`setPublicKey(self, newPublicKey, signature)`](#EthAccountComponent-setPublicKey)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self, public_key)`](#EthAccountComponent-initializer)
    
*   [`assert_only_self(self)`](#EthAccountComponent-assert_only_self)
    
*   [`assert_valid_new_owner(self, current_owner, new_owner, signature)`](#EthAccountComponent-assert_valid_new_owner)
    
*   [`validate_transaction(self)`](#EthAccountComponent-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#EthAccountComponent-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#EthAccountComponent-_is_valid_signature)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#EthAccountComponent-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#EthAccountComponent-OwnerRemoved)
    

#### [](#EthAccountComponent-Embeddable-Functions)
Embeddable functions

#### [](#EthAccountComponent-__execute__)
`__execute__(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#EthAccountComponent-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#EthAccountComponent-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#EthAccountComponent-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#EthAccountComponent-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: EthPublicKey) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#EthAccountComponent-get_public_key)
`get_public_key(self: @ContractState) → EthPublicKey` external

Returns the current public key of the account.

#### [](#EthAccountComponent-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: EthPublicKey, signature: Span<felt252>)` external

Sets a new public key for the account. Only accessible by the account calling itself through `__execute__`.

Requirements:

*   The caller must be the contract itself.
    
*   The signature must be valid for the new owner.
    

Emits both an [OwnerRemoved](#EthAccountComponent-OwnerRemoved)
 and an [OwnerAdded](#EthAccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The message to be signed is computed in Cairo as follows:<br><br>    let message_hash = PoseidonTrait::new()<br>            .update_with('StarkNet Message')<br>            .update_with('accept_ownership')<br>            .update_with(get_contract_address())<br>            .update_with(current_owner.get_coordinates().unwrap_syscall())<br>            .finalize(); |

#### [](#EthAccountComponent-isValidSignature)
`isValidSignature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#EthAccountComponent-getPublicKey)
`getPublicKey(self: @ContractState) → EthPublicKey` external

See [get\_public\_key](#EthAccountComponent-get_public_key)
.

#### [](#EthAccountComponent-setPublicKey)
`setPublicKey(ref self: ContractState, newPublicKey: EthPublicKey, signature: Span<felt252>)` external

See [set\_public\_key](#EthAccountComponent-set_public_key)
.

#### [](#EthAccountComponent-Internal-Functions)
Internal functions

#### [](#EthAccountComponent-initializer)
`initializer(ref self: ComponentState, public_key: EthPublicKey)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#EthAccountComponent-OwnerAdded)
 event.

#### [](#EthAccountComponent-assert_only_self)
`assert_only_self(self: @ComponentState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#EthAccountComponent-assert_valid_new_owner)
`assert_valid_new_owner(self: @ComponentState, current_owner: EthPublicKey, new_owner: EthPublicKey, signature: Span<felt252>)` internal

Validates that `new_owner` accepted the ownership of the contract through a signature.

Requirements:

*   The signature must be valid for the `new_owner`.
    

|     |     |
| --- | --- |
|     | This function assumes that `current_owner` is the current owner of the contract, and does not validate this assumption. |

#### [](#EthAccountComponent-validate_transaction)
`validate_transaction(self: @ComponentState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#EthAccountComponent-_set_public_key)
`_set_public_key(ref self: ComponentState, new_public_key: EthPublicKey)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#EthAccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#EthAccountComponent-_is_valid_signature)
`_is_valid_signature(self: @ComponentState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account’s current public key.

#### [](#EthAccountComponent-Events)
Events

|     |     |
| --- | --- |
|     | The `guid` is computed as the hash of the public key, using the poseidon hash function. |

#### [](#EthAccountComponent-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#EthAccountComponent-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

[](#presets)
Presets
--------------------

### [](#AccountUpgradeable)
`AccountUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/presets/account.cairo)

    use openzeppelin::presets::AccountUpgradeable;

Upgradeable account contract leveraging [AccountComponent](#AccountComponent)
.

[Sierra class hash](../presets)

0x005b8b908d16497cd347642c1ab43015b5956e2085aa4c8bb21f0b073015a1c9

Constructor

*   [`constructor(self, public_key)`](#AccountUpgradeable-constructor)
    

Embedded Implementations

AccountComponent

*   [`AccountMixinImpl`](#AccountComponent-Embeddable-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#AccountUpgradeable-upgrade)
    

#### [](#AccountUpgradeable-constructor-section)
Constructor

#### [](#AccountUpgradeable-constructor)
`constructor(ref self: ContractState, public_key: felt252)` constructor

Sets the account `public_key` and registers the interfaces the contract supports.

#### [](#AccountUpgradeable-external-functions)
External functions

#### [](#AccountUpgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the account contract itself.
    
*   `new_class_hash` cannot be zero.
    

### [](#EthAccountUpgradeable)
`EthAccountUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/presets/eth_account.cairo)

    use openzeppelin::presets::EthAccountUpgradeable;

Upgradeable account contract leveraging [EthAccountComponent](#EthAccountComponent)
.

|     |     |
| --- | --- |
|     | The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`. |

[Sierra class hash](../presets)

0x041534fff05642ddbb5778be304be14dd36da40a02feadb6e489f9f749f5c983

Constructor

*   [`constructor(self, public_key)`](#EthAccountUpgradeable-constructor)
    

Embedded Implementations

EthAccountComponent

*   [`EthAccountMixinImpl`](#EthAccountComponent-Embeddable-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#EthAccountUpgradeable-upgrade)
    

#### [](#EthAccountUpgradeable-constructor-section)
Constructor

#### [](#EthAccountUpgradeable-constructor)
`constructor(ref self: ContractState, public_key: EthPublicKey)` constructor

Sets the account `public_key` and registers the interfaces the contract supports.

#### [](#EthAccountUpgradeable-external-functions)
External functions

#### [](#EthAccountUpgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the account contract itself.
    
*   `new_class_hash` cannot be zero.
    

[← Accounts](/contracts-cairo/0.15.0/accounts)

[Governance →](/contracts-cairo/0.15.0/governance)




 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#OwnableComponent)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControlComponent)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#OwnableComponent)
`OwnableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::OwnableComponent;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

Embeddable Implementations

OwnableImpl

*   [`owner(self)`](#OwnableComponent-owner)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-renounce_ownership)
    

Embeddable Implementations (camelCase)

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#OwnableComponent-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-renounceOwnership)
    

Internal Implementations

InternalImpl

*   [`initializer(self, owner)`](#OwnableComponent-initializer)
    
*   [`assert_only_owner(self)`](#OwnableComponent-assert_only_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#OwnableComponent-_transfer_ownership)
    

Events

*   [`OwnershipTransferred(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferred)
    

#### [](#OwnableComponent-Embeddable-Functions)
Embeddable Functions

#### [](#OwnableComponent-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-camelCase-Support)
camelCase Support

#### [](#OwnableComponent-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#OwnableComponent-transfer_ownership)
.

#### [](#OwnableComponent-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#OwnableComponent-renounce_ownership)
.

#### [](#OwnableComponent-Internal-Functions)
Internal Functions

#### [](#OwnableComponent-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#OwnableComponent-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-Events)
Events

#### [](#OwnableComponent-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/access/accesscontrol/interface.cairo)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControlComponent)
`AccessControlComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControlComponent;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControlComponent-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

Embeddable Implementations

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControlComponent-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControlComponent-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControlComponent-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControlComponent-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControlComponent-renounce_role)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](#AccessControlComponent-supports_interface)
    

Embeddable Implementations (camelCase)

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControlComponent-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControlComponent-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControlComponent-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControlComponent-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControlComponent-renounceRole)
    

Internal Implementations

InternalImpl

*   [`initializer(self)`](#AccessControlComponent-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControlComponent-assert_only_role)
    
*   [`_set_role_admin(self, role, admin_role)`](#AccessControlComponent-_set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControlComponent-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControlComponent-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControlComponent-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControlComponent-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControlComponent-RoleRevoked)
    

#### [](#AccessControlComponent-Embeddable-Functions)
Embeddable Functions

#### [](#AccessControlComponent-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControlComponent-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#AccessControlComponent-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControlComponent-camelCase-Support)
camelCase Support

#### [](#AccessControlComponent-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControlComponent-has_role)
.

#### [](#AccessControlComponent-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControlComponent-get_role_admin)
.

#### [](#AccessControlComponent-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControlComponent-grant_role)
.

#### [](#AccessControlComponent-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControlComponent-revoke_role)
.

#### [](#AccessControlComponent-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControlComponent-renounce_role)
.

#### [](#AccessControlComponent-Internal-Functions)
Internal Functions

#### [](#AccessControlComponent-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControlComponent-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControlComponent-_set_role_admin)
`_set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControlComponent-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-Events)
Events

#### [](#AccessControlComponent-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControlComponent-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControlComponent-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access](/contracts-cairo/0.8.1/access)

[Accounts →](/contracts-cairo/0.8.1/accounts)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. The `ERC721.cairo` contract implements an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC721](#ierc721)
    
*   [ERC721 Compatibility](#erc721_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC721 URIs](#interpreting_erc721_uris)
        
    *   [ERC721Received](#erc721received)
        
        *   [IERC721Receiver](#ierc721receiver)
            
        
    *   [Supporting Interfaces](#supporting_interfaces)
        
    *   [Ready\_to\_Use Presets](#ready_to_use_presets)
        
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC721MintableBurnable](#erc721mintableburnable)
        
    *   [ERC721MintablePausable](#erc721mintablepausable)
        
    *   [ERC721EnumerableMintableBurnable](#erc721enumerablemintableburnable)
        
        *   [IERC721Enumerable](#ierc721enumerable)
            
        
    *   [ERC721Metadata](#erc721metadata)
        
        *   [IERC721Metadata](#ierc721metadata)
            
        
    
*   [Utilities](#utilities)
    
    *   [ERC721Holder](#erc721_holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC721`](#ierc721_api)
        
        *   [`balanceOf`](#balanceof)
            
        *   [`ownerOf`](#ownerof)
            
        *   [`safeTransferFrom`](#safetransferfrom)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        *   [`setApprovalForAll`](#setapprovalforall)
            
        *   [`getApproved`](#getapproved)
            
        *   [`isApprovedForAll`](#isapprovedforall)
            
        
    *   [Events](#events)
        
        *   [`Approval (event)`](#approval_event)
            
        *   [`ApprovalForAll (event)`](#approvalforall_event)
            
        *   [`Transfer (event)`](#transfer_event)
            
        
    *   [`IERC721Metadata`](#ierc721metadata)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`tokenURI`](#tokenuri)
            
        
    *   [`IERC721Enumerable`](#ierc721enumerable)
        
        *   [`totalSupply`](#totalsupply)
            
        *   [`tokenByIndex`](#tokenbyindex)
            
        *   [`tokenOfOwnerByIndex`](#tokenofownerbyindex)
            
        
    *   [`IERC721Receiver`](#ierc721receiver_api)
        
        *   [`onERC721Received`](#onerc721received)
            
        
    

[](#ierc721)
IERC721
--------------------

    @contract_interface
    namespace IERC721:
        func balanceOf(owner: felt) -> (balance: Uint256):
        end
    
        func ownerOf(tokenId: Uint256) -> (owner: felt):
        end
    
        func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    
        func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
        func approve(approved: felt, tokenId: Uint256):
        end
    
        func setApprovalForAll(operator: felt, approved: felt):
        end
    
        func getApproved(tokenId: Uint256) -> (approved: felt):
        end
    
        func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
        end
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#erc721_compatibility)
ERC721 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `tokenURI` returns a felt representation of the queried token’s URI. The EIP721 standard, however, states that the return value should be of type string. If a token’s URI is not set, the returned value is `0`. Note that URIs cannot exceed 31 characters. See [Interpreting ERC721 URIs](#interpreting_erc721_uris)
    
*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Solidity’s selector calculations. See [Supporting Interfaces](#supporting_interfaces)
    
*   `safeTransferFrom` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721. The difference between both functions consists of accepting `data` as an argument. Because function overloading is currently not possible in Cairo, `safeTransferFrom` by default accepts the `data` argument. If `data` is not used, simply insert `0`.
    
*   `safeTransferFrom` is specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, it accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`
    
*   `ERC165.register_interface` allows contracts to set and communicate which interfaces they support. This follows OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) must support ERC165 by registering the `IERC721Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC721 transfers
    
*   `ERC721Enumerable` tracks the total number of tokens with the `all_tokens` and `all_tokens_len` storage variables mimicking the array of the Solidity implementation.
    

[](#usage)
Usage
----------------

Use cases go from artwork, digital collectibles, physical property, and many more.

To show a standard use case, we’ll use the `ERC721Mintable` preset which allows for only the owner to `mint` and `burn` tokens. To create a token you need to first deploy both Account and ERC721 contracts respectively. As most StarkNet contracts, ERC721 expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it.

Considering that the ERC721 constructor method looks like this:

    func constructor(
        name: felt,          # Token name as Cairo short string
        symbol: felt,        # Token symbol as Cairo short string
        owner: felt          # Address designated as the contract owner
    ):

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc721 = await starknet.deploy(
        "contracts/token/erc721/presets/ERC721Mintable.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),                       # name\
            str_to_felt("TKN"),                         # symbol\
            account.contract_address                    # owner\
        ]
    )

To mint a non-fungible token, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    tokenId = uint(1)
    
    await signer.send_transaction(
        account, erc721.contract_address, 'mint', [\
            recipient_address,\
            *tokenId\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `transferFrom` and `safeTransferFrom` to transfer NFTs. If using `transferFrom`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.**

The `safeTransferFrom` method incorporates the following conditional logic:

1.  if the calling address is an account contract, the token transfer will behave as if `transferFrom` was called
    
2.  if the calling address is not an account contract, the safe function will check that the contract supports ERC721 tokens
    

The current implementation of `safeTansferFrom` checks for `onERC721Received` and requires that the recipient contract supports ERC165 and exposes the `supportsInterface` method. See [ERC721Received](#erc721received)
.

### [](#interpreting_erc721_uris)
Interpreting ERC721 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard set in [EIP721](https://eips.ethereum.org/EIPS/eip-721)<br>. Therefore, this library’s ERC721 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC721, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc721.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc721.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc721received)
ERC721Received

In order to be sure a contract can safely accept ERC721 tokens, said contract must implement the `ERC721_Receiver` interface (as expressed in the EIP721 specification). Methods such as `safeTransferFrom` and `safeMint` call the recipient contract’s `onERC721Received` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. `safeTransferFrom` requires a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC721 implementation requires that all contracts that support safe ERC721 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC721Receiver` magic value `0x150b7a02` (which invokes `onERC721Received`). If the recipient contract supports the `IAccount` magic value `0x50b70dcb`, `supportsInterface` should return `TRUE`. Otherwise, `safeTransferFrom` should fail.

#### [](#ierc721receiver)
IERC721Receiver

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

    @contract_interface
    namespace IERC721Receiver:
        func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
        end
    end

### [](#supporting_interfaces)
Supporting Interfaces

In order to ensure EVM/StarkNet compatibility, this ERC721 implementation does not calculate interface identifiers. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

Further, this implementation stores supported interfaces in a mapping (similar to OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
).

### [](#ready_to_use_presets)
Ready-to-Use Presets

ERC721 presets have been created to allow for quick deployments as-is. To be as explicit as possible, each preset includes the additional features they offer in the contract name. For example:

*   `ERC721MintableBurnable` includes `mint` and `burn`
    
*   `ERC721MintablePausable` includes `mint`, `pause`, and `unpause`
    
*   `ERC721EnumerableMintableBurnable` includes `mint`, `burn`, and [IERC721Enumerable](#ierc721enumerable)
     methods
    

Ready-to-use presets are a great option for testing and prototyping. See [Presets](#presets)
.

[](#extensibility)
Extensibility
--------------------------------

Following the [contracts extensibility pattern](extensibility)
, this implementation is set up to include all ERC721 related storage and business logic under a namespace. Developers should be mindful of manually exposing the required methods from the namespace to comply with the standard interface. This is already done in the [preset contracts](#presets)
; however, additional functionality can be added. For instance, you could:

*   Implement a pausing mechanism
    
*   Add roles such as _owner_ or _minter_
    
*   Modify the `transferFrom` function to mimic the [`_beforeTokenTransfer` and `_afterTokenTransfer` hooks](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L335)
    

Just be sure that the exposed `external` methods invoke their imported function logic a la `approve` invokes `ERC721.approve`. As an example, see below.

    from openzeppelin.token.erc721.library import ERC721
    
    @external
    func approve{
            pedersen_ptr: HashBuiltin*,
            syscall_ptr: felt*,
            range_check_ptr
        }(to: felt, tokenId: Uint256):
        ERC721.approve(to, tokenId)
        return()
    end

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset includes a contract owner, which is set in the `constructor`, to offer simple access control on sensitive methods such as `mint` and `burn`.

### [](#erc721mintableburnable)
ERC721MintableBurnable

The `ERC721MintableBurnable` preset offers a quick and easy setup for creating NFTs. The contract owner can create tokens with `mint`, whereas token owners can destroy their tokens with `burn`.

### [](#erc721mintablepausable)
ERC721MintablePausable

The `ERC721MintablePausable` preset creates a contract with pausable token transfers and minting capabilities. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug. In this preset, only the contract owner can `mint`, `pause`, and `unpause`.

### [](#erc721enumerablemintableburnable)
ERC721EnumerableMintableBurnable

The `ERC721EnumerableMintableBurnable` preset adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This allows contracts to publish its full list of NFTs and make them discoverable.

In regard to implementation, contracts should expose the following view methods:

*   `ERC721Enumerable.total_supply`
    
*   `ERC721Enumerable.token_by_index`
    
*   `ERC721Enumerable.token_of_owner_by_index`
    

In order for the tokens to be correctly indexed, the contract should also use the following methods (which supercede some of the base `ERC721` methods):

*   `ERC721Enumerable.transfer_from`
    
*   `ERC721Enumerable.safe_transfer_from`
    
*   `ERC721Enumerable._mint`
    
*   `ERC721Enumerable._burn`
    

#### [](#ierc721enumerable)
IERC721Enumerable

    @contract_interface
    namespace IERC721Enumerable:
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
        end
    
        func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
        end
    end

### [](#erc721metadata)
ERC721Metadata

The `ERC721Metadata` extension allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

We follow OpenZeppelin’s Solidity approach of integrating the Metadata methods `name`, `symbol`, and `tokenURI` into all ERC721 implementations. If preferred, a contract can be created that does not import the Metadata methods from the `ERC721` library. Note that the `IERC721Metadata` interface id should be removed from the constructor as well.

#### [](#ierc721metadata)
IERC721Metadata

    @contract_interface
    namespace IERC721Metadata:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
        end
    end

[](#utilities)
Utilities
------------------------

### [](#erc721holder)
ERC721Holder

Implementation of the `IERC721Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC721.safeTransferFrom`, `IERC721.approve` or `IERC721.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC721Received](#erc721received)

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc721_api)
IERC721 API

    func balanceOf(owner: felt) -> (balance: Uint256):
    end
    
    func ownerOf(tokenId: Uint256) -> (owner: felt):
    end
    
    func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    end
    
    func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
    func approve(approved: felt, tokenId: Uint256):
    end
    
    func setApprovalForAll(operator: felt, approved: felt):
    end
    
    func getApproved(tokenId: Uint256) -> (approved: felt):
    end
    
    func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
    end

#### [](#balanceof)
`balanceOf`

Returns the number of tokens in `owner`'s account.

Parameters:

    owner: felt

Returns:

    balance: Uint256

#### [](#ownerof)
`ownerOf`

Returns the owner of the `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    owner: felt

#### [](#safetransferfrom)
`safeTransferFrom`

Safely transfers `tokenId` token from `from_` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [ERC721Received](#erc721received)
.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#transferfrom)
`transferFrom`

Transfers `tokenId` token from `from_` to `to`. **The caller is responsible to confirm that `to` is capable of receiving NFTs or else they may be permanently lost**.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

Returns: None.

#### [](#approve)
`approve`

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Emits an [Approval](#approval_event)
 event.

Parameters:

    to: felt
    tokenId: Uint256

Returns: None.

#### [](#getapproved)
`getApproved`

Returns the account approved for `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    operator: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.

Emits an [ApprovalForAll](#approvalforall_event)
 event.

Parameters:

    operator: felt

Returns: None.

#### [](#isapprovedforall)
`isApprovedForAll`

Returns if the `operator` is allowed to manage all of the assets of `owner`.

Parameters:

    owner: felt
    operator: felt

Returns:

    isApproved: felt

### [](#events)
Events

#### [](#approval_event)
`Approval (Event)`

Emitted when `owner` enables `approved` to manage the `tokenId` token.

Parameters:

    owner: felt
    approved: felt
    tokenId: Uint256

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    owner: felt
    operator: felt
    approved: felt

#### [](#transfer_event)
`Transfer (Event)`

Emitted when `tokenId` token is transferred from `from_` to `to`.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

* * *

### [](#ierc721metadata_api)
IERC721Metadata API

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
    end

#### [](#name)
`name`

Returns the token collection name.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the token collection symbol.

Parameters: None.

Returns:

    symbol: felt

#### [](#tokenuri)
`tokenURI`

Returns the Uniform Resource Identifier (URI) for `tokenID` token. If the URI is not set for the `tokenId`, the return value will be `0`.

Parameters:

    tokenId: Uint256

Returns:

    tokenURI: felt

* * *

### [](#ierc721enumerable_api)
IERC721Enumerable API

    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
    end
    
    func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
    end

#### [](#totalsupply)
`totalSupply`

Returns the total amount of tokens stored by the contract.

Parameters: None

Returns:

    totalSupply: Uint256

#### [](#tokenbyindex)
`tokenByIndex`

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [balanceOf](#balanceof)
 to enumerate all of `owner`'s tokens.

Parameters:

    index: Uint256

Returns:

    tokenId: Uint256

#### [](#tokenofownerbyindex)
`tokenOfOwnerByIndex`

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [totalSupply](#totalsupply)
 to enumerate all tokens.

Parameters:

    owner: felt
    index: Uint256

Returns:

    tokenId: Uint256

* * *

### [](#ierc721receiver_api)
IERC721Receiver API

    func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
    end

#### [](#onerc721received)
`onERC721Received`

Whenever an IERC721 `tokenId` token is transferred to this non-account contract via `safeTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC20](/contracts-cairo/0.3.0/erc20)

[Security →](/contracts-cairo/0.3.0/security)




 Account - OpenZeppelin Docs       

Account
=======

Reference of interfaces, presets, and utilities related to account contracts.

[](#core)
Core
--------------

### [](#ISRC6)
`ISRC6`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/account/interface.cairo)

    use openzeppelin::account::interface::ISRC6;

Interface of the SRC6 Standard Account as defined in the [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
.

[SRC5 ID](introspection#ISRC5)

0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd

Functions

*   [`__execute__(calls)`](#ISRC6-__execute__)
    
*   [`__validate__(calls)`](#ISRC6-__validate__)
    
*   [`is_valid_signature(hash, signature)`](#ISRC6-is_valid_signature)
    

#### [](#ISRC6-Functions)
Functions

#### [](#ISRC6-__execute__)
`__execute__(calls: Array<Call>) → Array<Span<felt252>>` external

Executes the list of calls as a transaction after validation.

Returns an array with each call’s output.

|     |     |
| --- | --- |
|     | The `Call` struct is defined in [corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3)<br>. |

#### [](#ISRC6-__validate__)
`__validate__(calls: Array<Call>) → felt252` external

Validates a transaction before execution.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#ISRC6-is_valid_signature)
`is_valid_signature(hash: felt252, signature: Array<felt252>) → felt252` external

Validates whether a signature is valid or not for the given message hash.

Returns the short string `'VALID'` if valid, otherwise it reverts.

### [](#AccountComponent)
`AccountComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/account/account.cairo#L27)

    use openzeppelin::account::AccountComponent;

Account component implementing [`ISRC6`](#ISRC6)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

Embeddable Implementations

SRC6Impl

*   [`__execute__(self, calls)`](#AccountComponent-__execute__)
    
*   [`__validate__(self, calls)`](#AccountComponent-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#AccountComponent-is_valid_signature)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#AccountComponent-__validate_declare__)
    

DeployableImpl

*   [`__validate_deploy__(self, hash, signature)`](#AccountComponent-__validate_deploy__)
    

PublicKeyImpl

*   [`get_public_key(self)`](#AccountComponent-get_public_key)
    
*   [`set_public_key(self, new_public_key)`](#AccountComponent-set_public_key)
    

Embeddable Implementations (camelCase)

SRC6CamelOnlyImpl

*   [`isValidSignature(self, hash, signature)`](#AccountComponent-isValidSignature)
    

PublicKeyCamelImpl

*   [`getPublicKey(self)`](#AccountComponent-getPublicKey)
    
*   [`setPublicKey(self, newPublicKey)`](#AccountComponent-setPublicKey)
    

Internal Implementations

InternalImpl

*   [`initializer(self, public_key)`](#AccountComponent-initializer)
    
*   [`assert_only_self(self)`](#AccountComponent-assert_only_self)
    
*   [`validate_transaction(self)`](#AccountComponent-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#AccountComponent-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#AccountComponent-_is_valid_signature)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#AccountComponent-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#AccountComponent-OwnerRemoved)
    

#### [](#AccountComponent-Embeddable-Functions)
Embeddable Functions

#### [](#AccountComponent-__execute__)
`__execute__(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#AccountComponent-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#AccountComponent-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: felt252) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-get_public_key)
`get_public_key(self: @ContractState) → felt252` external

Returns the current public key of the account.

#### [](#AccountComponent-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: felt252)` external

Sets a new public key for the account. Only accessible by the account calling itself through `__execute__`.

Emits both an [OwnerRemoved](#AccountComponent-OwnerRemoved)
 and an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

#### [](#AccountComponent-camelCase-Support)
camelCase Support

#### [](#AccountComponent-isValidSignature)
`isValidSignature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-getPublicKey)
`getPublicKey(self: @ContractState) → felt252` external

See [get\_public\_key](#AccountComponent-get_public_key)
.

#### [](#AccountComponent-setPublicKey)
`setPublicKey(ref self: ContractState, newPublicKey: felt252)` external

See [set\_public\_key](#AccountComponent-set_public_key)
.

#### [](#AccountComponent-Internal-Functions)
Internal Functions

#### [](#AccountComponent-initializer)
`initializer(ref self: ComponentState, public_key: felt252)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

#### [](#AccountComponent-assert_only_self)
`assert_only_self(self: @ComponentState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#AccountComponent-validate_transaction)
`validate_transaction(self: @ComponentState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-_set_public_key)
`_set_public_key(ref self: ComponentState, new_public_key: felt252)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#AccountComponent-_is_valid_signature)
`_is_valid_signature(self: @ComponentState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account’s current public key.

#### [](#AccountComponent-Events)
Events

#### [](#AccountComponent-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#AccountComponent-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

[](#presets)
Presets
--------------------

### [](#Account)
`Account`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/presets/account.cairo)

    use openzeppelin::presets::Account;

Basic account contract leveraging [AccountComponent](#AccountComponent)
.

[Sierra class hash](../presets)

0x061dac032f228abef9c6626f995015233097ae253a7f72d68552db02f2971b8f

Constructor

*   [`constructor(self, public_key)`](#Account-constructor)
    

Embedded Implementations

AccountComponent

*   [`SRC6Impl`](#AccountComponent-Embeddable-Impls)
    
*   [`PublicKeyImpl`](#AccountComponent-Embeddable-Impls)
    
*   [`DeclarerImpl`](#AccountComponent-Embeddable-Impls)
    
*   [`DeployableImpl`](#AccountComponent-Embeddable-Impls)
    
*   [`SRC6CamelOnlyImpl`](#AccountComponent-Embeddable-Impls-camelCase)
    
*   [`PublicKeyCamelImpl`](#AccountComponent-Embeddable-Impls-camelCase)
    

SRC5Component

*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

#### [](#Account-constructor-section)
Constructor

#### [](#Account-constructor)
`constructor(ref self: ContractState, public_key: felt252)` constructor

Sets the account `public_key` and registers the interfaces the contract supports.

[← Accounts](/contracts-cairo/0.8.1/accounts)

[Introspection →](/contracts-cairo/0.8.1/introspection)




 GSN Strategies - OpenZeppelin Docs       

GSN Strategies
==============

This guide shows you different strategies to accept relayed calls via the Gas Station Network (GSN) using OpenZeppelin Contracts.

First, we will go over what a 'GSN strategy' is, and then showcase how to use the two most common strategies. Finally, we will cover how to create your own custom strategies.

If you’re still learning about the basics of the Gas Station Network, you should first head over to the [GSN Guide](gsn)
.

[](#gsn-strategies)
GSN Strategies Explained
--------------------------------------------

A **GSN strategy** decides which relayed call gets approved and which relayed call gets rejected. Strategies are a key concept within the GSN. Dapps need a strategy to prevent malicious users from spending the dapp’s funds for relayed call fees.

As we have seen in the [GSN Guide](gsn)
, in order to be GSN enabled, your contracts need to extend from [`GSNRecipient`](api/GSN#GSNRecipient)
.

A GSN recipient contract needs the following to work:

1.  It needs to have funds deposited on its RelayHub.
    
2.  It needs to handle `msg.sender` and `msg.data` differently.
    
3.  It needs to decide how to approve and reject relayed calls.
    

Depositing funds for the GSN recipient contract can be done via the [GSN Dapp tool](https://gsn.openzeppelin.com/recipients)
 or programmatically with [**OpenZeppelin GSN Helpers**](../../gsn-helpers/0.2/api#javascript_interface)
.

The actual user’s `msg.sender` and `msg.data` can be obtained safely via [`_msgSender()`](api/GSN#GSNRecipient-_msgSender--)
 and [`_msgData()`](api/GSN#GSNRecipient-_msgData--)
 of [`GSNRecipient`](api/GSN#GSNRecipient)
.

Deciding how to approve and reject relayed calls is a bit more complex. Chances are you probably want to choose which users can use your contracts via the GSN and potentially charge them for it, like a bouncer at a nightclub. We call these _GSN strategies_.

The base [`GSNRecipient`](api/GSN#GSNRecipient)
 contract doesn’t include a strategy, so you must either use one of the pre-built ones or write your own. We will first go over using the included strategies: [`GSNRecipientSignature`](api/GSN#GSNRecipientSignature)
 and [`GSNRecipientERC20Fee`](api/GSN#GSNRecipientERC20Fee)
.

[](#gsnrecipientsignature)
`GSNRecipientSignature`
--------------------------------------------------

[`GSNRecipientSignature`](api/GSN#GSNRecipientSignature)
 lets users relay calls via the GSN to your recipient contract (charging you for it) if they can prove that an account you trust approved them to do so. The way they do this is via a _signature_.

The relayed call must include a signature of the relayed call parameters by the same account that was added to the contract as a trusted signer. If it is not the same, `GSNRecipientSignature` will not accept the relayed call.

This means that you need to set up a system where your trusted account signs the relayed call parameters to then include in the relayed call, as long as they are valid users (according to your business logic).

The definition of a valid user depends on your system, but an example is users that have completed their sign up via some kind of [OAuth](https://en.wikipedia.org/wiki/OAuth)
 and validation, e.g. gone through a captcha or validated their email address. You could restrict it further and let new users send a specific number of relayed calls (e.g. limit to 5 relayed calls via the GSN, at which point the user needs to create a wallet). Alternatively, you could charge the user off-chain (e.g. via credit card) for credit on your system and let them create relayed calls until their credit runs out.

The great thing about this setup is that **your contract doesn’t need to change** if you want to change the business rules. All you are doing is changing the backend logic conditions under which users use your contract for free. On the other hand, you need to have a backend server, microservice, or lambda function to accomplish this.

### [](#how_does_gsnrecipientsignature_work)
How Does `GSNRecipientSignature` Work?

`GSNRecipientSignature` decides whether or not to accept the relayed call based on the included signature.

The `acceptRelayedCall` implementation recovers the address from the signature of the relayed call parameters in `approvalData` and compares it to the trusted signer. If the included signature matches the trusted signer, the relayed call is approved. On the other hand, when the included signature doesn’t match the trusted signer, the relayed call gets rejected with an error code of `INVALID_SIGNER`.

### [](#how_to_use_gsnrecipientsignature)
How to Use `GSNRecipientSignature`

You will need to create an off-chain service (e.g. backend server, microservice, or lambda function) that your dapp calls to sign (or not sign, based on your business logic) the relayed call parameters with your trusted signer account. The signature is then included as the `approvalData` in the relayed call.

Instead of using `GSNRecipient` directly, your GSN recipient contract will instead inherit from `GSNRecipientSignature`, as well as setting the trusted signer in the constructor of `GSNRecipientSignature` as per the following sample code below:

    import "@openzeppelin/contracts/GSN/GSNRecipientSignature.sol";
    
    contract MyContract is GSNRecipientSignature {
        constructor(address trustedSigner) public GSNRecipientSignature(trustedSigner) {
        }
    }

|     |     |
| --- | --- |
|     | We wrote an in-depth guide on how to setup a signing server that works with `GSNRecipientSignature`, [check it out!](https://forum.openzeppelin.com/t/advanced-gsn-gsnrecipientsignature-sol/1414) |

[](#gsnrecipienterc20fee)
`GSNRecipientERC20Fee`
------------------------------------------------

[`GSNRecipientERC20Fee`](api/GSN#GSNRecipientERC20Fee)
 is a bit more complex (but don’t worry, it has already been written for you!). Unlike `GSNRecipientSignature`, `GSNRecipientERC20Fee` doesn’t require any off-chain services. Instead of off-chain approving each relayed call, you will give special-purpose ERC20 tokens to your users. These tokens are then used as payment for relayed calls to your recipient contract. Any user that has enough tokens to pay has their relayed calls automatically approved and the recipient contract will cover their transaction costs!

Each recipient contract has their own special-purpose token. The exchange rate from token to ether is 1:1, as the tokens are used to pay your contract to cover the gas fees when using the GSN.

`GSNRecipientERC20Fee` has an internal [`_mint`](api/GSN#GSNRecipientERC20Fee-_mint-address-uint256-)
 function. Firstly, you need to setup a way to call it (e.g. add a public function with some form of [access control](access-control)
 such as [`onlyMinter`](api/access#MinterRole-onlyMinter--)
). Then, issue tokens to users based on your business logic. For example, you could mint a limited amount of tokens to new users, mint tokens when users buy them off-chain, give tokens based on a users subscription, etc.

|     |     |
| --- | --- |
|     | **Users do not need to call approve** on their tokens for your recipient contract to use them. They are a modified ERC20 variant that lets the recipient contract retrieve them. |

### [](#how_does_gsnrecipienterc20fee_work)
How Does `GSNRecipientERC20Fee` Work?

`GSNRecipientERC20Fee` decides to approve or reject relayed calls based on the balance of the users tokens.

The `acceptRelayedCall` function implementation checks the users token balance. If the user doesn’t have enough tokens the relayed call gets rejected with an error of `INSUFFICIENT_BALANCE`. If there are enough tokens, the relayed call is approved with the end users address, `maxPossibleCharge`, `transactionFee` and `gasPrice` data being returned so it can be used in `_preRelayedCall` and `_postRelayedCall`.

In `_preRelayedCall` function the `maxPossibleCharge` amount of tokens is transferred to the recipient contract. The maximum amount of tokens required is transferred assuming that the relayed call will use all the gas available. Then, in the `_postRelayedCall` function, the actual amount is calculated, including the recipient contract implementation and ERC20 token transfers, and the difference is refunded.

The maximum amount of tokens required is transferred in `_preRelayedCall` to protect the contract from exploits (this is really similar to how ether is locked in Ethereum transactions).

|     |     |
| --- | --- |
|     | The gas cost estimation is not 100% accurate, we may tweak it further down the road. |

|     |     |
| --- | --- |
|     | Always use `_preRelayedCall` and `_postRelayedCall` functions. Internal `_preRelayedCall` and `_postRelayedCall` functions are used instead of public `preRelayedCall` and `postRelayedCall` functions, as the public functions are prevented from being called by non-RelayHub contracts. |

### [](#how_to_use_gsnrecipienterc20fee)
How to Use `GSNRecipientERC20Fee`

Your GSN recipient contract needs to inherit from `GSNRecipientERC20Fee` along with appropriate [access control](access-control)
 (for token minting), set the token details in the constructor of `GSNRecipientERC20Fee` and create a public `mint` function suitably protected by your chosen access control as per the following sample code (which uses [`AccessControl`](api/access#AccessControl)
):

    // contracts/MyContract.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import "@openzeppelin/contracts/GSN/GSNRecipientERC20Fee.sol";
    import "@openzeppelin/contracts/access/AccessControl.sol";
    
    contract MyContract is GSNRecipientERC20Fee, AccessControl {
        bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    
        constructor() public GSNRecipientERC20Fee("FeeToken", "FEE") {
            _setupRole(MINTER_ROLE, _msgSender());
        }
    
        function _msgSender() internal view override(Context, GSNRecipient) returns (address payable) {
            return GSNRecipient._msgSender();
        }
    
        function _msgData() internal view override(Context, GSNRecipient) returns (bytes memory) {
            return GSNRecipient._msgData();
        }
    
        function mint(address account, uint256 amount) public {
            require(hasRole(MINTER_ROLE, _msgSender()), "Caller is not a minter");
            _mint(account, amount);
        }
    }

[](#custom_strategies)
Custom Strategies
----------------------------------------

If the included strategies don’t quite fit your business needs, you can also write your own! For example, your custom strategy could use a specified token to pay for relayed calls with a custom exchange rate to ether. Alternatively you could issue users who subscribe to your dapp ERC721 tokens, and accounts holding the subscription token could use your contract for free as part of the subscription. There are lots of potential options!

To write a custom strategy, simply inherit from `GSNRecipient` and implement the `acceptRelayedCall`, `_preRelayedCall` and `_postRelayedCall` functions.

Your `acceptRelayedCall` implementation decides whether or not to accept the relayed call: return `_approveRelayedCall` to accept, and return `_rejectRelayedCall` with an error code to reject.

Not all GSN strategies use `_preRelayedCall` and `_postRelayedCall` (though they must still be implemented, e.g. `GSNRecipientSignature` leaves them empty), but are useful when your strategy involves charging end users.

`_preRelayedCall` should take the maximum possible charge, with `_postRelayedCall` refunding any difference from the actual charge once the relayed call has been made. When returning `_approveRelayedCall` to approve the relayed call, the end users address, `maxPossibleCharge`, `transactionFee` and `gasPrice` data can also be returned so that the data can be used in `_preRelayedCall` and `_postRelayedCall`. See [the code for `GSNRecipientERC20Fee`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/GSN/GSNRecipientERC20Fee.sol)
 as an example implementation.

Once your strategy is ready, all your GSN recipient needs to do is inherit from it:

    contract MyContract is MyCustomGSNStrategy {
        constructor() public MyCustomGSNStrategy() {
        }
    }

[← Gas Station Network](/contracts/3.x/gsn)

[Utilities →](/contracts/3.x/utilities)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `ERC20.cairo` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Interface](#interface)
    
    *   [ERC20 compatibility](#erc20_compatibility)
        
    
*   [Usage](#usage)
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC20 (basic)](#erc20_basic)
        
    *   [ERC20Mintable](#erc20mintable)
        
    *   [ERC20Pausable](#erc20pausable)
        
    *   [ERC20Upgradeable](#erc20upgradeable)
        
    
*   [API Specification](#api_specification)
    
    *   [Methods](#methods)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`decimals`](#decimals)
            
        *   [`totalSupply`](#totalsupply)
            
        *   [`balanceOf`](#balanceof)
            
        *   [`allowance`](#allowance)
            
        *   [`transfer`](#transfer)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        
    *   [Events](#events)
        
        *   [`Transfer (event)`](#transfer_event)
            
        *   [`Approval (event)`](#approval_event)
            
        
    

[](#interface)
Interface
------------------------

    @contract_interface
    namespace IERC20:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func decimals() -> (decimals: felt):
        end
    
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func balanceOf(account: felt) -> (balance: Uint256):
        end
    
        func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
        end
    
        func transfer(recipient: felt, amount: Uint256) -> (success: felt):
        end
    
        func transferFrom(
                sender: felt,
                recipient: felt,
                amount: Uint256
            ) -> (success: felt):
        end
    
        func approve(spender: felt, amount: Uint256) -> (success: felt):
        end
    end

### [](#erc20_compatibility)
ERC20 compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard, in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it accepts a `felt` argument for `decimals` in the constructor calldata with a max value of 2^8 (imitating `uint8` type)
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `transfer`, `transferFrom` and `approve` will never return anything different from `TRUE` because they will revert on any error
    
*   function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo-lang/blob/7712b21fc3b1cb02321a58d0c0579f5370147a8b/src/starkware/starknet/public/abi.py#L25)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    

[](#usage)
Usage
----------------

Use cases go from medium of exchange currency to voting rights, staking, and more.

Considering that the constructor method looks like this:

    func constructor(
        name: felt,               # Token name as Cairo short string
        symbol: felt,             # Token symbol as Cairo short string
        decimals: felt            # Token decimals (usually 18)
        initial_supply: Uint256,  # Amount to be minted
        recipient: felt           # Address where to send initial supply to
    ):

To create a token you need to deploy it like this:

    erc20 = await starknet.deploy(
        "openzeppelin/token/erc20/presets/ERC20.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),     # name\
            str_to_felt("TKN"),       # symbol\
            18,                       # decimals\
            (1000, 0),                # initial supply\
            account.contract_address  # recipient\
        ]
    )

As most StarkNet contracts, it expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it. For example:

    signer = MockSigner(PRIVATE_KEY)
    amount = uint(100)
    
    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    await signer.send_transaction(account, erc20.contract_address, 'transfer', [recipient_address, *amount])

[](#extensibility)
Extensibility
--------------------------------

ERC20 contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
. The basic idea behind integrating the pattern is to import the requisite ERC20 methods from the ERC20 library and incorporate the extended logic thereafter. For example, let’s say you wanted to implement a pausing mechanism. The contract should first import the ERC20 methods and the extended logic from the [Pausable library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/pausable/library.cairo)
 i.e. `Pausable.pause`, `Pausable.unpause`. Next, the contract should expose the methods with the extended logic therein like this:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()          # imported extended logic
        ERC20.transfer(recipient, amount)     # imported library method
        return (TRUE)
    end

Note that extensibility does not have to be only library-based like in the above example. For instance, an ERC20 contract with a pausing mechanism can define the pausing methods directly in the contract or even import the `pausable` methods from the library and tailor them further.

Some other ways to extend ERC20 contracts may include:

*   Implementing a minting mechanism
    
*   Creating a timelock
    
*   Adding roles such as owner or minter
    

For full examples of the extensibility pattern being used in ERC20 contracts, see [Presets](#presets)
.

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset mints an initial supply which is especially necessary for presets that do not expose a `mint` method.

### [](#erc20_basic)
ERC20 (basic)

The [`ERC20`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 preset offers a quick and easy setup for deploying a basic ERC20 token.

### [](#erc20mintable)
ERC20Mintable

The [`ERC20Mintable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
 preset allows the contract owner to mint new tokens.

### [](#erc20pausable)
ERC20Pausable

The [`ERC20Pausable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
 preset allows the contract owner to pause/unpause all state-modifying methods i.e. `transfer`, `approve`, etc. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug.

### [](#erc20upgradeable)
ERC20Upgradeable

The [`ERC20Upgradeable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
 preset allows the contract owner to upgrade a contract by deploying a new ERC20 implementation contract while also maintaing the contract’s state. This preset proves useful for scenarios such as eliminating bugs and adding new features. For more on upgradeability, see [Contract upgrades](proxies#contract_upgrades)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#methods)
Methods

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func decimals() -> (decimals: felt):
    end
    
    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func balanceOf(account: felt) -> (balance: Uint256):
    end
    
    func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
    end
    
    func transfer(recipient: felt, amount: Uint256) -> (success: felt):
    end
    
    func transferFrom(
            sender: felt,
            recipient: felt,
            amount: Uint256
        ) -> (success: felt):
    end
    
    func approve(spender: felt, amount: Uint256) -> (success: felt):
    end

#### [](#name)
`name`

Returns the name of the token.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the ticker symbol of the token.

Parameters: None.

Returns:

    symbol: felt

#### [](#decimals)
`decimals`

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user representation.

Parameters: None.

Returns:

    decimals: felt

#### [](#totalsupply)
`totalSupply`

Returns the amount of tokens in existence.

Parameters: None.

Returns:

    totalSupply: Uint256

#### [](#balanceof)
`balanceOf`

Returns the amount of tokens owned by `account`.

Parameters:

    account: felt

Returns:

    balance: Uint256

#### [](#allowance)
`allowance`

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through `transferFrom`. This is zero by default.

This value changes when `approve` or `transferFrom` are called.

Parameters:

    owner: felt
    spender: felt

Returns:

    remaining: Uint256

#### [](#transfer)
`transfer`

Moves `amount` tokens from the caller’s account to `recipient`. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#transferfrom)
`transferFrom`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    sender: felt
    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#approve)
`approve`

Sets `amount` as the allowance of `spender` over the caller’s tokens. It returns `1` representing a bool if it succeeds.

Emits an [Approval](#approval_event)
 event.

Parameters:

    spender: felt
    amount: Uint256

Returns:

    success: felt

### [](#events)
Events

    func Transfer(from_: felt, to: felt, value: Uint256):
    end
    
    func Approval(owner: felt, spender: felt, value: Uint256):
    end

#### [](#transfer_event)
`Transfer (event)`

Emitted when `value` tokens are moved from one account (`from_`) to another (`to`).

Note that `value` may be zero.

Parameters:

    from_: felt
    to: felt
    value: Uint256

#### [](#approval_event)
`Approval (event)`

Emitted when the allowance of a `spender` for an `owner` is set by a call to [approve](#approve)
. `value` is the new allowance.

Parameters:

    owner: felt
    spender: felt
    value: Uint256

[← Access Control](/contracts-cairo/0.3.1/access)

[ERC721 →](/contracts-cairo/0.3.1/erc721)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are directly derived from a private key, there’s no native account concept on StarkNet.

Instead, signature validation has to be done at the contract level. To relieve smart contract applications such as ERC20 tokens or exchanges from this responsibility, we make use of Account contracts to deal with transaction authentication.

A more detailed writeup on the topic can be found on [Perama’s blogpost](https://perama-v.github.io/cairo/account-abstraction/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Standard Interface](#standard_interface)
    
*   [Keys, signatures and signers](#keys_signatures_and_signers)
    
    *   [Signer](#signer)
        
    *   [MockSigner utility](#mocksigner_utility)
        
    *   [MockEthSigner utility](#mockethsigner_utility)
        
    
*   [Account entrypoint](#account_entrypoint)
    
*   [Call and AccountCallArray format](#call_and_accountcallarray_format)
    
    *   [Call](#call)
        
    *   [AccountCallArray](#accountcallarray)
        
    
*   [Multicall transactions](#multicall_transactions)
    
*   [API Specification](#api_specification)
    
    *   [`get_public_key`](#get_public_key)
        
    *   [`get_nonce`](#get_nonce)
        
    *   [`set_public_key`](#set_public_key)
        
    *   [`is_valid_signature`](#is_valid_signature)
        
    *   [`__execute__`](#execute)
        
    *   [`is_valid_eth_signature`](#is_valid_eth_signature)
        
    *   [`eth_execute`](#eth_execute)
        
    *   [`_unsafe_execute`](#unsafe_execute)
        
    
*   [Presets](#presets)
    
    *   [Account](#account)
        
    *   [Eth Account](#eth_account)
        
    
*   [Account differentiation with ERC165](#account_differentiation_with_erc165)
    
*   [Extending the Account contract](#extending_the_account_contract)
    
*   [L1 escape hatch mechanism](#l1_escape_hatch_mechanism)
    
*   [Paying for gas](#paying_for_gas)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Account contract is deployed to StarkNet
    
2.  Signed transactions can now be sent to the Account contract which validates and executes them
    

In Python, this would look as follows:

    from starkware.starknet.testing.starknet import Starknet
    from utils import get_contract_class
    from signers import MockSigner
    
    signer = MockSigner(123456789987654321)
    
    starknet = await Starknet.empty()
    
    # 1. Deploy Account
    account = await starknet.deploy(
        get_contract_class("Account"),
        constructor_calldata=[signer.public_key]
    )
    
    # 2. Send transaction through Account
    await signer.send_transaction(account, some_contract_address, 'some_function', [some_parameter])

[](#standard_interface)
Standard Interface
------------------------------------------

The [`IAccount.cairo`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/IAccount.cairo)
 contract interface contains the standard account interface proposed in [#41](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and adopted by OpenZeppelin and Argent. It implements [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and it is agnostic of signature validation and nonce management strategies.

    @contract_interface
    namespace IAccount:
        #
        # Getters
        #
    
        func get_nonce() -> (res : felt):
        end
    
        #
        # Business logic
        #
    
        func is_valid_signature(
                hash: felt,
                signature_len: felt,
                signature: felt*
            ) -> (is_valid: felt):
        end
    
        func __execute__(
                call_array_len: felt,
                call_array: AccountCallArray*,
                calldata_len: felt,
                calldata: felt*,
                nonce: felt
            ) -> (response_len: felt, response: felt*):
        end
    end

[](#keys_signatures_and_signers)
Keys, signatures and signers
-------------------------------------------------------------

While the interface is agnostic of signature validation schemes, this implementation assumes there’s a public-private key pair controlling the Account. That’s why the `constructor` function expects a `public_key` parameter to set it. Since there’s also a `set_public_key()` method, accounts can be effectively transferred.

### [](#signer)
Signer

The signer is responsible for creating a transaction signature with the user’s private key for a given transaction. This implementation utilizes [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 class to create transaction signatures through the `Signer` method `sign_transaction`.

`sign_transaction` expects the following parameters per transaction:

*   `sender` the contract address invoking the tx
    
*   `calls` a list containing a sublist of each call to be sent. Each sublist must consist of:
    
    1.  `to` the address of the target contract of the message
        
    2.  `selector` the function to be called on the target contract
        
    3.  `calldata` the parameters for the given `selector`
        
    
*   `nonce` an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    
*   `max_fee` the maximum fee a user will pay
    

Which returns:

*   `calls` a list of calls to be bundled in the transaction
    
*   `calldata` a list of arguments for each call
    
*   `sig_r` the transaction signature
    
*   `sig_s` the transaction signature
    

While the `Signer` class performs much of the work for a transaction to be sent, it neither manages nonces nor invokes the actual transaction on the Account contract. To simplify Account management, most of this is abstracted away with `MockSigner`.

### [](#mocksigner_utility)
MockSigner utility

The `MockSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account, crafting the transaction and managing nonces.

The flow of a transaction starts with checking the nonce and converting the `to` contract address of each call to hexadecimal format. The hexadecimal conversion is necessary because Nile’s `Signer` converts the address to a base-16 integer (which requires a string argument). Note that directly converting `to` to a string will ultimately result in an integer exceeding Cairo’s `FIELD_PRIME`.

The values included in the transaction are passed to the `sign_transaction` method of Nile’s `Signer` which creates and returns a signature. Finally, the `MockSigner` instance invokes the account contract’s `__execute__` with the transaction data.

Users only need to interact with the following exposed methods to perform a transaction:

*   `send_transaction(account, to, selector_name, calldata, nonce=None, max_fee=0)` returns a future of a signed transaction, ready to be sent.
    
*   `send_transactions(account, calls, nonce=None, max_fee=0)` returns a future of batched signed transactions, ready to be sent.
    

To use `MockSigner`, pass a private key when instantiating the class:

    from utils import MockSigner
    
    PRIVATE_KEY = 123456789987654321
    signer = MockSigner(PRIVATE_KEY)

Then send single transactions with the `send_transaction` method.

    await signer.send_transaction(account, contract_address, 'method_name', [])

If utilizing multicall, send multiple transactions with the `send_transactions` method.

        await signer.send_transactions(
            account,
            [\
                (contract_address, 'method_name', [param1, param2]),\
                (contract_address, 'another_method', [])\
            ]
        )

### [](#mockethsigner_utility)
MockEthSigner utility

The `MockEthSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account with a secp256k1 curve key pair, crafting the transaction and managing nonces. It differs from the `MockSigner` implementation by:

*   not using the public key but its derived address instead (the last 20 bytes of the keccak256 hash of the public key and adding `0x` to the beginning)
    
*   signing the message with a secp256k1 curve address
    

[](#account_entrypoint)
Account entrypoint
------------------------------------------

`__execute__` acts as a single entrypoint for all user interaction with any contract, including managing the account contract itself. That’s why if you want to change the public key controlling the Account, you would send a transaction targeting the very Account contract:

    await signer.send_transaction(account, account.contract_address, 'set_public_key', [NEW_KEY])

Or if you want to update the Account’s L1 address on the `AccountRegistry` contract, you would

    await signer.send_transaction(account, registry.contract_address, 'set_L1_address', [NEW_ADDRESS])

You can read more about how messages are structured and hashed in the [Account message scheme discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/24)
. For more information on the design choices and implementation of multicall, you can read the [How should Account multicall work discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/27)
.

The `__execute__` method has the following interface:

    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

Where:

*   `call_array_len` is the number of calls
    
*   `call_array` is an array representing each `Call`
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    
*   `nonce` is an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    

|     |     |
| --- | --- |
|     | The scheme of building multicall transactions within the `__execute__` method will change once StarkNet allows for pointers in struct arrays. In which case, multiple transactions can be passed to (as opposed to built within) `__execute__`. |

[](#call_and_accountcallarray_format)
`Call` and `AccountCallArray` format
--------------------------------------------------------------------------

The idea is for all user intent to be encoded into a `Call` representing a smart contract call. Users can also pack multiple messages into a single transaction (creating a multicall transaction). Cairo currently does not support arrays of structs with pointers which means the `__execute__` function cannot properly iterate through mutiple `Call`s. Instead, this implementation utilizes a workaround with the `AccountCallArray` struct. See [Multicall transactions](#multicall_transactions)
.

### [](#call)
`Call`

A single `Call` is structured as follows:

    struct Call:
        member to: felt
        member selector: felt
        member calldata_len: felt
        member calldata: felt*
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    

### [](#accountcallarray)
`AccountCallArray`

`AccountCallArray` is structured as:

    struct AccountCallArray:
        member to: felt
        member selector: felt
        member data_offset: felt
        member data_len: felt
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `data_offset` is the starting position of the calldata array that holds the `Call`'s calldata
    
*   `data_len` is the number of calldata elements in the `Call`
    

[](#multicall_transactions)
Multicall transactions
--------------------------------------------------

A multicall transaction packs the `to`, `selector`, `calldata_offset`, and `calldata_len` of each call into the `AccountCallArray` struct and keeps the cumulative calldata for every call in a separate array. The `__execute__` function rebuilds each message by combining the `AccountCallArray` with its calldata (demarcated by the offset and calldata length specified for that particular call). The rebuilding logic is set in the internal `_from_call_array_to_call`.

This is the basic flow:

First, the user sends the messages for the transaction through a Signer instantiation which looks like this:

     await signer.send_transaction(
             account, [\
                 (contract_address, 'contract_method', [arg_1]),\
                 (contract_address, 'another_method', [arg_1, arg_2])\
             ]
         )

Then the `_from_call_to_call_array` method in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 converts each call into the `AccountCallArray` format and cumulatively stores the calldata of every call into a single array. Next, both arrays (as well as the `sender`, `nonce`, and `max_fee`) are used to create the transaction hash. The Signer then invokes `__execute__` with the signature and passes `AccountCallArray`, calldata, and nonce as arguments.

Finally, the `__execute__` method takes the `AccountCallArray` and calldata and builds an array of `Call`s (MultiCall).

|     |     |
| --- | --- |
|     | Every transaction utilizes `AccountCallArray`. A single `Call` is treated as a bundle with one message. |

[](#api_specification)
API Specification
----------------------------------------

This in a nutshell is the Account contract public API:

    func get_public_key() -> (res: felt):
    end
    
    func get_nonce() -> (res: felt):
    end
    
    func set_public_key(new_public_key: felt):
    end
    
    func is_valid_signature(hash: felt,
            signature_len: felt,
            signature: felt*
        ) -> (is_valid: felt):
    end
    
    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

### [](#get_public_key)
`get_public_key`

Returns the public key associated with the Account contract.

Parameters: None.

Returns:

    public_key: felt

### [](#get_nonce)
`get_nonce`

Returns the current transaction nonce for the Account.

Parameters: None.

Returns:

    nonce: felt

### [](#set_public_key)
`set_public_key`

Sets the public key that will control this Account. It can be used to rotate keys for security, change them in case of compromised keys or even transferring ownership of the account.

Parameters:

    public_key: felt

Returns: None.

### [](#is_valid_signature)
`is_valid_signature`

This function is inspired by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and returns `TRUE` if a given signature is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    hash: felt
    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#execute)
`__execute__`

This is the only external entrypoint to interact with the Account contract. It:

1.  Validates the transaction signature matches the message (including the nonce)
    
2.  Increments the nonce
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

|     |     |
| --- | --- |
|     | The current signature scheme expects a 2-element array like `[sig_r, sig_s]`. |

Returns:

    response_len: felt
    response: felt*

### [](#is_valid_eth_signature)
`is_valid_eth_signature`

Returns `TRUE` if a given signature in the secp256k1 curve is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#eth_execute)
`eth_execute`

This follows the same idea as the vanilla version of `execute` with the sole difference that signature verification is on the secp256k1 curve.

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

Returns:

    response_len: felt
    response: felt*

|     |     |
| --- | --- |
|     | The current signature scheme expects a 7-element array like `[sig_v, uint256_sig_r_low, uint256_sig_r_high, uint256_sig_s_low, uint256_sig_s_high, uint256_hash_low, uint256_hash_high]` given that the parameters of the verification are bigger than a felt. |

### [](#unsafe_execute)
`_unsafe_execute`

It’s an [internal](extensibility#the_pattern)
 method that performs the following tasks:

1.  Increments the nonce.
    
2.  Takes the input and builds a `Call` for each iterated message. See [Multicall transactions](#multicall_transactions)
     for more information.
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset differs on the signature type being used by the Account.

### [](#account)
Account

The [`Account`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
 preset uses StarkNet keys to validate transactions.

### [](#eth_account)
Eth Account

The [`EthAccount`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/EthAccount.cairo)
 preset supports Ethereum addresses, validating transactions with secp256k1 keys.

[](#account_differentiation_with_erc165)
Account differentiation with ERC165
----------------------------------------------------------------------------

Certain contracts like ERC721 require a means to differentiate between account contracts and non-account contracts. For a contract to declare itself as an account, it should implement [ERC165](https://eips.ethereum.org/EIPS/eip-165)
 as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. To be in compliance with ERC165 specifications, the idea is to calculate the XOR of `IAccount`'s EVM selectors (not StarkNet selectors). The resulting magic value of `IAccount` is 0x50b70dcb.

Our ERC165 integration on StarkNet is inspired by OpenZeppelin’s Solidity implementation of [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
 which stores the interfaces that the implementing contract supports. In the case of account contracts, querying `supportsInterface` of an account’s address with the `IAccount` magic value should return `TRUE`.

[](#extending_the_account_contract)
Extending the Account contract
------------------------------------------------------------------

Account contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
.

To implement custom account contracts, a pair of `validate` and `execute` functions should be exposed. This is why the Account library comes with different flavors of such pairs, like the vanilla `is_valid_signature` and `execute`, or the Ethereum flavored `is_valid_eth_signature` and `eth_execute` pair.

Account contract developers are encouraged to implement the [standard Account interface](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and incorporate the custom logic thereafter.

To implement alternative `execute` functions, make sure to check their corresponding `validate` function before calling the `_unsafe_execute` building block, as each of the current presets is doing. Do not expose `_unsafe_execute` directly.

|     |     |
| --- | --- |
|     | The `ecdsa_ptr` implicit argument should be included in new methods that invoke `_unsafe_execute` (even if the `ecdsa_ptr` is not being used). Otherwise, it’s possible that an account’s functionality can work in both the testing and local devnet environments; however, it could fail on public networks on account of the [SignatureBuiltinRunner](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py)<br>. See [issue #386](https://github.com/OpenZeppelin/cairo-contracts/issues/386)<br> for more information. |

Some other validation schemes to look out for in the future:

*   multisig
    
*   guardian logic like in [Argent’s account](https://github.com/argentlabs/argent-contracts-starknet/blob/de5654555309fa76160ba3d7393d32d2b12e7349/contracts/ArgentAccount.cairo)
    

[](#l1_escape_hatch_mechanism)
L1 escape hatch mechanism
--------------------------------------------------------

[](#paying_for_gas)
Paying for gas
----------------------------------

[← Proxies and Upgrades](/contracts-cairo/0.3.1/proxies)

[Access Control →](/contracts-cairo/0.3.1/access)




 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes non-standard functions like `increase_allowance`.

    #[starknet::interface]
    trait ERC20ABI<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
        fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool;
        fn decrease_allowance(
            ref self: TState, spender: ContractAddress, subtracted_value: u256
        ) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> felt252;
        fn symbol(self: @DualCaseERC20) -> felt252;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    trait IERC20Camel<TState> {
        fn name(self: @TState) -> felt252;
        fn symbol(self: @TState) -> felt252;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, fallback, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Presets](/contracts-cairo/0.8.0/presets)

[Counterfactual deployments →](/contracts-cairo/0.8.0/guides/deployment)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

Reference of interfaces and utilities related to upgradeability.

[](#core)
Core
--------------

### [](#IUpgradeable)
`IUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/upgrades/interface.cairo#L3)

    use openzeppelin::upgrades::interface::IUpgradeable;

Interface of an upgradeable contract.

Functions

*   [`upgrade(new_class_hash)`](#IUpgradeable-upgrade)
    

#### [](#IUpgradeable-Functions)
Functions

#### [](#IUpgradeable-upgrade)
`upgrade(new_class_hash: ClassHash)` external

Upgrades the contract code by updating its [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

|     |     |
| --- | --- |
|     | This function is usually protected by an [Access Control](../access)<br> mechanism. |

### [](#Upgradeable)
`Upgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.1/src/upgrades/upgradeable.cairo)

    use openzeppelin::upgrades::upgradeable::Upgradeable;

Upgradeable contract module.

Internal Functions

InternalImpl

*   [`_upgrade(self, new_class_hash)`](#Upgradeable-_upgrade)
    

Events

*   [`Upgraded(class_hash)`](#Upgradeable-Upgraded)
    

#### [](#Upgradeable-Internal-Functions)
Internal Functions

#### [](#Upgradeable-_upgrade)
`_upgrade(ref self: ContractState, new_class_hash: ClassHash)` internal

Upgrades the contract by updating the contract [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

Requirements:

*   `new_class_hash` must be different from zero.
    

Emits an [Upgraded](#Upgradeable-Upgraded)
 event.

#### [](#Upgradeable-Events)
Events

#### [](#Upgradeable-Upgraded)
`Upgraded(class_hash: ClassHash)` event

Emitted when the [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
 is upgraded.

[← Upgrades](/contracts-cairo/0.8.0-beta.1/upgrades)

[Accounts →](/contracts-cairo/0.8.0-beta.1/accounts)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The OpenZeppelin Contracts provide a ton of useful utilities that you can use in your project. Here are some of the more popular ones.

[](#cryptography)
Cryptography
------------------------------

### [](#checking_signatures_on_chain)
Checking Signatures On-Chain

[`ECDSA`](api/cryptography#ECDSA)
 provides functions for recovering and managing Ethereum account ECDSA signatures. These are often generated via [`web3.eth.sign`](https://web3js.readthedocs.io/en/v1.2.4/web3-eth.html#sign)
, and are a 65 byte array (of type `bytes` in Solidity) arranged the following way: `[[v (1)], [r (32)], [s (32)]]`.

The data signer can be recovered with [`ECDSA.recover`](api/cryptography#ECDSA-recover-bytes32-bytes-)
, and its address compared to verify the signature. Most wallets will hash the data to sign and add the prefix '\\x19Ethereum Signed Message:\\n', so when attempting to recover the signer of an Ethereum signed message hash, you’ll want to use [`toEthSignedMessageHash`](api/cryptography#ECDSA-toEthSignedMessageHash-bytes32-)
.

    using ECDSA for bytes32;
    
    function _verify(bytes32 data, address account) pure returns (bool) {
        return keccack256(data)
            .toEthSignedMessageHash()
            .recover(signature) == account;
    }

|     |     |
| --- | --- |
|     | Getting signature verification right is not trivial: make sure you fully read and understand [`ECDSA`](api/cryptography#ECDSA)<br>'s documentation. |

### [](#verifying_merkle_proofs)
Verifying Merkle Proofs

[`MerkleProof`](api/cryptography#MerkleProof)
 provides [`verify`](api/cryptography#MerkleProof-verify-bytes32---bytes32-bytes32-)
, which can prove that some value is part of a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree)
.

[](#introspection)
Introspection
--------------------------------

In Solidity, it’s frequently helpful to know whether or not a contract supports an interface you’d like to use. ERC165 is a standard that helps do runtime interface detection. Contracts provides helpers both for implementing ERC165 in your contracts and querying other contracts:

*   [`IERC165`](api/introspection#IERC165)
     — this is the ERC165 interface that defines [`supportsInterface`](api/introspection#IERC165-supportsInterface-bytes4-)
    . When implementing ERC165, you’ll conform to this interface.
    
*   [`ERC165`](api/introspection#ERC165)
     — inherit this contract if you’d like to support interface detection using a lookup table in contract storage. You can register interfaces using [`_registerInterface(bytes4)`](api/introspection#ERC165-_registerInterface-bytes4-)
    : check out example usage as part of the ERC721 implementation.
    
*   [`ERC165Checker`](api/introspection#ERC165Checker)
     — ERC165Checker simplifies the process of checking whether or not a contract supports an interface you care about.
    
*   include with `using ERC165Checker for address;`
    
*   [`myAddress._supportsInterface(bytes4)`](api/introspection#ERC165Checker-_supportsInterface-address-bytes4-)
    
*   [`myAddress._supportsAllInterfaces(bytes4[`](api/introspection#ERC165Checker-_supportsAllInterfaces-address-bytes4---)\
    `)`\]
    

    contract MyContract {
        using ERC165Checker for address;
    
        bytes4 private InterfaceId_ERC721 = 0x80ac58cd;
    
        /**
         * @dev transfer an ERC721 token from this contract to someone else
         */
        function transferERC721(
            address token,
            address to,
            uint256 tokenId
        )
            public
        {
            require(token.supportsInterface(InterfaceId_ERC721), "IS_NOT_721_TOKEN");
            IERC721(token).transferFrom(address(this), to, tokenId);
        }
    }

[](#math)
Math
--------------

The most popular math related library OpenZeppelin Contracts provides is [`SafeMath`](api/math#SafeMath)
, which provides mathematical functions that protect your contract from overflows and underflows.

Include the contract with `using SafeMath for uint256;` and then call the functions:

*   `myNumber.add(otherNumber)`
    
*   `myNumber.sub(otherNumber)`
    
*   `myNumber.div(otherNumber)`
    
*   `myNumber.mul(otherNumber)`
    
*   `myNumber.mod(otherNumber)`
    

Easy!

[](#payment)
Payment
--------------------

Want to split some payments between multiple people? Maybe you have an app that sends 30% of art purchases to the original creator and 70% of the profits to the current owner; you can build that with [`PaymentSplitter`](api/payment#PaymentSplitter)
!

In Solidity, there are some security concerns with blindly sending money to accounts, since it allows them to execute arbitrary code. You can read up on these security concerns in the [Ethereum Smart Contract Best Practices](https://consensys.github.io/smart-contract-best-practices/)
 website. One of the ways to fix reentrancy and stalling problems is, instead of immediately sending Ether to accounts that need it, you can use [`PullPayment`](api/payment#PullPayment)
, which offers an [`_asyncTransfer`](api/payment#PullPayment-_asyncTransfer-address-uint256-)
 function for sending money to something and requesting that they [`withdrawPayments()`](api/payment#PullPayment-withdrawPayments-address-payable-)
 it later.

If you want to Escrow some funds, check out [`Escrow`](api/payment#Escrow)
 and [`ConditionalEscrow`](api/payment#ConditionalEscrow)
 for governing the release of some escrowed Ether.

[](#collections)
Collections
----------------------------

If you need support for more powerful collections than Solidity’s native arrays and mappings, take a look at [`EnumerableSet`](api/utils#EnumerableSet)
 and [`EnumerableMap`](api/utils#EnumerableMap)
. They are similar to mappings in that they store and remove elements in constant time and don’t allow for repeated entries, but they also support _enumeration_, which means you can easily query all stored entries both on and off-chain.

[](#misc)
Misc
--------------

Want to check if an address is a contract? Use [`Address`](api/utils#Address)
 and [`Address.isContract()`](api/utils#Address-isContract-address-)
.

Want to keep track of some numbers that increment by 1 every time you want another one? Check out [`Counters`](api/utils#Counters)
. This is useful for lots of things, like creating incremental identifiers, as shown on the [ERC721 guide](erc721)
.

[← Strategies](/contracts/3.x/gsn-strategies)

[Access →](/contracts/3.x/api/access)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `ERC20.cairo` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Interface](#interface)
    
    *   [ERC20 compatibility](#erc20_compatibility)
        
    
*   [Usage](#usage)
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC20 (basic)](#erc20_basic)
        
    *   [ERC20Mintable](#erc20mintable)
        
    *   [ERC20Pausable](#erc20pausable)
        
    *   [ERC20Upgradeable](#erc20upgradeable)
        
    
*   [API Specification](#api_specification)
    
    *   [Methods](#methods)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`decimals`](#decimals)
            
        *   [`totalSupply`](#totalsupply)
            
        *   [`balanceOf`](#balanceof)
            
        *   [`allowance`](#allowance)
            
        *   [`transfer`](#transfer)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        
    *   [Events](#events)
        
        *   [`Transfer (event)`](#transfer_event)
            
        *   [`Approval (event)`](#approval_event)
            
        
    

[](#interface)
Interface
------------------------

    @contract_interface
    namespace IERC20:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func decimals() -> (decimals: felt):
        end
    
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func balanceOf(account: felt) -> (balance: Uint256):
        end
    
        func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
        end
    
        func transfer(recipient: felt, amount: Uint256) -> (success: felt):
        end
    
        func transferFrom(
                sender: felt,
                recipient: felt,
                amount: Uint256
            ) -> (success: felt):
        end
    
        func approve(spender: felt, amount: Uint256) -> (success: felt):
        end
    end

### [](#erc20_compatibility)
ERC20 compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard, in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it accepts a `felt` argument for `decimals` in the constructor calldata with a max value of 2^8 (imitating `uint8` type)
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `transfer`, `transferFrom` and `approve` will never return anything different from `TRUE` because they will revert on any error
    
*   function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo-lang/blob/7712b21fc3b1cb02321a58d0c0579f5370147a8b/src/starkware/starknet/public/abi.py#L25)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    

[](#usage)
Usage
----------------

Use cases go from medium of exchange currency to voting rights, staking, and more.

Considering that the constructor method looks like this:

    func constructor(
        name: felt,               # Token name as Cairo short string
        symbol: felt,             # Token symbol as Cairo short string
        decimals: felt            # Token decimals (usually 18)
        initial_supply: Uint256,  # Amount to be minted
        recipient: felt           # Address where to send initial supply to
    ):

To create a token you need to deploy it like this:

    erc20 = await starknet.deploy(
        "openzeppelin/token/erc20/presets/ERC20.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),     # name\
            str_to_felt("TKN"),       # symbol\
            18,                       # decimals\
            (1000, 0),                # initial supply\
            account.contract_address  # recipient\
        ]
    )

As most StarkNet contracts, it expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it. For example:

    signer = MockSigner(PRIVATE_KEY)
    amount = uint(100)
    
    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    await signer.send_transaction(account, erc20.contract_address, 'transfer', [recipient_address, *amount])

[](#extensibility)
Extensibility
--------------------------------

ERC20 contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
. The basic idea behind integrating the pattern is to import the requisite ERC20 methods from the ERC20 library and incorporate the extended logic thereafter. For example, let’s say you wanted to implement a pausing mechanism. The contract should first import the ERC20 methods and the extended logic from the [Pausable library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/pausable/library.cairo)
 i.e. `Pausable.pause`, `Pausable.unpause`. Next, the contract should expose the methods with the extended logic therein like this:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()          # imported extended logic
        ERC20.transfer(recipient, amount)     # imported library method
        return (TRUE)
    end

Note that extensibility does not have to be only library-based like in the above example. For instance, an ERC20 contract with a pausing mechanism can define the pausing methods directly in the contract or even import the `pausable` methods from the library and tailor them further.

Some other ways to extend ERC20 contracts may include:

*   Implementing a minting mechanism
    
*   Creating a timelock
    
*   Adding roles such as owner or minter
    

For full examples of the extensibility pattern being used in ERC20 contracts, see [Presets](#presets)
.

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset mints an initial supply which is especially necessary for presets that do not expose a `mint` method.

### [](#erc20_basic)
ERC20 (basic)

The [`ERC20`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 preset offers a quick and easy setup for deploying a basic ERC20 token.

### [](#erc20mintable)
ERC20Mintable

The [`ERC20Mintable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
 preset allows the contract owner to mint new tokens.

### [](#erc20pausable)
ERC20Pausable

The [`ERC20Pausable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
 preset allows the contract owner to pause/unpause all state-modifying methods i.e. `transfer`, `approve`, etc. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug.

### [](#erc20upgradeable)
ERC20Upgradeable

The [`ERC20Upgradeable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
 preset allows the contract owner to upgrade a contract by deploying a new ERC20 implementation contract while also maintaing the contract’s state. This preset proves useful for scenarios such as eliminating bugs and adding new features. For more on upgradeability, see [Contract upgrades](proxies#contract_upgrades)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#methods)
Methods

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func decimals() -> (decimals: felt):
    end
    
    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func balanceOf(account: felt) -> (balance: Uint256):
    end
    
    func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
    end
    
    func transfer(recipient: felt, amount: Uint256) -> (success: felt):
    end
    
    func transferFrom(
            sender: felt,
            recipient: felt,
            amount: Uint256
        ) -> (success: felt):
    end
    
    func approve(spender: felt, amount: Uint256) -> (success: felt):
    end

#### [](#name)
`name`

Returns the name of the token.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the ticker symbol of the token.

Parameters: None.

Returns:

    symbol: felt

#### [](#decimals)
`decimals`

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user representation.

Parameters: None.

Returns:

    decimals: felt

#### [](#totalsupply)
`totalSupply`

Returns the amount of tokens in existence.

Parameters: None.

Returns:

    totalSupply: Uint256

#### [](#balanceof)
`balanceOf`

Returns the amount of tokens owned by `account`.

Parameters:

    account: felt

Returns:

    balance: Uint256

#### [](#allowance)
`allowance`

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through `transferFrom`. This is zero by default.

This value changes when `approve` or `transferFrom` are called.

Parameters:

    owner: felt
    spender: felt

Returns:

    remaining: Uint256

#### [](#transfer)
`transfer`

Moves `amount` tokens from the caller’s account to `recipient`. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#transferfrom)
`transferFrom`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    sender: felt
    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#approve)
`approve`

Sets `amount` as the allowance of `spender` over the caller’s tokens. It returns `1` representing a bool if it succeeds.

Emits an [Approval](#approval_event)
 event.

Parameters:

    spender: felt
    amount: Uint256

Returns:

    success: felt

### [](#events)
Events

    func Transfer(from_: felt, to: felt, value: Uint256):
    end
    
    func Approval(owner: felt, spender: felt, value: Uint256):
    end

#### [](#transfer_event)
`Transfer (event)`

Emitted when `value` tokens are moved from one account (`from_`) to another (`to`).

Note that `value` may be zero.

Parameters:

    from_: felt
    to: felt
    value: Uint256

#### [](#approval_event)
`Approval (event)`

Emitted when the allowance of a `spender` for an `owner` is set by a call to [approve](#approve)
. `value` is the new allowance.

Parameters:

    owner: felt
    spender: felt
    value: Uint256

[← Access Control](/contracts-cairo/0.3.0/access)

[ERC721 →](/contracts-cairo/0.3.0/erc721)




 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/access/ownable/ownable.cairo)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#AccessControlComponent-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        #[abi(embed_v0)]
        impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
        #[abi(embed_v0)]
        impl OwnableCamelOnlyImpl =
            OwnableComponent::OwnableCamelOnlyImpl<ContractState>;
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `Ownable` implementation:

    trait IOwnable {
        /// Returns the current owner.
        fn owner() -> ContractAddress;
    
        /// Transfers the ownership from the current owner to a new owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#OwnableComponent-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing `AccessControl` on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControlComponent)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#OwnableComponent)
. Where `AccessControl` shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControlComponent-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControlComponent-grant_role)
 and [`revoke_role`](api/access#AccessControlComponent-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControlComponent-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: felt252,
            symbol: felt252,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControl` implementation:

    trait IAccessControl {
        /// Returns whether the account has the role or not.
        fn has_role(role: felt252, account: ContractAddress) -> bool;
    
        /// Returns the adming role that controls `role`.
        fn get_role_admin(role: felt252) -> felt252;
    
        /// Grants `role` to `account`.
        fn grant_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from `account`.
        fn revoke_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from self.
        fn renounce_role(role: felt252, account: ContractAddress);
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← Counterfactual Deployments](/contracts-cairo/0.8.1/guides/deployment)

[API Reference →](/contracts-cairo/0.8.1/api/access)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

In different blockchains, multiple patterns have been developed for making a contract upgradeable including the widely adopted proxy patterns.

Starknet has native upgradeability through a syscall that updates the contract source code, removing the need for proxies.

[](#replacing_contract_classes)
Replacing contract classes
----------------------------------------------------------

To better comprehend how upgradeability works in Starknet, it’s important to understand the difference between a contract and its contract class.

[Contract Classes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-classes/)
 represent the source code of a program. All contracts are associated to a class, and many contracts can be instances of the same one. Classes are usually represented by a [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
, and before a contract of a class can be deployed, the class hash needs to be declared.

### [](#replace_class_syscall)
`replace_class_syscall`

The `[replace_class](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#replace_class) ` syscall allows a contract to update its source code by replacing its class hash once deployed.

    /// Upgrades the contract source code to the new contract class.
    fn _upgrade(new_class_hash: ClassHash) {
        assert(!new_class_hash.is_zero(), 'Class hash cannot be zero');
        starknet::replace_class_syscall(new_class_hash).unwrap();
    }

|     |     |
| --- | --- |
|     | If a contract is deployed without this mechanism, its class hash can still be replaced through [library calls](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#library_call)<br>. |

[](#upgradeable_component)
`Upgradeable` component
--------------------------------------------------

OpenZeppelin Contracts for Cairo provides [Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/upgrades/upgradeable.cairo)
 to add upgradeability support to your contracts.

### [](#usage)
Usage

Upgrades are often very sensitive operations, and some form of access control is usually required to avoid unauthorized upgrades. The [Ownable](access#ownership_and_ownable)
 module is used in this example.

|     |     |
| --- | --- |
|     | We will be using the following module to implement the [IUpgradeable](api/upgrades#IUpgradeable)<br> interface described in the API Reference section. |

    #[starknet::contract]
    mod UpgradeableContract {
        use openzeppelin::access::ownable::Ownable as ownable_component;
        use openzeppelin::upgrades::Upgradeable as upgradeable_component;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::ClassHash;
        use starknet::ContractAddress;
    
        component!(path: ownable_component, storage: ownable, event: OwnableEvent);
        component!(path: upgradeable_component, storage: upgradeable, event: UpgradeableEvent);
    
        /// Ownable
        #[abi(embed_v0)]
        impl OwnableImpl = ownable_component::OwnableImpl<ContractState>;
        impl OwnableInternalImpl = ownable_component::InternalImpl<ContractState>;
    
        /// Upgradeable
        impl UpgradeableInternalImpl = upgradeable_component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: ownable_component::Storage,
            #[substorage(v0)]
            upgradeable: upgradeable_component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: ownable_component::Event,
            #[flat]
            UpgradeableEvent: upgradeable_component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            self.ownable.initializer(owner);
        }
    
        #[external(v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                // This function can only be called by the owner
                self.ownable.assert_only_owner();
    
                // Replace the class hash upgrading the contract
                self.upgradeable._upgrade(new_class_hash);
            }
        }
    }

[](#proxies_and_starknet)
Proxies and Starknet
----------------------------------------------

Proxies enable different patterns such as upgrades and clones. But since Starknet achieves the same in different ways is that there’s no support to implement them.

In the case of contract upgrades, it is achieved by simply changing the contract’s class hash. As of clones, contracts already are like clones of the class they implement.

Implementing a proxy pattern in Starknet has an important limitation: there is no fallback mechanism to be used for redirecting every potential function call to the implementation. This means that a generic proxy contract can’t be implemented. Instead, a limited proxy contract can implement specific functions that forward their execution to another contract class. This can still be useful for example to upgrade the logic of some functions.

[← Interfaces and Dispatchers](/contracts-cairo/0.8.0-beta.0/interfaces)

[API Reference →](/contracts-cairo/0.8.0-beta.0/api/upgrades)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `ERC20.cairo` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Interface](#interface)
    
    *   [ERC20 compatibility](#erc20_compatibility)
        
    
*   [Usage](#usage)
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC20 (basic)](#erc20_basic)
        
    *   [ERC20Mintable](#erc20mintable)
        
    *   [ERC20Pausable](#erc20pausable)
        
    *   [ERC20Upgradeable](#erc20upgradeable)
        
    
*   [API Specification](#api_specification)
    
    *   [Methods](#methods)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`decimals`](#decimals)
            
        *   [`totalSupply`](#totalsupply)
            
        *   [`balanceOf`](#balanceof)
            
        *   [`allowance`](#allowance)
            
        *   [`transfer`](#transfer)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        
    *   [Events](#events)
        
        *   [`Transfer (event)`](#transfer_event)
            
        *   [`Approval (event)`](#approval_event)
            
        
    

[](#interface)
Interface
------------------------

    @contract_interface
    namespace IERC20 {
        func name() -> (name: felt) {
        }
    
        func symbol() -> (symbol: felt) {
        }
    
        func decimals() -> (decimals: felt) {
        }
    
        func totalSupply() -> (totalSupply: Uint256) {
        }
    
        func balanceOf(account: felt) -> (balance: Uint256) {
        }
    
        func allowance(owner: felt, spender: felt) -> (remaining: Uint256) {
        }
    
        func transfer(recipient: felt, amount: Uint256) -> (success: felt) {
        }
    
        func transferFrom(sender: felt, recipient: felt, amount: Uint256) -> (success: felt) {
        }
    
        func approve(spender: felt, amount: Uint256) -> (success: felt) {
        }
    }

### [](#erc20_compatibility)
ERC20 compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard, in the following ways:

*   It uses Cairo’s `uint256` instead of `felt`.
    
*   It returns `TRUE` as success.
    
*   It accepts a `felt` argument for `decimals` in the constructor calldata with a max value of 2^8 (imitating `uint8` type).
    
*   It makes use of Cairo’s short strings to simulate `name` and `symbol`.
    

But some differences can still be found, such as:

*   `transfer`, `transferFrom` and `approve` will never return anything different from `TRUE` because they will revert on any error.
    
*   Function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo-lang/blob/7712b21fc3b1cb02321a58d0c0579f5370147a8b/src/starkware/starknet/public/abi.py#L25)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    .
    

[](#usage)
Usage
----------------

Use cases go from medium of exchange currency to voting rights, staking, and more.

Considering that the constructor method looks like this:

    func constructor(
        name: felt,               // Token name as Cairo short string
        symbol: felt,             // Token symbol as Cairo short string
        decimals: felt            // Token decimals (usually 18)
        initial_supply: Uint256,  // Amount to be minted
        recipient: felt           // Address where to send initial supply to
    ) {
    }

To create a token you need to deploy it like this:

    erc20 = await starknet.deploy(
        "openzeppelin/token/erc20/presets/ERC20.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),     # name\
            str_to_felt("TKN"),       # symbol\
            18,                       # decimals\
            (1000, 0),                # initial supply\
            account.contract_address  # recipient\
        ]
    )

As most StarkNet contracts, it expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it. For example:

    signer = MockSigner(PRIVATE_KEY)
    amount = uint(100)
    
    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    await signer.send_transaction(account, erc20.contract_address, 'transfer', [recipient_address, *amount])

[](#extensibility)
Extensibility
--------------------------------

ERC20 contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
. The basic idea behind integrating the pattern is to import the requisite ERC20 methods from the ERC20 library and incorporate the extended logic thereafter. For example, let’s say you wanted to implement a pausing mechanism. The contract should first import the ERC20 methods and the extended logic from the [Pausable library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/security/pausable/library.cairo)
 i.e. `Pausable.pause`, `Pausable.unpause`. Next, the contract should expose the methods with the extended logic therein like this:

    @external
    func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        recipient: felt, amount: Uint256
    ) -> (success: felt) {
        Pausable.assert_not_paused();                 // imported extended logic
        return ERC20.transfer(recipient, amount);     // imported library method
    }

Note that extensibility does not have to be only library-based like in the above example. For instance, an ERC20 contract with a pausing mechanism can define the pausing methods directly in the contract or even import the `pausable` methods from the library and tailor them further.

Some other ways to extend ERC20 contracts may include:

*   Implementing a minting mechanism.
    
*   Creating a timelock.
    
*   Adding roles such as owner or minter.
    

For full examples of the extensibility pattern being used in ERC20 contracts, see [Presets](#presets)
.

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset mints an initial supply which is especially necessary for presets that do not expose a `mint` method.

### [](#erc20_basic)
ERC20 (basic)

The [`ERC20`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 preset offers a quick and easy setup for deploying a basic ERC20 token.

### [](#erc20mintable)
ERC20Mintable

The [`ERC20Mintable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
 preset allows the contract owner to mint new tokens.

### [](#erc20pausable)
ERC20Pausable

The [`ERC20Pausable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
 preset allows the contract owner to pause/unpause all state-modifying methods i.e. `transfer`, `approve`, etc. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug.

### [](#erc20upgradeable)
ERC20Upgradeable

The [`ERC20Upgradeable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
 preset allows the contract owner to upgrade a contract by deploying a new ERC20 implementation contract while also maintaining the contract’s state. This preset proves useful for scenarios such as eliminating bugs and adding new features. For more on upgradeability, see [Contract upgrades](proxies#contract_upgrades)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#methods)
Methods

    func name() -> (name: felt) {
    }
    
    func symbol() -> (symbol: felt) {
    }
    
    func decimals() -> (decimals: felt) {
    }
    
    func totalSupply() -> (totalSupply: Uint256) {
    }
    
    func balanceOf(account: felt) -> (balance: Uint256) {
    }
    
    func allowance(owner: felt, spender: felt) -> (remaining: Uint256) {
    }
    
    func transfer(recipient: felt, amount: Uint256) -> (success: felt) {
    }
    
    func transferFrom(sender: felt, recipient: felt, amount: Uint256) -> (success: felt) {
    }
    
    func approve(spender: felt, amount: Uint256) -> (success: felt) {
    }

#### [](#name)
`name`

Returns the name of the token.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the ticker symbol of the token.

Parameters: None.

Returns:

    symbol: felt

#### [](#decimals)
`decimals`

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user representation.

Parameters: None.

Returns:

    decimals: felt

#### [](#totalsupply)
`totalSupply`

Returns the amount of tokens in existence.

Parameters: None.

Returns:

    totalSupply: Uint256

#### [](#balanceof)
`balanceOf`

Returns the amount of tokens owned by `account`.

Parameters:

    account: felt

Returns:

    balance: Uint256

#### [](#allowance)
`allowance`

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through `transferFrom`. This is zero by default.

This value changes when `approve` or `transferFrom` are called.

Parameters:

    owner: felt
    spender: felt

Returns:

    remaining: Uint256

#### [](#transfer)
`transfer`

Moves `amount` tokens from the caller’s account to `recipient`. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#transferfrom)
`transferFrom`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    sender: felt
    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#approve)
`approve`

Sets `amount` as the allowance of `spender` over the caller’s tokens. It returns `1` representing a bool if it succeeds.

Emits an [Approval](#approval_event)
 event.

Parameters:

    spender: felt
    amount: Uint256

Returns:

    success: felt

### [](#events)
Events

    func Transfer(from_: felt, to: felt, value: Uint256) {
    }
    
    func Approval(owner: felt, spender: felt, value: Uint256) {
    }

#### [](#transfer_event)
`Transfer (event)`

Emitted when `value` tokens are moved from one account (`from_`) to another (`to`).

Note that `value` may be zero.

Parameters:

    from_: felt
    to: felt
    value: Uint256

#### [](#approval_event)
`Approval (event)`

Emitted when the allowance of a `spender` for an `owner` is set by a call to [approve](#approve)
. `value` is the new allowance.

Parameters:

    owner: felt
    spender: felt
    value: Uint256

[← Access Control](/contracts-cairo/0.5.0/access)

[ERC721 →](/contracts-cairo/0.5.0/erc721)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

Access control—​that is, "who is allowed to do this thing"--is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Ownable](#ownable)
    
    *   [Quickstart](#quickstart)
        
    *   [Ownable library API](#ownable_library_api)
        
    *   [Ownable events](#ownable_events)
        
    
*   [AccessControl](#accesscontrol)
    
    *   [Usage](#usage)
        
    *   [Granting and revoking roles](#granting_and_revoking_roles)
        
    *   [Creating role identifiers](#creating_role_identifiers)
        
    *   [AccessControl library API](#accesscontrol_library_api)
        
    *   [AccessControl events](#accesscontrol_events)
        
    

[](#ownable)
Ownable
--------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/access/ownable/library.cairo)
 for implementing ownership in your contracts.

### [](#quickstart)
Quickstart

Integrating [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/access/ownable/library.cairo)
 into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [initializer](#initializer)
 like this:

    from openzeppelin.access.ownable.library import Ownable
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) {
        Ownable.initializer(owner);
        return ();
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    from openzeppelin.access.ownable.library import Ownable
    
    func protected_function{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        Ownable.assert_only_owner();
        return ();
    }

### [](#ownable_library_api)
Ownable library API

    func initializer(owner: felt) {
    }
    
    func assert_only_owner() {
    }
    
    func owner() -> (owner: felt) {
    }
    
    func transfer_ownership(new_owner: felt) {
    }
    
    func renounce_ownership() {
    }
    
    func _transfer_ownership(new_owner: felt) {
    }

#### [](#initializer)
`initializer`

Initializes Ownable access control and should be called in the implementing contract’s constructor. Assigns `owner` as the initial owner address of the contract.

This must be called only once.

Parameters:

    owner: felt

Returns: None.

#### [](#assert_only_owner)
`assert_only_owner`

Reverts if called by any account other than the owner. In case of renounced ownership, any call from the default zero address will also be reverted.

Parameters: None.

Returns: None.

#### [](#owner)
`owner`

Returns the address of the current owner.

Parameters: None.

Returns:

    owner: felt

#### [](#transfer_ownership)
`transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

#### [](#renounce_ownership)
`renounce_ownership`

Leaves the contract without owner. It will not be possible to call functions with `assert_only_owner` anymore. Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters: None.

Returns: None.

#### [](#transfer-ownership-internal)
`_transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). [`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

### [](#ownable_events)
Ownable events

    func OwnershipTransferred(previousOwner: felt, newOwner: felt) {
    }

#### [](#ownershiptransferred)
OwnershipTransferred

Emitted when ownership of a contract is transferred from `previousOwner` to `newOwner`.

Parameters:

    previousOwner: felt
    newOwner: felt

[](#accesscontrol)
AccessControl
--------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [assert\_only\_owner](#assert_only_owner)
. This check can be enforced through [assert\_only\_role](#assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role (see [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers).

Here’s a simple example of implementing `AccessControl` on a portion of an [ERC20 token contract](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 which defines and sets the 'minter' role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        name: felt, symbol: felt, decimals: felt, minter: felt
    ) {
        ERC20.initializer(name, symbol, decimals);
        AccessControl.initializer();
        AccessControl._grant_role(MINTER_ROLE, minter);
        return ();
    }
    
    @external
    func mint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        to: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(MINTER_ROLE);
        ERC20._mint(to, amount);
        return ();
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](#accesscontrol)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](#ownable)
. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens, and by using `assert_only_role`:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        name: felt, symbol: felt, decimals: felt, minter: felt, burner: felt
    ) {
        ERC20.initializer(name, symbol, decimals);
        AccessControl.initializer();
        AccessControl._grant_role(MINTER_ROLE, minter);
        AccessControl._grant_role(BURNER_ROLE, burner);
        return ();
    }
    
    @external
    func mint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        to: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(MINTER_ROLE);
        ERC20._mint(to, amount);
        return ();
    }
    
    @external
    func burn{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        from_: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(BURNER_ROLE);
        ERC20._burn(from_, amount);
        return ();
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses `_grant_role`, an [`internal`](extensibility#the_pattern)
 function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `assert_only_role` check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the `grant_role` and `revoke_role` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_set_role_admin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    from openzeppelin.utils.constants import DEFAULT_ADMIN_ROLE
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        name: felt, symbol: felt, decimals: felt, admin: felt,
    ) {
        ERC20.initializer(name, symbol, decimals);
        AccessControl.initializer();
    
        AccessControl._grant_role(DEFAULT_ADMIN_ROLE, admin);
        return ();
    }
    
    @external
    func mint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        to: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(MINTER_ROLE);
        ERC20._mint(to, amount);
        return ();
    }
    
    @external
    func burn{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        from_: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(BURNER_ROLE);
        ERC20._burn(from_, amount);
        return ();
    }

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

The following example uses the [AccessControl mock contract](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/tests/mocks/AccessControl.cairo)
 which exposes the role management functions. To grant and revoke roles in Python, for example:

    MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    # grants MINTER_ROLE and BURNER_ROLE to account1 and account2 respectively
    await signer.send_transactions(
        admin, [\
            (accesscontrol.contract_address, 'grantRole', [MINTER_ROLE, account1.contract_address]),\
            (accesscontrol.contract_address, 'grantRole', [BURNER_ROLE, account2.contract_address])\
        ]
    )
    
    # revokes MINTER_ROLE from account1
    await signer.send_transaction(
        admin,
        accesscontrol.contract_address,
        'revokeRole',
        [MINTER_ROLE, account1.contract_address]
    )

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier. For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements store a maximum of 252 bits. Even further, a declared _constant_ field element in a StarkNet contract stores even less (see [cairo\_constants](https://github.com/starkware-libs/cairo-lang/blob/release-v0.4.0b/src/starkware/cairo/lang/cairo_constants.py#L1)
). With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use the first or last 251 bits of keccak256 hash digests.
    
*   Use Cairo’s [hash2](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash.cairo)
    .
    

### [](#accesscontrol_library_api)
AccessControl library API

    func initializer() {
    }
    
    func assert_only_role(role: felt) {
    }
    
    func has_role(role: felt, user: felt) -> (has_role: felt) {
    }
    
    func get_role_admin(role: felt) -> (admin: felt) {
    }
    
    func grant_role(role: felt, user: felt) {
    }
    
    func revoke_role(role: felt, user: felt) {
    }
    
    func renounce_role(role: felt, user: felt) {
    }
    
    func _grant_role(role: felt, user: felt) {
    }
    
    func _revoke_role(role: felt, user: felt) {
    }
    
    func _set_role_admin(role: felt, admin_role: felt) {
    }

#### [](#initializer-accesscontrol)
`initializer`

Initializes AccessControl and should be called in the implementing contract’s constructor.

This must only be called once.

Parameters: None.

Returns: None.

#### [](#assert_only_role)
`assert_only_role`

Checks that an account has a specific role. Reverts with a message including the required role.

Parameters:

    role: felt

Returns: None.

#### [](#has_role)
has\_role

Returns `TRUE` if `user` has been granted `role`, `FALSE` otherwise.

Parameters:

    role: felt
    user: felt

Returns:

    has_role: felt

#### [](#get_role_admin)
`get_role_admin`

Returns the admin role that controls `role`. See [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
.

To change a role’s admin, use [`_set_role_admin`](#set_role_admin)
.

Parameters:

    role: felt

Returns:

    admin: felt

#### [](#grant_role)
`grant_role`

Grants `role` to `user`.

If `user` had not been already granted `role`, emits a [RoleGranted](#rolegranted)
 event.

Requirements:

*   The caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revoke_role)
`revoke_role`

Revokes `role` from `user`.

If `user` had been granted `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   The caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#renounce_role)
`renounce_role`

Revokes `role` from the calling `user`.

Roles are often managed via [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling `user` had been revoked `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   The caller must be `user`.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#grantrole-internal)
`_grant_role`

Grants `role` to `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleGranted](#rolegranted)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revokerole-internal)
`_revoke_role`

Revokes `role` from `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleRevoked](#rolerevoked)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#setroleadmin)
`_set_role_admin`

[`internal`](extensibility#the_pattern)
 function that sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#roleadminchanged)
 event.

Parameters:

    role: felt
    admin_role: felt

Returns: None.

### [](#accesscontrol_events)
AccessControl events

    func RoleGranted(role: felt, account: felt, sender: felt) {
    }
    
    func RoleRevoked(role: felt, account: felt, sender: felt) {
    }
    
    func RoleAdminChanged(role: felt, previousAdminRole: felt, newAdminRole: felt) {
    }

#### [](#rolegranted)
`RoleGranted`

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

Parameters:

    role: felt
    account: felt
    sender: felt

#### [](#rolerevoked)
`RoleRevoked`

Emitted when account is revoked role.

`sender` is the account that originated the contract call:

*   If using [revoke\_role](#revoke_role)
    , it is the admin role bearer.
    
*   If using [renounce\_role](#renounce_role)
    , it is the role bearer (i.e. `account`).
    

    role: felt
    account: felt
    sender: felt

#### [](#roleadminchanged)
`RoleAdminChanged`

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`.

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite `RoleAdminChanged` not being emitted signaling this.

    role: felt
    previousAdminRole: felt
    newAdminRole: felt

[← Accounts](/contracts-cairo/0.5.0/accounts)

[ERC20 →](/contracts-cairo/0.5.0/erc20)




 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#Ownable)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControl)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#Ownable)
`Ownable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::Ownable;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

Embeddable Functions

OwnableImpl

*   [`owner(self)`](#Ownable-owner)
    
*   [`transfer_ownership(self, new_owner)`](#Ownable-transfer_ownership)
    
*   [`renounce_ownership(self)`](#Ownable-renounce_ownership)
    

camelCase Support

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#Ownable-transferOwnership)
    
*   [`renounceOwnership(self)`](#Ownable-renounceOwnership)
    

Internal Functions

InternalImpl

*   [`initializer(self, owner)`](#Ownable-initializer)
    
*   [`assert_only_owner(self)`](#Ownable-assert_only_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#Ownable-_transfer_ownership)
    

Events

*   [`OwnershipTransferred(previous_owner, new_owner)`](#Ownable-OwnershipTransferred)
    

#### [](#Ownable-Embeddable-Functions)
Embeddable Functions

#### [](#Ownable-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#Ownable-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#Ownable-OwnershipTransferred)
 event.

#### [](#Ownable-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#Ownable-camelCase-Support)
camelCase Support

#### [](#Ownable-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#Ownable-transfer_ownership)
.

#### [](#Ownable-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#Ownable-renounce_ownership)
.

#### [](#Ownable-Internal-Functions)
Internal Functions

#### [](#Ownable-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#Ownable-OwnershipTransferred)
 event.

#### [](#Ownable-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#Ownable-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#Ownable-OwnershipTransferred)
 event.

#### [](#Ownable-Events)
Events

#### [](#Ownable-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/access/accesscontrol/interface.cairo)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControl-_set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControl)
`AccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControl;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControl-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [\_set\_role\_admin](#AccessControl-_set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

Embeddable Functions

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControl-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControl-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControl-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControl-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControl-renounce_role)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](#AccessControl-supports_interface)
    

camelCase Support

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControl-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControl-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControl-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControl-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControl-renounceRole)
    

Internal Functions

InternalImpl

*   [`initializer(self)`](#AccessControl-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControl-assert_only_role)
    
*   [`_set_role_admin(self, role, admin_role)`](#AccessControl-_set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControl-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControl-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControl-RoleRevoked)
    

#### [](#AccessControl-Embeddable-Functions)
Embeddable Functions

#### [](#AccessControl-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControl-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControl-_set_role_admin)
.

#### [](#AccessControl-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControl-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControl-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControl-grant_role)
 and [revoke\_role](#AccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControl-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControl-camelCase-Support)
camelCase Support

#### [](#AccessControl-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControl-has_role)
.

#### [](#AccessControl-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControl-get_role_admin)
.

#### [](#AccessControl-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControl-grant_role)
.

#### [](#AccessControl-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControl-revoke_role)
.

#### [](#AccessControl-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControl-renounce_role)
.

#### [](#AccessControl-Internal-Functions)
Internal Functions

#### [](#AccessControl-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControl-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControl-_set_role_admin)
`_set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControl-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControl-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControl-Events)
Events

#### [](#AccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access Control](/contracts-cairo/0.8.0-beta.0/access)

[ERC20 →](/contracts-cairo/0.8.0-beta.0/erc20)




 Introspection - OpenZeppelin Docs       

Introspection
=============

To smooth interoperability, often standards require smart contracts to implement [introspection mechanisms](https://en.wikipedia.org/wiki/Type_introspection)
.

In Ethereum, the [EIP165](https://eips.ethereum.org/EIPS/eip-165)
 standard defines how contracts should declare their support for a given interface, and how other contracts may query this support.

Starknet offers a similar mechanism for interface introspection defined by the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard.

[](#src5)
SRC5
--------------

Similar to its Ethereum counterpart, the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard requires contracts to implement the `supports_interface` function, which can be used by others to query if a given interface is supported:

    trait ISRC5 {
        /// Query if a contract implements an interface.
        /// Receives the interface identifier as specified in SRC-5.
        /// Returns `true` if the contract implements `interface_id`, `false` otherwise.
        fn supports_interface(interface_id: felt252) -> bool;
    }

### [](#computing_the_interface_id)
Computing the interface ID

The interface ID, as specified in the standard, is the [XOR](https://en.wikipedia.org/wiki/Exclusive_or)
 of all the [Extended Function Selectors](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#extended-function-selector)
 of the interface. We strongly advise reading the SNIP to understand the specifics of computing these extended function selectors. There are tools such as [src5-rs](https://github.com/ericnordelo/src5-rs)
 that can help with this process.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, we recommend using the SRC5 component to register support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            // Register the contract's support for the ISRC6 interface
            self.src5.register_interface(interface::ISRC6_ID);
        }
    
        (...)
    }

### [](#querying_interfaces)
Querying interfaces

Use the `supports_interface` function to query a contract’s support for a given interface.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::interface::ISRC5DispatcherTrait;
        use openzeppelin::introspection::interface::ISRC5Dispatcher;
        use starknet::ContractAddress;
    
        #[storage]
        struct Storage {}
    
        #[external(v0)]
        fn query_is_account(self: @ContractState, target: ContractAddress) -> bool {
            let dispatcher = ISRC5Dispatcher { contract_address: target };
            dispatcher.supports_interface(interface::ISRC6_ID)
        }
    }

|     |     |
| --- | --- |
|     | If you are unsure whether a contract implements SRC5 or not, you can follow the process described in [here](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#how-to-detect-if-a-contract-implements-src-5)<br>. |

[← API Reference](/contracts-cairo/0.8.0/api/account)

[Migrating ERC165 to SRC5 →](/contracts-cairo/0.8.0/guides/src5-migration)




 Crowdsales - OpenZeppelin Docs       

Crowdsales
==========

Crowdsales are a popular use for Ethereum; they let you allocate tokens to network participants in various ways, mostly in exchange for Ether. They come in a variety of shapes and flavors, so let’s go over the various types available in OpenZeppelin Contracts and how to use them.

Crowdsales have a bunch of different properties, but here are some important ones:

*   Price & Rate Configuration
    
*   Does your crowdsale sell tokens at a fixed price?
    
*   Does the price change over time or as a function of demand?
    
*   Emission
    
*   How is this token actually sent to participants?
    
*   Validation — Who is allowed to purchase tokens?
    
*   Are there KYC / AML checks?
    
*   Is there a max cap on tokens?
    
*   What if that cap is per-participant?
    
*   Is there a starting and ending time frame?
    
*   Distribution
    
*   Does distribution of funds happen in real-time or after the crowdsale?
    
*   Can participants receive a refund if the goal is not met?
    

To manage all of the different combinations and flavors of crowdsales, Contracts provides a highly configurable [`Crowdsale`](api/crowdsale#Crowdsale)
 base contract that can be combined with various other functionalities to construct a bespoke crowdsale.

[](#crowdsale-rate)
Crowdsale Rate
----------------------------------

Understanding the rate of a crowdsale is super important, and mistakes here are a common source of bugs.

✨ **HOLD UP FAM THIS IS IMPORTANT** ✨

Firstly, **all currency math is done in the smallest unit of that currency and converted to the correct decimal places when _displaying_ the currency**.

This means that when you do math in your smart contracts, you need to understand that you’re adding, dividing, and multiplying the smallest amount of a currency (like wei), _not_ the commonly-used displayed value of the currency (Ether).

In Ether, the smallest unit of the currency is wei, and `1 ETH === 10^18 wei`. In tokens, the process is _very similar_: `1 TKN === 10^(decimals) TKNbits`.

*   The smallest unit of a token is "bits" or `TKNbits`.
    
*   The display value of a token is `TKN`, which is `TKNbits * 10^(decimals)`
    

What people usually call "one token" is actually a bunch of TKNbits, displayed to look like `1 TKN`. This is the same relationship that Ether and wei have. And what you’re _always_ doing calculations in is **TKNbits and wei**.

So, if you want to issue someone "one token for every 2 wei" and your decimals are 18, your rate is `0.5e18`. Then, when I send you `2 wei`, your crowdsale issues me `2 * 0.5e18 TKNbits`, which is exactly equal to `10^18 TKNbits` and is displayed as `1 TKN`.

If you want to issue someone “1 TKN\` for every ``1 ETH”, and your decimals are 18, your rate is `1``. This is because what’s actually happening with the math is that the contract sees a user send `10^18 wei`, not `1 ETH`. Then it uses your rate of 1 to calculate `TKNbits = rate * wei`, or `1 * 10^18`, which is still `10^18`. And because your decimals are 18, this is displayed as `1 TKN`.

One more for practice: if I want to issue "1 TKN for every dollar (USD) in Ether", we would calculate it as follows:

*   assume 1 ETH == $400
    
*   therefore, 10^18 wei = $400
    
*   therefore, 1 USD is `10^18 / 400`, or `2.5 * 10^15 wei`
    
*   we have a decimals of 18, so we’ll use `10 ^ 18 TKNbits` instead of `1 TKN`
    
*   therefore, if the participant sends the crowdsale `2.5 * 10^15 wei` we should give them `10 ^ 18 TKNbits`
    
*   therefore the rate is `2.5 * 10^15 wei === 10^18 TKNbits`, or `1 wei = 400 TKNbits`
    
*   therefore, our rate is `400`
    

(this process is pretty straightforward when you keep 18 decimals, the same as Ether/wei)

[](#token-emission)
Token Emission
----------------------------------

One of the first decisions you have to make is "how do I get these tokens to users?". This is usually done in one of three ways:

*   (default) — The `Crowdsale` contract owns tokens and simply transfers tokens from its own ownership to users that purchase them.
    
*   [`MintedCrowdsale`](api/crowdsale#MintedCrowdsale)
     — The `Crowdsale` mints tokens when a purchase is made.
    
*   [`AllowanceCrowdsale`](api/crowdsale#AllowanceCrowdsale)
     — The `Crowdsale` is granted an allowance to another wallet (like a Multisig) that already owns the tokens to be sold in the crowdsale.
    

### [](#default-emission)
Default Emission

In the default scenario, your crowdsale must own the tokens that are sold. You can send the crowdsale tokens through a variety of methods, but here’s what it looks like in Solidity:

    IERC20(tokenAddress).transfer(CROWDSALE_ADDRESS, SOME_TOKEN_AMOUNT);

Then when you deploy your crowdsale, simply tell it about the token

    new Crowdsale(
        1,             // rate in TKNbits
        MY_WALLET,     // address where Ether is sent
        TOKEN_ADDRESS  // the token contract address
    );

### [](#minted-crowdsale)
Minted Crowdsale

To use a [`MintedCrowdsale`](api/crowdsale#MintedCrowdsale)
, your token must also be a [`ERC20Mintable`](api/token/ERC20#ERC20Mintable)
 token that the crowdsale has permission to mint from. This can look like:

    contract MyToken is ERC20, ERC20Mintable {
        // ... see "Tokens" for more info
    }
    
    contract MyCrowdsale is Crowdsale, MintedCrowdsale {
        constructor(
            uint256 rate,    // rate in TKNbits
            address payable wallet,
            IERC20 token
        )
            MintedCrowdsale()
            Crowdsale(rate, wallet, token)
            public
        {
    
        }
    }
    
    contract MyCrowdsaleDeployer {
        constructor()
            public
        {
            // create a mintable token
            ERC20Mintable token = new MyToken();
    
            // create the crowdsale and tell it about the token
            Crowdsale crowdsale = new MyCrowdsale(
                1,               // rate, still in TKNbits
                msg.sender,      // send Ether to the deployer
                token            // the token
            );
            // transfer the minter role from this contract (the default)
            // to the crowdsale, so it can mint tokens
            token.addMinter(address(crowdsale));
            token.renounceMinter();
        }
    }

### [](#allowancecrowdsale)
AllowanceCrowdsale

Use an [`AllowanceCrowdsale`](api/crowdsale#AllowanceCrowdsale)
 to send tokens from another wallet to the participants of the crowdsale. In order for this to work, the source wallet must give the crowdsale an allowance via the ERC20 [`approve`](api/token/ERC20#IERC20-approve-address-uint256-)
 method.

    contract MyCrowdsale is Crowdsale, AllowanceCrowdsale {
        constructor(
            uint256 rate,
            address payable wallet,
            IERC20 token,
            address tokenWallet  // <- new argument
        )
            AllowanceCrowdsale(tokenWallet)  // <- used here
            Crowdsale(rate, wallet, token)
            public
        {
    
        }
    }

Then after the crowdsale is created, don’t forget to approve it to use your tokens!

    IERC20(tokenAddress).approve(CROWDSALE_ADDRESS, SOME_TOKEN_AMOUNT);

[](#validation)
Validation
--------------------------

There are a bunch of different validation requirements that your crowdsale might be a part of:

*   [`CappedCrowdsale`](api/crowdsale#CappedCrowdsale)
     — adds a cap to your crowdsale, invalidating any purchases that would exceed that cap
    
*   [`IndividuallyCappedCrowdsale`](api/crowdsale#IndividuallyCappedCrowdsale)
     — caps an individual’s contributions.
    
*   [`WhitelistCrowdsale`](api/crowdsale#WhitelistCrowdsale)
     — only allow whitelisted participants to purchase tokens. this is useful for putting your KYC / AML whitelist on-chain!
    
*   [`TimedCrowdsale`](api/crowdsale#TimedCrowdsale)
     — adds an [`openingTime`](api/crowdsale#TimedCrowdsale-openingTime--)
     and [`closingTime`](#api:Crowdsale.adoc#TimedCrowdsale-closingTime--)
     to your crowdsale
    

Simply mix and match these crowdsale flavors to your heart’s content:

    contract MyCrowdsale is Crowdsale, CappedCrowdsale, TimedCrowdsale {
    
        constructor(
            uint256 rate,            // rate, in TKNbits
            address payable wallet,  // wallet to send Ether
            IERC20 token,            // the token
            uint256 cap,             // total cap, in wei
            uint256 openingTime,     // opening time in unix epoch seconds
            uint256 closingTime      // closing time in unix epoch seconds
        )
            CappedCrowdsale(cap)
            TimedCrowdsale(openingTime, closingTime)
            Crowdsale(rate, wallet, token)
            public
        {
            // nice, we just created a crowdsale that's only open
            // for a certain amount of time
            // and stops accepting contributions once it reaches `cap`
        }
    }

[](#distribution)
Distribution
------------------------------

There comes a time in every crowdsale’s life where it must relinquish the tokens it’s been entrusted with. It’s your decision as to when that happens!

The default behavior is to release tokens as participants purchase them, but sometimes that may not be desirable. For example, what if we want to give users a refund if we don’t hit a minimum raised in the sale? Or, maybe we want to wait until after the sale is over before users can claim their tokens and start trading them, perhaps for compliance reasons?

OpenZeppelin Contracts is here to make that easy!

### [](#postdeliverycrowdsale)
PostDeliveryCrowdsale

The [`PostDeliveryCrowdsale`](api/crowdsale#PostDeliveryCrowdsale)
, as its name implies, distributes tokens after the crowdsale has finished, letting users call [`withdrawTokens`](api/crowdsale#PostDeliveryCrowdsale-withdrawTokens_address-)
 in order to claim the tokens they’ve purchased.

    contract MyCrowdsale is Crowdsale, TimedCrowdsale, PostDeliveryCrowdsale {
    
        constructor(
            uint256 rate,            // rate, in TKNbits
            address payable wallet,  // wallet to send Ether
            IERC20 token,            // the token
            uint256 openingTime,     // opening time in unix epoch seconds
            uint256 closingTime      // closing time in unix epoch seconds
        )
            PostDeliveryCrowdsale()
            TimedCrowdsale(openingTime, closingTime)
            Crowdsale(rate, wallet, token)
            public
        {
            // nice! this Crowdsale will keep all of the tokens until the end of the crowdsale
            // and then users can `withdrawTokens()` to get the tokens they're owed
        }
    }

### [](#refundablecrowdsale)
RefundableCrowdsale

The [`RefundableCrowdsale`](api/crowdsale#RefundableCrowdsale)
 offers to refund users if a minimum goal is not reached. If the goal is not reached, the users can [`claimRefund`](api/crowdsale#RefundableCrowdsale-claimRefund-address-payable-)
 to get their Ether back.

    contract MyCrowdsale is Crowdsale, RefundableCrowdsale {
    
        constructor(
            uint256 rate,            // rate, in TKNbits
            address payable wallet,  // wallet to send Ether
            IERC20 token,            // the token
            uint256 goal             // the minimum goal, in wei
        )
            RefundableCrowdsale(goal)
            Crowdsale(rate, wallet, token)
            public
        {
            // nice! this crowdsale will, if it doesn't hit `goal`, allow everyone to get their money back
            // by calling claimRefund(...)
        }
    }

[← Creating Supply](/contracts/2.x/erc20-supply)

[ERC721 →](/contracts/2.x/erc721)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: felt252
        ) -> felt252;
    }

[← Interfaces and Dispatchers](/contracts-cairo/0.8.0/interfaces)

[Access Control →](/contracts-cairo/0.8.0/access)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of methods and constants found in `openzeppelin/security/`.

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Initializable](#initializable)
    
*   [Pausable](#pausable)
    
*   [Reentrancy Guard](#reentrancy_guard)
    
*   [SafeMath](#safemath)
    
    *   [SafeUint256](#safeuint256)
        
    

[](#initializable)
Initializable
--------------------------------

The Initializable library provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to setup a contract’s initial state when a constructor cannot be used.

The recommended pattern with Initializable is to include a check that the Initializable state is `False` and invoke `initialize` in the target function like this:

    from openzeppelin.security.initializable.library import Initializable
    
    @external
    func foo{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() {
        let (initialized) = Initializable.initialized();
        assert initialized = FALSE;
    
        Initializable.initialize();
        return ();
    }

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used on one function. |

[](#pausable)
Pausable
----------------------

The Pausable library allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To use the Pausable library, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when not paused, insert `assert_not_paused`. For methods that should be available only when paused, insert `assert_paused`. For example:

    from openzeppelin.security.pausable.library import Pausable
    
    @external
    func whenNotPaused{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        Pausable.assert_not_paused();
    
        // function body
    
        return ();
    }
    
    @external
    func whenPaused{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        Pausable.assert_paused();
    
        // function body
    
        return ();
    }

|     |     |
| --- | --- |
|     | `pause` and `unpause` already include these assertions. In other words, `pause` cannot be invoked when already paused and vice versa. |

For a list of full implementations utilizing the Pausable library, see:

*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [`reentrancy guard`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/security/reentrancyguard/library.cairo)
 library exposes two methods `start` and `end` to protect functions against reentrancy attacks. The protected function must call `ReentrancyGuard.start` before the first function statement, and `ReentrancyGuard.end` before the return statement, as shown below:

    from openzeppelin.security.reentrancyguard.library import ReentrancyGuard
    
    func test_function{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() {
       ReentrancyGuard.start();
    
       // function body
    
       ReentrancyGuard.end();
       return ();
    }

[](#safemath)
SafeMath
----------------------

### [](#safeuint256)
SafeUint256

The SafeUint256 namespace in the [SafeMath library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/security/safemath/library.cairo)
 offers arithmetic for unsigned 256-bit integers (uint256) by leveraging Cairo’s Uint256 library and integrating overflow checks. Some of Cairo’s Uint256 functions do not revert upon overflows. For instance, `uint256_add` will return a bit carry when the sum exceeds 256 bits. This library includes an additional assertion ensuring values do not overflow.

Using SafeUint256 methods is rather straightforward. Simply import SafeUint256 and insert the arithmetic method like this:

    from openzeppelin.security.safemath.library import SafeUint256
    
    func add_two_uints{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        a: Uint256, b: Uint256) -> (c: Uint256) {
        let (c: Uint256) = SafeUint256.add(a, b);
        return (c);
    }

[← ERC721](/contracts-cairo/0.5.0/erc721)

[Introspection →](/contracts-cairo/0.5.0/introspection)




 Introspection - OpenZeppelin Docs       

Introspection
=============

Reference of interfaces and utilities related to [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
.

[](#core)
Core
--------------

### [](#ISRC5)
`ISRC5`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/introspection/interface.cairo#L7)

    use openzeppelin::introspection::interface::ISRC5;

Interface of the SRC5 Introspection Standard as defined in [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
.

[SRC5 ID](#ISRC5)

0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055

Functions

*   [`supports_interface(interface_id)`](#ISRC5-supports_interface)
    

#### [](#ISRC5-Functions)
Functions

#### [](#ISRC5-supports_interface)
`supports_interface(interface_id: felt252) → bool` external

Checks whether the contract implements the given interface.

|     |     |
| --- | --- |
|     | Check [Computing the Interface ID](../introspection#computing_the_interface_id)<br> for more information on how to compute this ID. |

### [](#SRC5Component)
`SRC5Component`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/introspection/src5.cairo)

    use openzeppelin::introspection::src5::SRC5Component;

SRC5 component extending [`ISRC5`](#ISRC5)
.

Embeddable Implementations

SRC5Impl

*   [`supports_interface(self, interface_id)`](#SRC5Component-supports_interface)
    

Internal Implementations

InternalImpl

*   [`register_interface(self, interface_id)`](#SRC5Component-register_interface)
    
*   [`deregister_interface(self, interface_id)`](#SRC5Component-deregister_interface)
    

#### [](#SRC5Component-Embeddable-Functions)
Embeddable Functions

#### [](#SRC5Component-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [`ISRC5::supports_interface`](#ISRC5-supports_interface)
.

#### [](#SRC5Component-Internal-Functions)
Internal Functions

#### [](#SRC5Component-register_interface)
`register_interface(ref self: ComponentState, interface_id: felt252)` internal

Registers support for the given `interface_id`.

#### [](#SRC5Component-deregister_interface)
`deregister_interface(ref self: ComponentState, interface_id: felt252)` internal

Deregisters support for the given `interface_id`.

[← Migrating ERC165 to SRC5](/contracts-cairo/0.8.1/guides/src5-migration)

[Security →](/contracts-cairo/0.8.1/security)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `token::erc20::ERC20` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for Starknet.

|     |     |
| --- | --- |
|     | Prior to [Contracts v0.7.0](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.7.0)<br>, ERC20 contracts store and read `decimals` from storage; however, this implementation returns a static `18`. If upgrading an older ERC20 contract that has a decimals value other than `18`, the upgraded contract **must** use a custom `decimals` implementation. See the [Customizing decimals](#customizing_decimals)<br> guide. |

[](#interface)
Interface
------------------------

The following interface represents the full ABI of the Contracts for Cairo `ERC20` preset. The interface includes the `IERC20` standard interface as well as non-standard functions like `increase_allowance`. To support older deployments of ERC20, as mentioned in [Dual interfaces](interfaces#dual_interfaces)
, `ERC20` also includes the previously defined functions written in camelCase.

    trait ERC20ABI {
        // IERC20
        fn name() -> felt252;
        fn symbol() -> felt252;
        fn decimals() -> u8;
        fn total_supply() -> u256;
        fn balance_of(account: ContractAddress) -> u256;
        fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(spender: ContractAddress, amount: u256) -> bool;
    
        // Non-standard
        fn increase_allowance(spender: ContractAddress, added_value: u256) -> bool;
        fn decrease_allowance(spender: ContractAddress, subtracted_value: u256) -> bool;
    
        // Camel case compatibility
        fn totalSupply() -> u256;
        fn balanceOf(account: ContractAddress) -> u256;
        fn transferFrom(
            sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn increaseAllowance(spender: ContractAddress, addedValue: u256) -> bool;
        fn decreaseAllowance(spender: ContractAddress, subtractedValue: u256) -> bool;
    }

### [](#erc20_compatibility)
ERC20 compatibility

Although Starknet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard. Some notable differences, however, can still be found, such as:

*   Cairo short strings are used to simulate `name` and `symbol` because Cairo does not yet include native string support.
    
*   The contract offers a [dual interface](interfaces#dual_interfaces)
     which supports both snake\_case and camelCase methods, as opposed to just camelCase in Solidity.
    
*   `transfer`, `transfer_from` and `approve` will never return anything different from `true` because they will revert on any error.
    
*   Function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo/blob/7dd34f6c57b7baf5cd5a30c15e00af39cb26f7e1/crates/cairo-lang-starknet/src/contract.rs#L39-L48)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    .
    

[](#usage)
Usage
----------------

|     |     |
| --- | --- |
|     | The following example uses `unsafe_new_contract_state` to access another contract’s state. Although this is useful to use them as modules, it’s considered unsafe because storage members could clash among used contracts if not reviewed carefully. Extensibility will be revisited after [Components](https://community.starknet.io/t/cairo-1-contract-syntax-is-evolving/94794#extensibility-and-components-11)<br> are introduced. |

Using Contracts for Cairo, constructing an ERC20 contract requires setting up the constructor and exposing the ERC20 interface. Here’s what that looks like:

    #[starknet::contract]
    mod MyToken {
        use starknet::ContractAddress;
        use openzeppelin::token::erc20::ERC20;
    
        #[storage]
        struct Storage {}
    
        #[constructor]
        fn constructor(
            self: @ContractState,
            initial_supply: u256,
            recipient: ContractAddress
        ) {
            let name = 'MyToken';
            let symbol = 'MTK';
    
            let mut unsafe_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref unsafe_state, name, symbol);
            ERC20::InternalImpl::_mint(ref unsafe_state, recipient, initial_supply);
        }
    
        #[external(v0)]
        impl MyTokenImpl of IERC20<ContractState> {
            fn name(self: @ContractState) -> felt252 {
                let mut unsafe_state = ERC20::unsafe_new_contract_state();
                ERC20::ERC20Impl::name(@unsafe_state)
            }
    
            (...)
        }
    }

In order for the `MyToken` contract to extend the ERC20 contract, it utilizes the `unsafe_new_contract_state`. The unsafe contract state allows access to ERC20’s implementations. With this access, the constructor first calls the initializer to set the token name and symbol. The constructor then calls `_mint` to create a fixed supply of tokens.

|     |     |
| --- | --- |
|     | For a more complete guide on ERC20 token mechanisms, see [Creating ERC20 Supply](guides/erc20-supply)<br>. |

In the external implementation, notice that `MyTokenImpl` is an implementation of `IERC20`. This ensures that the external implementation will include all of the methods defined in the interface.

### [](#customizing_decimals)
Customizing decimals

Cairo, like Solidity, does not support [floating-point numbers](https://en.wikipedia.org//wiki/Floating-point_arithmetic)
. To get around this limitation, ERC20 offers a `decimals` field which communicates to outside interfaces (wallets, exchanges, etc.) how the token should be displayed. For instance, suppose a token had a `decimals` value of `3` and the total token supply was `1234`. An outside interface would display the token supply as `1.234`. In the actual contract, however, the supply would still be the integer `1234`. In other words, **the decimals field in no way changes the actual arithmetic** because all operations are still performed on integers.

Most contracts use `18` decimals and this was even proposed to be compulsory (see the [EIP discussion](https://github.com/ethereum/EIPs/issues/724)
). The Contracts for Cairo ERC20 implementation of `decimals` returns `18` by default to save on gas fees. For those who want an ERC20 token with a configurable number of decimals, the following guide shows two ways to achieve this.

#### [](#the_static_approach)
The static approach

The simplest way to customize `decimals` consists of returning the target value when exposing the `decimals` method. For example:

    #[external(v0)]
    impl MyTokenImpl of IERC20<ContractState> {
        fn decimals(self: @ContractState) -> u8 {
            // Change the `3` below to the desired number of decimals
            3
        }
    
        (...)
    }

#### [](#the_storage_approach)
The storage approach

For more complex scenarios, such as a factory deploying multiple tokens with differing values for decimals, a flexible solution might be appropriate.

    #[starknet::contract]
    mod MyToken {
        use starknet::ContractAddress;
        use openzeppelin::token::erc20::ERC20;
    
        #[storage]
        struct Storage {
            // The decimals value is stored locally
            _decimals: u8,
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            decimals: u8
        ) {
            // Call the internal function that writes decimals to storage
            self._set_decimals(decimals);
    
            // Initialize ERC20
            let name = 'MyToken';
            let symbol = 'MTK';
    
            let mut unsafe_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref unsafe_state, name, symbol);
        }
    
        /// This is a standalone function for brevity.
        /// It's recommended to create an implementation of IERC20
        /// to ensure that the contract exposes the entire ERC20 interface.
        /// See the previous example.
        #[external(v0)]
        fn decimals(self: @ContractState) -> u8 {
            self._decimals.read()
        }
    
        #[generate_trait]
        impl InternalImpl of InternalTrait {
            fn _set_decimals(ref self: ContractState, decimals: u8) {
                self._decimals.write(decimals);
            }
        }
    }

This contract expects a `decimals` argument in the constructor and uses an internal function to write the decimals to storage. Note that the `_decimals` state variable must be stored in the local contract’s storage because this variable does not exist in the Contracts for Cairo library. It’s important to include the correct logic in the exposed `decimals` method and to NOT use the Contracts for Cairo `decimals` implementation in this specific case. The library’s `decimals` implementation does not read from storage and will return `18`.

[← API Reference](/contracts-cairo/0.8.0-beta.1/api/access)

[Creating Supply →](/contracts-cairo/0.8.0-beta.1/guides/erc20-supply)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

Reference of interfaces and utilities related to upgradeability.

[](#core)
Core
--------------

### [](#IUpgradeable)
`IUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/upgrades/interface.cairo#L3)

    use openzeppelin::upgrades::interface::IUpgradeable;

Interface of an upgradeable contract.

Functions

*   [`upgrade(new_class_hash)`](#IUpgradeable-upgrade)
    

#### [](#IUpgradeable-Functions)
Functions

#### [](#IUpgradeable-upgrade)
`upgrade(new_class_hash: ClassHash)` external

Upgrades the contract code by updating its [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

|     |     |
| --- | --- |
|     | This function is usually protected by an [Access Control](../access)<br> mechanism. |

### [](#Upgradeable)
`Upgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/upgrades/upgradeable.cairo)

    use openzeppelin::upgrades::upgradeable::Upgradeable;

Upgradeable component.

Internal Functions

InternalImpl

*   [`_upgrade(self, new_class_hash)`](#Upgradeable-_upgrade)
    

Events

*   [`Upgraded(class_hash)`](#Upgradeable-Upgraded)
    

#### [](#Upgradeable-Internal-Functions)
Internal Functions

#### [](#Upgradeable-_upgrade)
`_upgrade(ref self: ContractState, new_class_hash: ClassHash)` internal

Upgrades the contract by updating the contract [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

Requirements:

*   `new_class_hash` must be different from zero.
    

Emits an [Upgraded](#Upgradeable-Upgraded)
 event.

#### [](#Upgradeable-Events)
Events

#### [](#Upgradeable-Upgraded)
`Upgraded(class_hash: ClassHash)` event

Emitted when the [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
 is upgraded.

[← Upgrades](/contracts-cairo/0.8.0-beta.0/upgrades)

[Accounts →](/contracts-cairo/0.8.0-beta.0/accounts)




 Introspection - OpenZeppelin Docs       

Introspection
=============

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [ERC165](#erc165)
    
    *   [Interface calculations](#interface_calculations)
        
    *   [Registering interfaces](#registering_interfaces)
        
    *   [Querying interfaces](#querying_interfaces)
        
    *   [IERC165](#ierc165)
        
    *   [IERC165 API Specification](#ierc165_api_specification)
        
        *   [`supportsInterface`](#supportsinterface)
            
        
    *   [ERC165 Library Functions](#erc165_library_functions)
        
        *   [`supports_interface`](#supportsinterface2)
            
        *   [`register_interface`](#register_interface)
            
        
    

[](#erc165)
ERC165
------------------

The ERC165 standard allows smart contracts to exercise [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
 on other contracts, that is, examining which functions can be called on them. This is usually referred to as a contract’s interface.

Cairo contracts, like Ethereum contracts, have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. ERC20 tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract declaring its interface can be very helpful in preventing errors.

It should be noted that the [constants library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 includes constant variables referencing all of the interface ids used in these contracts. This allows for more legible code i.e. using `IERC165_ID` instead of `0x01ffc9a7`.

### [](#interface_calculations)
Interface calculations

In order to ensure EVM/StarkNet compatibility, interface identifiers are not calculated on StarkNet. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, the contract should import the ERC165 library and register its support. It’s recommended to register interface support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    from openzeppelin.introspection.erc165.library import ERC165
    
    INTERFACE_ID = 0x12345678
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        ERC165.register_interface(INTERFACE_ID)
        return ()
    end

### [](#querying_interfaces)
Querying interfaces

To query a target contract’s support for an interface, the querying contract should call `supportsInterface` through IERC165 with the target contract’s address and the queried interface id. Here’s an example:

    from openzeppelin.introspection.erc265.IERC165 import IERC165
    
    INTERFACE_ID = 0x12345678
    
    func check_support{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            target_contract: felt,
        ) -> (success: felt):
        let (is_supported) = IERC165.supportsInterface(target_contract, INTERFACE_ID)
        return (is_supported)
    end

|     |     |
| --- | --- |
|     | `supportsInterface` is camelCased because it is an exposed contract method as part of ERC165’s interface. This differs from library methods (such as `supports_interface` from the [ERC165 library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/introspection/erc165/library.cairo)<br>) which are snake\_cased and not exposed. See the [Function names and coding style](extensibility#function_names_and_coding_style)<br> for more details. |

### [](#ierc165)
IERC165

    @contract_interface
    namespace IERC165:
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#ierc165_api_specification)
IERC165 API Specification

    func supportsInterface(interfaceId: felt) -> (success: felt):
    end

#### [](#supportsinterface)
`supportsInterface`

Returns true if this contract implements the interface defined by `interfaceId`.

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#erc165_library_functions)
ERC165 Library Functions

    func supports_interface(interface_id: felt) -> (success: felt):
    end
    
    func register_interface(interface_id: felt):
    end

#### [](#supportsinterface2)
`supports_interface`

Returns true if this contract implements the interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns:

    success: felt

#### [](#register_interface)
`register_interface`

Calling contract declares support for a specific interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns: None.

[← Security](/contracts-cairo/0.3.1/security)

[Utilities →](/contracts-cairo/0.3.1/utilities)




 Account - OpenZeppelin Docs       

Account
=======

Reference of interfaces, presets, and utilities related to account contracts.

[](#core)
Core
--------------

### [](#ISRC6)
`ISRC6`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/account/interface.cairo)

    use openzeppelin::account::interface::ISRC6;

Interface of the SRC6 Standard Account as defined in the [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
.

[SRC5 ID](introspection#ISRC5)

0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd

Functions

*   [`__execute__(calls)`](#ISRC6-__execute__)
    
*   [`__validate__(calls)`](#ISRC6-__validate__)
    
*   [`is_valid_signature(hash, signature)`](#ISRC6-is_valid_signature)
    

#### [](#ISRC6-Functions)
Functions

#### [](#ISRC6-__execute__)
`__execute__(calls: Array<Call>) → Array<Span<felt252>>` external

Executes the list of calls as a transaction after validation.

Returns an array with each call’s output.

|     |     |
| --- | --- |
|     | The `Call` struct is defined in [corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3)<br>. |

#### [](#ISRC6-__validate__)
`__validate__(calls: Array<Call>) → felt252` external

Validates a transaction before execution.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#ISRC6-is_valid_signature)
`is_valid_signature(hash: felt252, signature: Array<felt252>) → felt252` external

Validates whether a signature is valid or not for the given message hash.

Returns the short string `'VALID'` if valid, otherwise it reverts.

### [](#AccountComponent)
`AccountComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/account/account.cairo)

    use openzeppelin::account::AccountComponent;

Account component implementing [`ISRC6`](#ISRC6)
 for signatures over the [Starknet curve](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/stark-curve/)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

[Embeddable Mixin Implementations](../components#mixins)

AccountMixinImpl

*   [`SRC6Impl`](#AccountComponent-Embeddable-Impls-SRC6Impl)
    
*   [`DeclarerImpl`](#AccountComponent-Embeddable-Impls-DeclarerImpl)
    
*   [`DeployableImpl`](#AccountComponent-Embeddable-Impls-DeployableImpl)
    
*   [`PublicKeyImpl`](#AccountComponent-Embeddable-Impls-PublicKeyImpl)
    
*   [`SRC6CamelOnlyImpl`](#AccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl)
    
*   [`PublicKeyCamelImpl`](#AccountComponent-Embeddable-Impls-PublicKeyCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

SRC6Impl

*   [`__execute__(self, calls)`](#AccountComponent-__execute__)
    
*   [`__validate__(self, calls)`](#AccountComponent-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#AccountComponent-is_valid_signature)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#AccountComponent-__validate_declare__)
    

DeployableImpl

*   [`__validate_deploy__(self, hash, signature)`](#AccountComponent-__validate_deploy__)
    

PublicKeyImpl

*   [`get_public_key(self)`](#AccountComponent-get_public_key)
    
*   [`set_public_key(self, new_public_key, signature)`](#AccountComponent-set_public_key)
    

SRC6CamelOnlyImpl

*   [`isValidSignature(self, hash, signature)`](#AccountComponent-isValidSignature)
    

PublicKeyCamelImpl

*   [`getPublicKey(self)`](#AccountComponent-getPublicKey)
    
*   [`setPublicKey(self, newPublicKey, signature)`](#AccountComponent-setPublicKey)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self, public_key)`](#AccountComponent-initializer)
    
*   [`assert_only_self(self)`](#AccountComponent-assert_only_self)
    
*   [`assert_valid_new_owner(self, current_owner, new_owner, signature)`](#AccountComponent-assert_valid_new_owner)
    
*   [`validate_transaction(self)`](#AccountComponent-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#AccountComponent-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#AccountComponent-_is_valid_signature)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#AccountComponent-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#AccountComponent-OwnerRemoved)
    

#### [](#AccountComponent-Embeddable-Functions)
Embeddable functions

#### [](#AccountComponent-__execute__)
`__execute__(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#AccountComponent-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#AccountComponent-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: felt252) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-get_public_key)
`get_public_key(self: @ContractState) → felt252` external

Returns the current public key of the account.

#### [](#AccountComponent-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: felt252, signature: Span<felt252>)` external

Sets a new public key for the account. Only accessible by the account calling itself through `__execute__`.

Requirements:

*   The caller must be the contract itself.
    
*   The signature must be valid for the new owner.
    

Emits both an [OwnerRemoved](#AccountComponent-OwnerRemoved)
 and an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The message to be signed is computed in Cairo as follows:<br><br>    let message_hash = PoseidonTrait::new()<br>            .update_with('StarkNet Message')<br>            .update_with('accept_ownership')<br>            .update_with(get_contract_address())<br>            .update_with(current_owner)<br>            .finalize(); |

#### [](#AccountComponent-isValidSignature)
`isValidSignature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#AccountComponent-getPublicKey)
`getPublicKey(self: @ContractState) → felt252` external

See [get\_public\_key](#AccountComponent-get_public_key)
.

#### [](#AccountComponent-setPublicKey)
`setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span<felt252>)` external

See [set\_public\_key](#AccountComponent-set_public_key)
.

#### [](#AccountComponent-Internal-Functions)
Internal functions

#### [](#AccountComponent-initializer)
`initializer(ref self: ComponentState, public_key: felt252)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

#### [](#AccountComponent-assert_only_self)
`assert_only_self(self: @ComponentState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#AccountComponent-assert_valid_new_owner)
`assert_valid_new_owner(self: @ComponentState, current_owner: felt252, new_owner: felt252, signature: Span<felt252>)` internal

Validates that `new_owner` accepted the ownership of the contract through a signature.

Requirements:

*   `signature` must be valid for the new owner.
    

|     |     |
| --- | --- |
|     | This function assumes that `current_owner` is the current owner of the contract, and does not validate this assumption. |

#### [](#AccountComponent-validate_transaction)
`validate_transaction(self: @ComponentState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#AccountComponent-_set_public_key)
`_set_public_key(ref self: ComponentState, new_public_key: felt252)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#AccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#AccountComponent-_is_valid_signature)
`_is_valid_signature(self: @ComponentState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account’s current public key.

#### [](#AccountComponent-Events)
Events

#### [](#AccountComponent-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#AccountComponent-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

### [](#EthAccountComponent)
`EthAccountComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/account/eth_account.cairo)

    use openzeppelin::account::eth_account::EthAccountComponent;

Account component implementing [`ISRC6`](#ISRC6)
 for signatures over the [Secp256k1 curve](https://en.bitcoin.it/wiki/Secp256k1)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

|     |     |
| --- | --- |
|     | The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`. |

[Embeddable Mixin Implementations](../components#mixins)

EthAccountMixinImpl

*   [`SRC6Impl`](#EthAccountComponent-Embeddable-Impls-SRC6Impl)
    
*   [`DeclarerImpl`](#EthAccountComponent-Embeddable-Impls-DeclarerImpl)
    
*   [`DeployableImpl`](#EthAccountComponent-Embeddable-Impls-DeployableImpl)
    
*   [`PublicKeyImpl`](#EthAccountComponent-Embeddable-Impls-PublicKeyImpl)
    
*   [`SRC6CamelOnlyImpl`](#EthAccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl)
    
*   [`PublicKeyCamelImpl`](#EthAccountComponent-Embeddable-Impls-PublicKeyCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

SRC6Impl

*   [`__execute__(self, calls)`](#EthAccountComponent-__execute__)
    
*   [`__validate__(self, calls)`](#EthAccountComponent-__validate__)
    
*   [`is_valid_signature(self, hash, signature)`](#EthAccountComponent-is_valid_signature)
    

DeclarerImpl

*   [`__validate_declare__(self, class_hash)`](#EthAccountComponent-__validate_declare__)
    

DeployableImpl

*   [`__validate_deploy__(self, hash, signature)`](#EthAccountComponent-__validate_deploy__)
    

PublicKeyImpl

*   [`get_public_key(self)`](#EthAccountComponent-get_public_key)
    
*   [`set_public_key(self, new_public_key, signature)`](#EthAccountComponent-set_public_key)
    

SRC6CamelOnlyImpl

*   [`isValidSignature(self, hash, signature)`](#EthAccountComponent-isValidSignature)
    

PublicKeyCamelImpl

*   [`getPublicKey(self)`](#EthAccountComponent-getPublicKey)
    
*   [`setPublicKey(self, newPublicKey, signature)`](#EthAccountComponent-setPublicKey)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self, public_key)`](#EthAccountComponent-initializer)
    
*   [`assert_only_self(self)`](#EthAccountComponent-assert_only_self)
    
*   [`assert_valid_new_owner(self, current_owner, new_owner, signature)`](#EthAccountComponent-assert_valid_new_owner)
    
*   [`validate_transaction(self)`](#EthAccountComponent-validate_transaction)
    
*   [`_set_public_key(self, new_public_key)`](#EthAccountComponent-_set_public_key)
    
*   [`_is_valid_signature(self, hash, signature)`](#EthAccountComponent-_is_valid_signature)
    

Events

*   [`OwnerAdded(new_owner_guid)`](#EthAccountComponent-OwnerAdded)
    
*   [`OwnerRemoved(removed_owner_guid)`](#EthAccountComponent-OwnerRemoved)
    

#### [](#EthAccountComponent-Embeddable-Functions)
Embeddable functions

#### [](#EthAccountComponent-__execute__)
`__execute__(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>` external

See [ISRC6::\_\_execute\_\_](#ISRC6-__execute__)
.

#### [](#EthAccountComponent-__validate__)
`__validate__(self: @ContractState, calls: Array<Call>) → felt252` external

See [ISRC6::\_\_validate\_\_](#ISRC6-__validate__)
.

#### [](#EthAccountComponent-is_valid_signature)
`is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#EthAccountComponent-__validate_declare__)
`__validate_declare__(self: @ContractState, class_hash: felt252) → felt252` external

Validates a [`Declare` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#declare-transaction)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#EthAccountComponent-__validate_deploy__)
`__validate_deploy__(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: EthPublicKey) → felt252` external

Validates a [`DeployAccount` transaction](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#deploy_account_transaction)
. See [Counterfactual Deployments](../guides/deployment)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#EthAccountComponent-get_public_key)
`get_public_key(self: @ContractState) → EthPublicKey` external

Returns the current public key of the account.

#### [](#EthAccountComponent-set_public_key)
`set_public_key(ref self: ContractState, new_public_key: EthPublicKey, signature: Span<felt252>)` external

Sets a new public key for the account. Only accessible by the account calling itself through `__execute__`.

Requirements:

*   The caller must be the contract itself.
    
*   The signature must be valid for the new owner.
    

Emits both an [OwnerRemoved](#EthAccountComponent-OwnerRemoved)
 and an [OwnerAdded](#EthAccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The message to be signed is computed in Cairo as follows:<br><br>    let message_hash = PoseidonTrait::new()<br>            .update_with('StarkNet Message')<br>            .update_with('accept_ownership')<br>            .update_with(get_contract_address())<br>            .update_with(current_owner.get_coordinates().unwrap_syscall())<br>            .finalize(); |

#### [](#EthAccountComponent-isValidSignature)
`isValidSignature(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252` external

See [ISRC6::is\_valid\_signature](#ISRC6-is_valid_signature)
.

#### [](#EthAccountComponent-getPublicKey)
`getPublicKey(self: @ContractState) → EthPublicKey` external

See [get\_public\_key](#EthAccountComponent-get_public_key)
.

#### [](#EthAccountComponent-setPublicKey)
`setPublicKey(ref self: ContractState, newPublicKey: EthPublicKey, signature: Span<felt252>)` external

See [set\_public\_key](#EthAccountComponent-set_public_key)
.

#### [](#EthAccountComponent-Internal-Functions)
Internal functions

#### [](#EthAccountComponent-initializer)
`initializer(ref self: ComponentState, public_key: EthPublicKey)` internal

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an [OwnerAdded](#EthAccountComponent-OwnerAdded)
 event.

#### [](#EthAccountComponent-assert_only_self)
`assert_only_self(self: @ComponentState)` internal

Validates that the caller is the account itself. Otherwise it reverts.

#### [](#EthAccountComponent-assert_valid_new_owner)
`assert_valid_new_owner(self: @ComponentState, current_owner: EthPublicKey, new_owner: EthPublicKey, signature: Span<felt252>)` internal

Validates that `new_owner` accepted the ownership of the contract through a signature.

Requirements:

*   The signature must be valid for the `new_owner`.
    

|     |     |
| --- | --- |
|     | This function assumes that `current_owner` is the current owner of the contract, and does not validate this assumption. |

#### [](#EthAccountComponent-validate_transaction)
`validate_transaction(self: @ComponentState) → felt252` internal

Validates a transaction signature from the [global context](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61)
.

Returns the short string `'VALID'` if valid, otherwise it reverts.

#### [](#EthAccountComponent-_set_public_key)
`_set_public_key(ref self: ComponentState, new_public_key: EthPublicKey)` internal

Set the public key without validating the caller.

Emits an [OwnerAdded](#EthAccountComponent-OwnerAdded)
 event.

|     |     |
| --- | --- |
|     | The usage of this method outside the `set_public_key` function is discouraged. |

#### [](#EthAccountComponent-_is_valid_signature)
`_is_valid_signature(self: @ComponentState, hash: felt252, signature: Span<felt252>) → bool` internal

Validates the provided `signature` for the `hash`, using the account’s current public key.

#### [](#EthAccountComponent-Events)
Events

|     |     |
| --- | --- |
|     | The `guid` is computed as the hash of the public key, using the poseidon hash function. |

#### [](#EthAccountComponent-OwnerAdded)
`OwnerAdded(new_owner_guid: felt252)` event

Emitted when a `public_key` is added.

#### [](#EthAccountComponent-OwnerRemoved)
`OwnerRemoved(removed_owner_guid: felt252)` event

Emitted when a `public_key` is removed.

[](#presets)
Presets
--------------------

### [](#AccountUpgradeable)
`AccountUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/presets/account.cairo)

    use openzeppelin::presets::AccountUpgradeable;

Upgradeable account contract leveraging [AccountComponent](#AccountComponent)
.

[Sierra class hash](../presets)

0x00e2eb8f5672af4e6a4e8a8f1b44989685e668489b0a25437733756c5a34a1d6

Constructor

*   [`constructor(self, public_key)`](#AccountUpgradeable-constructor)
    

Embedded Implementations

AccountComponent

*   [`AccountMixinImpl`](#AccountComponent-Embeddable-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#AccountUpgradeable-upgrade)
    

#### [](#AccountUpgradeable-constructor-section)
Constructor

#### [](#AccountUpgradeable-constructor)
`constructor(ref self: ContractState, public_key: felt252)` constructor

Sets the account `public_key` and registers the interfaces the contract supports.

#### [](#AccountUpgradeable-external-functions)
External functions

#### [](#AccountUpgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the account contract itself.
    
*   `new_class_hash` cannot be zero.
    

### [](#EthAccountUpgradeable)
`EthAccountUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/presets/eth_account.cairo)

    use openzeppelin::presets::EthAccountUpgradeable;

Upgradeable account contract leveraging [EthAccountComponent](#EthAccountComponent)
.

|     |     |
| --- | --- |
|     | The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`. |

[Sierra class hash](../presets)

0x0169e64bc8a60422da86e6cc821c498d2f8cba60888399ce4be86690aaa51e4a

Constructor

*   [`constructor(self, public_key)`](#EthAccountUpgradeable-constructor)
    

Embedded Implementations

EthAccountComponent

*   [`EthAccountMixinImpl`](#EthAccountComponent-Embeddable-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#EthAccountUpgradeable-upgrade)
    

#### [](#EthAccountUpgradeable-constructor-section)
Constructor

#### [](#EthAccountUpgradeable-constructor)
`constructor(ref self: ContractState, public_key: EthPublicKey)` constructor

Sets the account `public_key` and registers the interfaces the contract supports.

#### [](#EthAccountUpgradeable-external-functions)
External functions

#### [](#EthAccountUpgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the account contract itself.
    
*   `new_class_hash` cannot be zero.
    

[← Accounts](/contracts-cairo/0.13.0/accounts)

[Governance →](/contracts-cairo/0.13.0/api/governance)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are directly derived from a private key, there’s no native account concept on StarkNet.

Instead, signature validation has to be done at the contract level. To relieve smart contract applications such as ERC20 tokens or exchanges from this responsibility, we make use of Account contracts to deal with transaction authentication.

For a general overview of the account abstraction, see StarkWare’s [StarkNet Alpha 0.10](https://medium.com/starkware/starknet-alpha-0-10-0-923007290470)
. A more detailed discussion on the topic can be found in [StarkNet Account Abstraction Part 1](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Account entrypoints](#account_entrypoints)
    
*   [Standard interface](#standard_interface)
    
*   [Keys, signatures and signers](#keys_signatures_and_signers)
    
    *   [Signature validation](#signature_validation)
        
    *   [Signer](#signer)
        
    *   [MockSigner utility](#mocksigner_utility)
        
    *   [MockEthSigner utility](#mockethsigner_utility)
        
    
*   [Call and AccountCallArray format](#call_and_accountcallarray_format)
    
    *   [Call](#call)
        
    *   [AccountCallArray](#accountcallarray)
        
    
*   [Multicall transactions](#multicall_transactions)
    
*   [API Specification](#api_specification)
    
    *   [`constructor`](#constructor)
        
    *   [`getPublicKey`](#getpublickey)
        
    *   [`supportsInterface`](#supportsinterface)
        
    *   [`setPublicKey`](#setpublickey)
        
    *   [`isValidSignature`](#isvalidsignature)
        
    *   [`__validate__`](#validate)
        
    *   [`__validate_declare__`](#validate_declare)
        
    *   [`__execute__`](#execute)
        
    
*   [Presets](#presets)
    
    *   [Account](#account)
        
    *   [Eth Account](#eth_account)
        
    
*   [Account differentiation with ERC165](#account_differentiation_with_erc165)
    
*   [Extending the Account contract](#extending_the_account_contract)
    
*   [L1 escape hatch mechanism](#l1_escape_hatch_mechanism)
    
*   [Paying for gas](#paying_for_gas)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Account contract is deployed to StarkNet.
    
2.  Signed transactions can now be sent to the Account contract which validates and executes them.
    

In Python, this would look as follows:

    from starkware.starknet.testing.starknet import Starknet
    from utils import get_contract_class
    from signers import MockSigner
    
    signer = MockSigner(123456789987654321)
    
    starknet = await Starknet.empty()
    
    # 1. Deploy Account
    account = await starknet.deploy(
        get_contract_class("Account"),
        constructor_calldata=[signer.public_key]
    )
    
    # 2. Send transaction through Account
    await signer.send_transaction(account, some_contract_address, 'some_function', [some_parameter])

[](#account_entrypoints)
Account entrypoints
--------------------------------------------

Account contracts contain three entry points for all user interactions with any contract.

1.  [`__validate_declare__`](#validate_declare)
     validates the declaration signature prior to the declaration. As of Cairo v0.10.0, contract classes should be declared from an Account contract.
    
2.  [`__validate__`](#validate)
     verifies the transaction signature before executing the transaction with `__execute__`.
    
3.  [`__execute__`](#execute)
     acts as the state-changing entry point for all user interaction with any contract, including managing the account contract itself. That’s why if you want to change the public key controlling the Account, you would send a transaction targeting the very Account contract:
    

    await signer.send_transaction(
        account,
        account.contract_address,
        'set_public_key',
        [NEW_KEY]
    )

Or if you want to update the Account’s L1 address on the `AccountRegistry` contract, you would

    await signer.send_transaction(account, registry.contract_address, 'set_L1_address', [NEW_ADDRESS])

You can read more about how messages are structured and hashed in the [Account message scheme discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/24)
. For more information on the design choices and implementation of multicall, you can read the [How should Account multicall work discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/27)
.

The `__validate__` and `__execute__` methods accept the same arguments; however, `__execute__` returns a transaction response:

    func __validate__(
        call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*) {
    }
    
    func __execute__(
        call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
    ) -> (response_len: felt, response: felt*) {
    }

Where:

*   `call_array_len` is the number of calls.
    
*   `call_array` is an array representing each `Call`.
    
*   `calldata_len` is the number of calldata parameters.
    
*   `calldata` is an array representing the function parameters.
    

|     |     |
| --- | --- |
|     | The scheme of building multicall transactions within the `__execute__` method will change once StarkNet allows for pointers in struct arrays. In which case, multiple transactions can be passed to (as opposed to built within) `__execute__`. |

[](#standard_interface)
Standard interface
------------------------------------------

The [`IAccount.cairo`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/account/IAccount.cairo)
 contract interface contains the standard account interface proposed in [#41](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and adopted by OpenZeppelin and Argent. It implements [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and it is agnostic of signature validation. Further, nonce management is handled on the protocol level.

    struct Call {
        to: felt,
        selector: felt,
        calldata_len: felt,
        calldata: felt*,
    }
    
    // Tmp struct introduced while we wait for Cairo to support passing `[Call]` to __execute__
    struct CallArray {
        to: felt,
        selector: felt,
        data_offset: felt,
        data_len: felt,
    }
    
    
    @contract_interface
    namespace IAccount {
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    
        func isValidSignature(hash: felt, signature_len: felt, signature: felt*) -> (isValid: felt) {
        }
    
        func __validate__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) {
        }
    
        func __validate_declare__(class_hash: felt) {
        }
    
        func __execute__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
        }
    }

[](#keys_signatures_and_signers)
Keys, signatures and signers
-------------------------------------------------------------

While the interface is agnostic of signature validation schemes, this implementation assumes there’s a public-private key pair controlling the Account. That’s why the `constructor` function expects a `public_key` parameter to set it. Since there’s also a `setPublicKey()` method, accounts can be effectively transferred.

### [](#signature_validation)
Signature validation

Signature validation occurs separately from execution as of Cairo v0.10. Upon receiving transactions, an account contract first calls `__validate__`. An account will only execute a transaction if, and only if, the signature proves valid. This decoupling allows for a protocol-level distinction between invalid and reverted transactions. See [Account entrypoints](#account_entrypoints)
.

### [](#signer)
Signer

The signer is responsible for creating a transaction signature with the user’s private key for a given transaction. This implementation utilizes [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 class to create transaction signatures through the `Signer` method `sign_transaction`.

`sign_transaction` expects the following parameters per transaction:

*   `sender` the contract address invoking the tx.
    
*   `calls` a list containing a sublist of each call to be sent. Each sublist must consist of:
    
    1.  `to` the address of the target contract of the message.
        
    2.  `selector` the function to be called on the target contract.
        
    3.  `calldata` the parameters for the given `selector`.
        
    
*   `nonce` an unique identifier of this message to prevent transaction replays.
    
*   `max_fee` the maximum fee a user will pay.
    

Which returns:

*   `calldata` a list of arguments for each call.
    
*   `sig_r` the transaction signature.
    
*   `sig_s` the transaction signature.
    

While the `Signer` class performs much of the work for a transaction to be sent, it neither manages nonces nor invokes the actual transaction on the Account contract. To simplify Account management, most of this is abstracted away with `MockSigner`.

### [](#mocksigner_utility)
MockSigner utility

The `MockSigner` class in [signers.py](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/tests/signers.py)
 is used to perform transactions on a given Account, crafting the transaction and managing nonces.

The flow of a transaction starts with checking the nonce and converting the `to` contract address of each call to hexadecimal format. The hexadecimal conversion is necessary because Nile’s `Signer` converts the address to a base-16 integer (which requires a string argument). Note that directly converting `to` to a string will ultimately result in an integer exceeding Cairo’s `FIELD_PRIME`.

The values included in the transaction are passed to the `sign_transaction` method of Nile’s `Signer` which creates and returns a signature. Finally, the `MockSigner` instance invokes the account contract’s `__execute__` with the transaction data.

|     |     |
| --- | --- |
|     | StarkNet’s testing framework does not currently support transaction invocations from account contracts. `MockSigner` therefore utilizes StarkNet’s API gateway to manually execute the `InvokeFunction` for testing. |

Users only need to interact with the following exposed methods to perform a transaction:

*   `send_transaction(account, to, selector_name, calldata, nonce=None, max_fee=0)` returns a future of a signed transaction, ready to be sent.
    
*   `send_transactions(account, calls, nonce=None, max_fee=0)` returns a future of batched signed transactions, ready to be sent.
    

To use `MockSigner`, pass a private key when instantiating the class:

    from utils import MockSigner
    
    PRIVATE_KEY = 123456789987654321
    signer = MockSigner(PRIVATE_KEY)

Then send single transactions with the `send_transaction` method.

    await signer.send_transaction(account, contract_address, 'method_name', [])

If utilizing multicall, send multiple transactions with the `send_transactions` method.

    await signer.send_transactions(
        account,
        [\
            (contract_address, 'method_name', [param1, param2]),\
            (contract_address, 'another_method', [])\
        ]
    )

### [](#mockethsigner_utility)
MockEthSigner utility

The `MockEthSigner` class in [signers.py](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/tests/signers.py)
 is used to perform transactions on a given Account with a secp256k1 curve key pair, crafting the transaction and managing nonces. It differs from the `MockSigner` implementation by:

*   Not using the public key but its derived address instead (the last 20 bytes of the keccak256 hash of the public key and adding `0x` to the beginning).
    
*   Signing the message with a secp256k1 curve address.
    

[](#call_and_accountcallarray_format)
`Call` and `AccountCallArray` format
--------------------------------------------------------------------------

The idea is for all user intent to be encoded into a `Call` representing a smart contract call. Users can also pack multiple messages into a single transaction (creating a multicall transaction). Cairo currently does not support arrays of structs with pointers which means the `__execute__` function cannot properly iterate through multiple `Call`s. Instead, this implementation utilizes a workaround with the `AccountCallArray` struct. See [Multicall transactions](#multicall_transactions)
.

### [](#call)
`Call`

A single `Call` is structured as follows:

    struct Call {
        to: felt
        selector: felt
        calldata_len: felt
        calldata: felt*
    }

Where:

*   `to` is the address of the target contract of the message.
    
*   `selector` is the selector of the function to be called on the target contract.
    
*   `calldata_len` is the number of calldata parameters.
    
*   `calldata` is an array representing the function parameters.
    

### [](#accountcallarray)
`AccountCallArray`

`AccountCallArray` is structured as:

    struct AccountCallArray {
        to: felt
        selector: felt
        data_offset: felt
        data_len: felt
    }

Where:

*   `to` is the address of the target contract of the message.
    
*   `selector` is the selector of the function to be called on the target contract.
    
*   `data_offset` is the starting position of the calldata array that holds the `Call`'s calldata.
    
*   `data_len` is the number of calldata elements in the `Call`.
    

[](#multicall_transactions)
Multicall transactions
--------------------------------------------------

A multicall transaction packs the `to`, `selector`, `calldata_offset`, and `calldata_len` of each call into the `AccountCallArray` struct and keeps the cumulative calldata for every call in a separate array. The `__execute__` function rebuilds each message by combining the `AccountCallArray` with its calldata (demarcated by the offset and calldata length specified for that particular call). The rebuilding logic is set in the internal `_from_call_array_to_call`.

This is the basic flow:

First, the user sends the messages for the transaction through a Signer instantiation which looks like this:

    await signer.send_transaction(
        account, [\
            (contract_address, 'contract_method', [arg_1]),\
            (contract_address, 'another_method', [arg_1, arg_2])\
        ]
    )

Then the `from_call_to_call_array` method in [Nile’s signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 converts each call into the `AccountCallArray` format and cumulatively stores the calldata of every call into a single array. Next, both arrays (as well as the `sender`, `nonce`, and `max_fee`) are used to create the transaction hash. The Signer then invokes `__execute__` with the signature and passes `AccountCallArray`, calldata, and nonce as arguments.

Finally, the `__execute__` method takes the `AccountCallArray` and calldata and builds an array of `Call`s (MultiCall).

|     |     |
| --- | --- |
|     | Every transaction utilizes `AccountCallArray`. A single `Call` is treated as a bundle with one message. |

[](#api_specification)
API Specification
----------------------------------------

This in a nutshell is the Account contract public API:

    namespace Account {
        func constructor(publicKey: felt) {
        }
    
        func getPublicKey() -> (publicKey: felt) {
        }
    
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    
        func setPublicKey(newPublicKey: felt) {
        }
    
        func isValidSignature(hash: felt, signature_len: felt, signature: felt*) -> (isValid: felt) {
        }
    
        func __validate__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
        }
    
        func __validate_declare__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
        }
    
        func __execute__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
    }

### [](#constructor)
`constructor`

Initializes and sets the public key for the Account contract.

Parameters:

    publicKey: felt

Returns: None.

### [](#getpublickey)
`getPublicKey`

Returns the public key associated with the Account.

Parameters: None.

Returns:

    publicKey: felt

### [](#supportsinterface)
`supportsInterface`

Returns `TRUE` if this contract implements the interface defined by `interfaceId`. Account contracts now implement ERC165 through static support (see [Account differentiation with ERC165](#account_differentiation_with_erc165)
).

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#setpublickey)
`setPublicKey`

Sets the public key that will control this Account. It can be used to rotate keys for security, change them in case of compromised keys or even transferring ownership of the account.

Parameters:

    newPublicKey: felt

Returns: None.

### [](#isvalidsignature)
`isValidSignature`

This function is inspired by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and returns `TRUE` if a given signature is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    hash: felt
    signature_len: felt
    signature: felt*

Returns:

    isValid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#validate)
`__validate__`

Validates the transaction signature and is called prior to `__execute__`.

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*

Returns: None.

### [](#validate_declare)
`__validate_declare__`

Validates the signature for declaration transactions.

Parameters:

    class_hash: felt

Returns: None.

### [](#execute)
`__execute__`

This is the only external entrypoint to interact with the Account contract. It:

1.  Calls the target contract with the intended function selector and calldata parameters.
    
2.  Forwards the contract call response data as return value.
    

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*

|     |     |
| --- | --- |
|     | The current signature scheme expects a 2-element array like `[sig_r, sig_s]`. |

Returns:

    response_len: felt
    response: felt*

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset differs on the signature type being used by the Account.

### [](#account)
Account

The [`Account`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/account/presets/Account.cairo)
 preset uses StarkNet keys to validate transactions.

### [](#eth_account)
Eth Account

The [`EthAccount`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/account/presets/EthAccount.cairo)
 preset supports Ethereum addresses, validating transactions with secp256k1 keys.

[](#account_differentiation_with_erc165)
Account differentiation with ERC165
----------------------------------------------------------------------------

Certain contracts like ERC721 require a means to differentiate between account contracts and non-account contracts. For a contract to declare itself as an account, it should implement [ERC165](https://eips.ethereum.org/EIPS/eip-165)
 as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. To be in compliance with ERC165 specifications, the idea is to calculate the XOR of `IAccount`'s EVM selectors (not StarkNet selectors). The resulting magic value of `IAccount` is 0x50b70dcb.

Our ERC165 integration on StarkNet is inspired by OpenZeppelin’s Solidity implementation of [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
 which stores the interfaces that the implementing contract supports. In the case of account contracts, querying `supportsInterface` of an account’s address with the `IAccount` magic value should return `TRUE`.

|     |     |
| --- | --- |
|     | For Account contracts, ERC165 support is static and does not require Account contracts to register. |

[](#extending_the_account_contract)
Extending the Account contract
------------------------------------------------------------------

Account contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
.

To implement custom account contracts, it’s required by the StarkNet compiler that they include the three entrypoint functions `__validate__`, `__validate_declare__`, and `__execute__`.

`__validate__` and `__validate_declare__` should include the same signature validation method; whereas, `__execute__` should only handle the actual transaction. Incorporating a new validation scheme necessitates only that it’s invoked by both `__validate__` and `__validate_declare__`.

This is why the Account library comes with different flavors of signature validation methods like `is_valid_eth_signature` and the vanilla `is_valid_signature`.

Account contract developers are encouraged to implement the [standard Account interface](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and incorporate the custom logic thereafter.

|     |     |
| --- | --- |
|     | Due to current inconsistencies between the testing framework and the actual StarkNet network, extreme caution should be used when integrating new Account contracts. Instances have occurred where account functionality tests pass and transactions execute correctly on the local node; yet, they fail on public networks. For this reason, it’s highly encouraged that new account contracts are also deployed and tested on the public testnet. See [issue #386](https://github.com/OpenZeppelin/cairo-contracts/issues/386)<br> for more information. |

Some other validation schemes to look out for in the future:

*   Multisig.
    
*   Guardian logic like in [Argent’s account](https://github.com/argentlabs/argent-contracts-starknet/blob/de5654555309fa76160ba3d7393d32d2b12e7349/contracts/ArgentAccount.cairo)
    .
    

[](#l1_escape_hatch_mechanism)
L1 escape hatch mechanism
--------------------------------------------------------

[](#paying_for_gas)
Paying for gas
----------------------------------

[← Proxies and Upgrades](/contracts-cairo/0.5.0/proxies)

[Access Control →](/contracts-cairo/0.5.0/access)




 Proxies - OpenZeppelin Docs       

Proxies
=======

|     |     |
| --- | --- |
|     | Expect rapid iteration as this pattern matures and more patterns potentially emerge. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Solidity/Cairo upgrades comparison](#soliditycairo_upgrades_comparison)
    
    *   [Constructors](#constructors)
        
    *   [Storage](#storage)
        
    
*   [Proxies](#proxies2)
    
    *   [Proxy contract](#proxy_contract)
        
    *   [Implementation contract](#implementation_contract)
        
    
*   [Upgrades library API](#upgrades_library_api)
    
    *   [Methods](#methods)
        
    *   [Events](#events)
        
    
*   [Using proxies](#using_proxies)
    
    *   [Contract upgrades](#contract_upgrades)
        
    *   [Declaring contracts](#declaring_contracts)
        
    *   [Testing method calls](#testing_method_calls)
        
    
*   [Presets](#presets)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Declare an implementation [contract class](https://starknet.io/docs/hello_starknet/intro.html#declare-the-contract-on-the-starknet-testnet)
    .
    
2.  Deploy proxy contract with the implementation contract’s class hash, and the inputs describing the call to initialize the proxy from the implementation (if required). This will redirect the call as a library\_call to the implementation (similar to Solidity delegatecall).
    

In Python, this would look as follows:

    # declare implementation contract
    IMPLEMENTATION = await starknet.declare(
        "path/to/implementation.cairo",
    )
    
    # deploy proxy
    selector = get_selector_from_name('initializer')
    params = [\
        proxy_admin   # admin account\
    ]
    PROXY = await starknet.deploy(
        "path/to/proxy.cairo",
        constructor_calldata=[\
            IMPLEMENTATION.class_hash,  # set implementation contract class hash\
            selector,                   # initializer function selector\
            len(params),                # calldata length in felt\
            *params                     # actual calldata\
        ]
    )

[](#soliditycairo_upgrades_comparison)
Solidity/Cairo upgrades comparison
-------------------------------------------------------------------------

### [](#constructors)
Constructors

OpenZeppelin Contracts for Solidity requires the use of an alternative library for upgradeable contracts. Consider that in Solidity constructors are not part of the deployed contract’s runtime bytecode; rather, a constructor’s logic is executed only once when the contract instance is deployed and then discarded. This is why proxies can’t imitate the construction of its implementation, therefore requiring a different initialization mechanism.

The constructor problem in upgradeable contracts is resolved by the use of initializer methods. Initializer methods are essentially regular methods that execute the logic that would have been in the constructor. Care needs to be exercised with initializers to ensure they can only be called once. Thus, OpenZeppelin offers an [upgradeable contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
 where much of this process is abstracted away. See OpenZeppelin’s [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)
 for more info.

The Cairo programming language does not support inheritance. Instead, Cairo contracts follow the [Extensibility Pattern](extensibility)
 which already uses initializer methods to mimic constructors. Upgradeable contracts do not, therefore, require a separate library with refactored constructor logic.

### [](#storage)
Storage

OpenZeppelin’s alternative Upgrades library also implements [unstructured storage](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies)
 for its upgradeable contracts. The basic idea behind unstructured storage is to pseudo-randomize the storage structure of the upgradeable contract so it’s based on variable names instead of declaration order, which makes the chances of storage collision during an upgrade extremely unlikely.

The StarkNet compiler, meanwhile, already creates pseudo-random storage addresses by hashing the storage variable names (and keys in mappings) by default. In other words, StarkNet already uses unstructured storage and does not need a second library to modify how storage is set. See StarkNet’s [Contracts Storage documentation](https://starknet.io/documentation/contracts/#contracts_storage)
 for more information.

[](#proxies2)
Proxies
---------------------

A proxy contract is a contract that delegates function calls to another contract. This type of pattern decouples state and logic. Proxy contracts store the state and redirect function calls to an implementation contract that handles the logic. This allows for different patterns such as upgrades, where implementation contracts can change but the proxy contract (and thus the state) does not; as well as deploying multiple proxy instances pointing to the same implementation. This can be useful to deploy many contracts with identical logic but unique initialization data.

In the case of contract upgrades, it is achieved by simply changing the proxy’s reference to the class hash of the declared implementation. This allows developers to add features, update logic, and fix bugs without touching the state or the contract address to interact with the application.

### [](#proxy_contract)
Proxy contract

The [Proxy contract](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/upgrades/presets/Proxy.cairo)
 includes two core methods:

1.  The `__default__` method is a fallback method that redirects a function call and associated calldata to the implementation contract.
    
2.  The `__l1_default__` method is also a fallback method; however, it redirects the function call and associated calldata to a layer one contract. In order to invoke `__l1_default__`, the original function call must include the library function `send_message_to_l1`. See Cairo’s [Interacting with L1 contracts](https://www.cairo-lang.org/docs/hello_starknet/l1l2.html)
     for more information.
    

Since this proxy is designed to work both as an [UUPS-flavored upgrade proxy](https://eips.ethereum.org/EIPS/eip-1822)
 as well as a non-upgradeable proxy, it does not know how to handle its own state. Therefore it requires the implementation contract class to be declared beforehand, so its class hash can be passed to the Proxy on construction time.

When interacting with the contract, function calls should be sent by the user to the proxy. The proxy’s fallback function redirects the function call to the implementation contract to execute.

### [](#implementation_contract)
Implementation contract

The implementation contract, also known as the logic contract, receives the redirected function calls from the proxy contract. The implementation contract should follow the [Extensibility pattern](extensibility#the_pattern)
 and import directly from the [Proxy library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/upgrades/library.cairo)
.

The implementation contract should:

*   Import `Proxy` namespace.
    
*   Provide an external initializer function (calling `Proxy.initializer`) to intialize the proxy immediately after deployment.
    

If the implementation is upgradeable, it should:

*   Include a method to upgrade the implementation (i.e. `upgrade`).
    
*   Use access control to protect the contract’s upgradeability.
    

The implementation contract should NOT:

*   Be deployed like a regular contract. Instead, the implementation contract should be declared (which creates a `DeclaredClass` containing its hash and abi).
    
*   Set its initial state with a traditional constructor (decorated with `@constructor`). Instead, use an initializer method that invokes the Proxy `constructor`.
    

|     |     |
| --- | --- |
|     | The Proxy `constructor` includes a check that ensures the initializer can only be called once; however, `_set_implementation` does not include this check. It’s up to the developers to protect their implementation contract’s upgradeability with access controls such as [`assert_only_admin`](#assert_only_admin)<br>. |

For a full implementation contract example, please see:

*   [Proxiable implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ProxiableImplementation.cairo)
    

[](#upgrades_library_api)
Upgrades library API
----------------------------------------------

### [](#methods)
Methods

    func initializer(proxy_admin: felt) {
    }
    
    func assert_only_admin() {
    }
    
    func get_implementation_hash() -> (implementation: felt) {
    }
    
    func get_admin() -> (admin: felt) {
    }
    
    func _set_admin(new_admin: felt) {
    }
    
    func _set_implementation_hash(new_implementation: felt) {
    }

#### [](#initializer)
`initializer`

Initializes the proxy contract with an initial implementation.

Parameters:

    proxy_admin: felt

Returns: None.

#### [](#assert_only_admin)
`assert_only_admin`

Reverts if called by any account other than the admin.

Parameters: None.

Returns: None.

#### [](#get_implementation)
`get_implementation`

Returns the current implementation hash.

Parameters: None.

Returns:

    implementation: felt

#### [](#get_admin)
`get_admin`

Returns the current admin.

Parameters: None.

Returns:

    admin: felt

#### [](#set_admin)
`_set_admin`

Sets `new_admin` as the admin of the proxy contract.

Parameters:

    new_admin: felt

Returns: None.

#### [](#set_implementation_hash)
`_set_implementation_hash`

Sets `new_implementation` as the implementation’s contract class. This method is included in the proxy contract’s constructor and can be used to upgrade contracts.

Parameters:

    new_implementation: felt

Returns: None.

### [](#events)
Events

    func Upgraded(implementation: felt) {
    }
    
    func AdminChanged(previousAdmin: felt, newAdmin: felt) {
    }

#### [](#upgraded)
`Upgraded`

Emitted when a proxy contract sets a new implementation class hash.

Parameters:

    implementation: felt

#### [](#adminchanged)
`AdminChanged`

Emitted when the `admin` changes from `previousAdmin` to `newAdmin`.

Parameters:

    previousAdmin: felt
    newAdmin: felt

[](#using_proxies)
Using proxies
--------------------------------

### [](#contract_upgrades)
Contract upgrades

To upgrade a contract, the implementation contract should include an `upgrade` method that, when called, changes the reference to a new deployed contract like this:

    # declare first implementation
    IMPLEMENTATION = await starknet.declare(
        "path/to/implementation.cairo",
    )
    
    # deploy proxy
    PROXY = await starknet.deploy(
        "path/to/proxy.cairo",
        constructor_calldata=[\
            IMPLEMENTATION.class_hash,  # set implementation hash\
            0,                          # selector set to 0 ignores initialization\
            0,                          # calldata length in felt\
            *[]                         # empty calldata\
        ]
    )
    
    # declare implementation v2
    IMPLEMENTATION_V2 = await starknet.declare(
        "path/to/implementation_v2.cairo",
    )
    
    # call upgrade with the new implementation contract class hash
    await signer.send_transaction(
        account, PROXY.contract_address, 'upgrade', [\
            IMPLEMENTATION_V2.class_hash\
        ]
    )

For a full deployment and upgrade implementation, please see:

*   [Upgrades V1](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/tests/mocks/UpgradesMockV1.cairo)
    
*   [Upgrades V2](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/tests/mocks/UpgradesMockV2.cairo)
    

### [](#declaring_contracts)
Declaring contracts

StarkNet contracts come in two forms: contract classes and contract instances. Contract classes represent the uninstantiated, stateless code; whereas, contract instances are instantiated and include the state. Since the Proxy contract references the implementation contract by its class hash, declaring an implementation contract proves sufficient (as opposed to a full deployment). For more information on declaring classes, see [StarkNet’s documentation](https://starknet.io/docs/hello_starknet/intro.html#declare-contract)
.

### [](#testing_method_calls)
Testing method calls

As with most StarkNet contracts, interacting with a proxy contract requires an [account abstraction](accounts#quickstart)
. Due to limitations in the StarkNet testing framework, however, `@view` methods also require an account abstraction. This is only a requirement when testing. The differences in getter methods written in Python, for example, are as follows:

    # standard ERC20 call
    result = await erc20.totalSupply().call()
    
    # upgradeable ERC20 call
    result = await signer.send_transaction(
        account, PROXY.contract_address, 'totalSupply', []
    )

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets include:

*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   More to come! Have an idea? [Open an issue](https://github.com/OpenZeppelin/cairo-contracts/issues/new/choose)
    !
    

[← Extensibility](/contracts-cairo/0.5.0/extensibility)

[Accounts →](/contracts-cairo/0.5.0/accounts)




 Governance - OpenZeppelin Docs       

Governance
==========

Reference of interfaces and utilities related to Governance.

[](#utils)
Utils
----------------

### [](#IVotes)
`IVotes`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/governance/utils/interfaces/votes.cairo)

    use openzeppelin::governance::utils::interfaces::IVotes;

Common interface for Votes-enabled contracts. For an implementation example see [ERC20VotesComponent](erc20#ERC20VotesComponent)
.

Functions

*   [`get_votes(account)`](#IVotes-get_votes)
    
*   [`get_past_votes(account, timepoint)`](#IVotes-get_past_votes)
    
*   [`get_past_total_supply(timepoint)`](#IVotes-get_past_total_supply)
    
*   [`delegates(account)`](#IVotes-delegates)
    
*   [`delegate(delegatee)`](#IVotes-delegate)
    
*   [`delegate_by_sig(delegator, delegatee, nonce, expiry, signature)`](#IVotes-delegate_by_sig)
    

#### [](#IVotes-Functions)
Functions

#### [](#IVotes-get_votes)
`get_votes(account: ContractAddress) → u256` external

Returns the current amount of votes that `account` has.

#### [](#IVotes-get_past_votes)
`get_past_votes(account: ContractAddress, timepoint: u64) → u256` external

Returns the amount of votes that `account` had at a specific moment in the past.

#### [](#IVotes-get_past_total_supply)
`get_past_total_supply(timepoint: u64) → u256` external

Returns the total supply of votes available at a specific moment in the past.

|     |     |
| --- | --- |
|     | This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. Votes that have not been delegated are still part of total supply, even though they would not participate in a vote. |

#### [](#IVotes-delegates)
`delegates(account: ContractAddress) → ContractAddress` external

Returns the delegate that `account` has chosen.

#### [](#IVotes-delegate)
`delegate(delegatee: ContractAddress)` external

Delegates votes from the sender to `delegatee`.

#### [](#IVotes-delegate_by_sig)
`delegate_by_sig(delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Array<felt252>)` external

Delegates votes from `delegator` to `delegatee`.

[← API Reference](/contracts-cairo/0.13.0/api/account)

[Introspection →](/contracts-cairo/0.13.0/introspection)




 Introspection - OpenZeppelin Docs       

Introspection
=============

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [ERC165](#erc165)
    
    *   [Interface calculations](#interface_calculations)
        
    *   [Registering interfaces](#registering_interfaces)
        
    *   [Querying interfaces](#querying_interfaces)
        
    *   [IERC165](#ierc165)
        
    *   [IERC165 API Specification](#ierc165_api_specification)
        
        *   [`supportsInterface`](#supportsinterface)
            
        
    *   [ERC165 Library Functions](#erc165_library_functions)
        
        *   [`supports_interface`](#supportsinterface2)
            
        *   [`register_interface`](#register_interface)
            
        
    

[](#erc165)
ERC165
------------------

The ERC165 standard allows smart contracts to exercise [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
 on other contracts, that is, examining which functions can be called on them. This is usually referred to as a contract’s interface.

Cairo contracts, like Ethereum contracts, have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. ERC20 tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract declaring its interface can be very helpful in preventing errors.

It should be noted that the [constants library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/utils/constants/library.cairo)
 includes constant variables referencing all of the interface ids used in these contracts. This allows for more legible code i.e. using `IERC165_ID` instead of `0x01ffc9a7`.

### [](#interface_calculations)
Interface calculations

In order to ensure EVM/StarkNet compatibility, interface identifiers are not calculated on StarkNet. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, the contract should import the ERC165 library and register its support. It’s recommended to register interface support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    from openzeppelin.introspection.erc165.library import ERC165
    
    INTERFACE_ID = 0x12345678
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        ERC165.register_interface(INTERFACE_ID);
        return ();
    }

### [](#querying_interfaces)
Querying interfaces

To query a target contract’s support for an interface, the querying contract should call `supportsInterface` through IERC165 with the target contract’s address and the queried interface id. Here’s an example:

    from openzeppelin.introspection.erc265.IERC165 import IERC165
    
    INTERFACE_ID = 0x12345678
    
    func check_support{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        target_contract: felt
    ) -> (success: felt) {
        let (is_supported) = IERC165.supportsInterface(target_contract, INTERFACE_ID);
        return (is_supported);
    }

|     |     |
| --- | --- |
|     | `supportsInterface` is camelCased because it is an exposed contract method as part of ERC165’s interface. This differs from library methods (such as `supports_interface` from the [ERC165 library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/introspection/erc165/library.cairo)<br>) which are snake\_cased and not exposed. See the [Function names and coding style](extensibility#function_names_and_coding_style)<br> for more details. |

### [](#ierc165)
IERC165

    @contract_interface
    namespace IERC165 {
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    }

### [](#ierc165_api_specification)
IERC165 API Specification

    func supportsInterface(interfaceId: felt) -> (success: felt) {
    }

#### [](#supportsinterface)
`supportsInterface`

Returns true if this contract implements the interface defined by `interfaceId`.

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#erc165_library_functions)
ERC165 Library Functions

    func supports_interface(interface_id: felt) -> (success: felt) {
    }
    
    func register_interface(interface_id: felt) {
    }

#### [](#supportsinterface2)
`supports_interface`

Returns true if this contract implements the interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns:

    success: felt

#### [](#register_interface)
`register_interface`

Calling contract declares support for a specific interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns: None.

[← Security](/contracts-cairo/0.6.0/security)

[Universal Deployer Contract →](/contracts-cairo/0.6.0/udc)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of methods and constants found in `openzeppelin/security/`.

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Initializable](#initializable)
    
*   [Pausable](#pausable)
    
*   [Reentrancy Guard](#reentrancy_guard)
    
*   [SafeMath](#safemath)
    
    *   [SafeUint256](#safeuint256)
        
    

[](#initializable)
Initializable
--------------------------------

The Initializable library provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to setup a contract’s initial state when a constructor cannot be used.

The recommended pattern with Initializable is to include a check that the Initializable state is `False` and invoke `initialize` in the target function like this:

    from openzeppelin.security.initializable.library import Initializable
    
    @external
    func foo{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() {
        let (initialized) = Initializable.initialized();
        assert initialized = FALSE;
    
        Initializable.initialize();
        return ();
    }

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used on one function. |

[](#pausable)
Pausable
----------------------

The Pausable library allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To use the Pausable library, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when not paused, insert `assert_not_paused`. For methods that should be available only when paused, insert `assert_paused`. For example:

    from openzeppelin.security.pausable.library import Pausable
    
    @external
    func whenNotPaused{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        Pausable.assert_not_paused();
    
        // function body
    
        return ();
    }
    
    @external
    func whenPaused{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        Pausable.assert_paused();
    
        // function body
    
        return ();
    }

|     |     |
| --- | --- |
|     | `pause` and `unpause` already include these assertions. In other words, `pause` cannot be invoked when already paused and vice versa. |

For a list of full implementations utilizing the Pausable library, see:

*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [`reentrancy guard`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/security/reentrancyguard/library.cairo)
 library exposes two methods `start` and `end` to protect functions against reentrancy attacks. The protected function must call `ReentrancyGuard.start` before the first function statement, and `ReentrancyGuard.end` before the return statement, as shown below:

    from openzeppelin.security.reentrancyguard.library import ReentrancyGuard
    
    func test_function{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() {
       ReentrancyGuard.start();
    
       // function body
    
       ReentrancyGuard.end();
       return ();
    }

[](#safemath)
SafeMath
----------------------

### [](#safeuint256)
SafeUint256

The SafeUint256 namespace in the [SafeMath library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/security/safemath/library.cairo)
 offers arithmetic for unsigned 256-bit integers (uint256) by leveraging Cairo’s Uint256 library and integrating overflow checks. Some of Cairo’s Uint256 functions do not revert upon overflows. For instance, `uint256_add` will return a bit carry when the sum exceeds 256 bits. This library includes an additional assertion ensuring values do not overflow.

Using SafeUint256 methods is rather straightforward. Simply import SafeUint256 and insert the arithmetic method like this:

    from openzeppelin.security.safemath.library import SafeUint256
    
    func add_two_uints{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        a: Uint256, b: Uint256) -> (c: Uint256) {
        let (c: Uint256) = SafeUint256.add(a, b);
        return (c);
    }

[← ERC1155](/contracts-cairo/0.6.0/erc1155)

[Introspection →](/contracts-cairo/0.6.0/introspection)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are derived from a private key, all Starknet accounts are contracts. This means there’s no Externally Owned Account (EOA) concept on Starknet.

Instead, the network features native account abstraction and signature validation happens at the contract level.

For a general overview of account abstraction, see [Starknet’s documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/introduction/)
. A more detailed discussion on the topic can be found in [Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

|     |     |
| --- | --- |
|     | For detailed information on the usage and implementation check the [API Reference](api/account)<br> section. |

[](#what_is_an_account)
What is an account?
-------------------------------------------

Accounts in Starknet are smart contracts, and so they can be deployed and interacted with like any other contract, and can be extended to implement any custom logic. However, an account is a special type of contract that is used to validate and execute transactions. For this reason, it must implement a set of entrypoints that the protocol uses for this execution flow. The [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 proposal defines a standard interface for accounts, supporting this execution flow and interoperability with DApps in the ecosystem.

### [](#isrc6_interface)
ISRC6 Interface

    /// Represents a call to a target contract function.
    struct Call {
        to: ContractAddress,
        selector: felt252,
        calldata: Array<felt252>
    }
    
    /// Standard Account Interface
    #[starknet::interface]
    pub trait ISRC6 {
        /// Executes a transaction through the account.
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
    
        /// Asserts whether the transaction is valid to be executed.
        fn __validate__(calls: Array<Call>) -> felt252;
    
        /// Asserts whether a given signature for a given hash is valid.
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    }

|     |     |
| --- | --- |
|     | The `calldata` member of the `Call` struct in the accounts has been updated to `Span<felt252>` for optimization purposes, but the interface Id remains the same for backwards compatibility. This inconsistency will be fixed in future releases. |

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 adds the `is_valid_signature` method. This method is not used by the protocol, but it’s useful for DApps to verify the validity of signatures, supporting features like Sign In with Starknet.

SNIP-6 also defines that compliant accounts must implement the SRC5 interface following [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
, as a mechanism for detecting whether a contract is an account or not through introspection.

### [](#isrc5_interface)
ISRC5 Interface

    /// Standard Interface Detection
    #[starknet::interface]
    pub trait ISRC5 {
        /// Queries if a contract implements a given interface.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 compliant accounts must return `true` when queried for the ISRC6 interface Id.

Even though these interfaces are not enforced by the protocol, it’s recommended to implement them for enabling interoperability with the ecosystem.

### [](#protocol_level_methods)
Protocol-level methods

The Starknet protocol uses a few entrypoints for abstracting the accounts. We already mentioned the first two as part of the ISRC6 interface, and both are required for enabling accounts to be used for executing transactions. The rest are optional:

1.  `__validate__` verifies the validity of the transaction to be executed. This is usually used to validate signatures, but the entrypoint implementation can be customized to feature any validation mechanism [with some limitations](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/validate_and_execute/#validate_limitations)
    .
    
2.  `__execute__` executes the transaction if the validation is successful.
    
3.  `__validate_declare__` optional entrypoint similar to `__validate__` but for transactions meant to declare other contracts.
    
4.  `__validate_deploy__` optional entrypoint similar to `__validate__` but meant for [counterfactual deployments](guides/deployment)
    .
    

|     |     |
| --- | --- |
|     | Although these entrypoints are available to the protocol for its regular transaction flow, they can also be called like any other method. |

[](#starknet_account)
Starknet Account
--------------------------------------

Starknet native account abstraction pattern allows for the creation of custom accounts with different validation schemes, but usually most account implementations validate transactions using the [Stark curve](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/stark-curve)
 which is the most efficient way of validating signatures since it is a STARK-friendly curve.

OpenZeppelin Contracts for Cairo provides [AccountComponent](api/account#AccountComponent)
 for implementing this validation scheme.

### [](#usage)
Usage

Constructing an account contract requires integrating both [AccountComponent](api/account#AccountComponent)
 and [SRC5Component](api/introspection#SRC5Component)
. The contract should also set up the constructor to initialize the public key that will be used as the account’s signer. Here’s an example of a basic contract:

    #[starknet::contract(account)]
    mod MyAccount {
        use openzeppelin::account::AccountComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccountComponent, storage: account, event: AccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // Account Mixin
        #[abi(embed_v0)]
        impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
        impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            account: AccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccountEvent: AccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: felt252) {
            self.account.initializer(public_key);
        }
    }

### [](#interface)
Interface

This is the full interface of the `AccountMixinImpl` implementation:

    #[starknet::interface]
    pub trait AccountABI {
        // ISRC6
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
        fn __validate__(calls: Array<Call>) -> felt252;
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    
        // ISRC5
        fn supports_interface(interface_id: felt252) -> bool;
    
        // IDeclarer
        fn __validate_declare__(class_hash: felt252) -> felt252;
    
        // IDeployable
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: felt252
        ) -> felt252;
    
        // IPublicKey
        fn get_public_key() -> felt252;
        fn set_public_key(new_public_key: felt252, signature: Span<felt252>);
    
        // ISRC6CamelOnly
        fn isValidSignature(hash: felt252, signature: Array<felt252>) -> felt252;
    
        // IPublicKeyCamel
        fn getPublicKey() -> felt252;
        fn setPublicKey(newPublicKey: felt252, signature: Span<felt252>);
    }

[](#ethereum_account)
Ethereum Account
--------------------------------------

Besides the Stark-curve account, OpenZeppelin Contracts for Cairo also offers Ethereum-flavored accounts that use the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1)
 curve for signature validation. For this the [EthAccountComponent](api/account#EthAccountComponent)
 must be used.

### [](#usage_2)
Usage

Constructing a secp256k1 account contract also requires integrating both [EthAccountComponent](api/account#EthAccountComponent)
 and [SRC5Component](api/introspection#SRC5Component)
. The contract should also set up the constructor to initialize the public key that will be used as the account’s signer. Here’s an example of a basic contract:

    #[starknet::contract(account)]
    mod MyEthAccount {
        use openzeppelin::account::EthAccountComponent;
        use openzeppelin::account::interface::EthPublicKey;
        use openzeppelin::introspection::src5::SRC5Component;
        use starknet::ClassHash;
    
        component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // EthAccount Mixin
        #[abi(embed_v0)]
        impl EthAccountMixinImpl =
            EthAccountComponent::EthAccountMixinImpl<ContractState>;
        impl EthAccountInternalImpl = EthAccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            eth_account: EthAccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            EthAccountEvent: EthAccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: EthPublicKey) {
            self.eth_account.initializer(public_key);
        }
    }

### [](#interface_2)
Interface

This is the full interface of the `EthAccountMixinImpl` implementation:

    #[starknet::interface]
    pub trait EthAccountABI {
        // ISRC6
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
        fn __validate__(calls: Array<Call>) -> felt252;
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    
        // ISRC5
        fn supports_interface(interface_id: felt252) -> bool;
    
        // IDeclarer
        fn __validate_declare__(class_hash: felt252) -> felt252;
    
        // IEthDeployable
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: EthPublicKey
        ) -> felt252;
    
        // IEthPublicKey
        fn get_public_key() -> EthPublicKey;
        fn set_public_key(new_public_key: EthPublicKey, signature: Span<felt252>);
    
        // ISRC6CamelOnly
        fn isValidSignature(hash: felt252, signature: Array<felt252>) -> felt252;
    
        // IEthPublicKeyCamel
        fn getPublicKey() -> EthPublicKey;
        fn setPublicKey(newPublicKey: EthPublicKey, signature: Span<felt252>);
    }

[](#deploying_an_account)
Deploying an account
----------------------------------------------

In Starknet there are two ways of deploying smart contracts: using the `deploy_syscall` and doing counterfactual deployments. The former can be easily done with the [Universal Deployer Contract (UDC)](udc)
, a contract that wraps and exposes the `deploy_syscall` to provide arbitrary deployments through regular contract calls. But if you don’t have an account to invoke it, you will probably want to use the latter.

To do counterfactual deployments, you need to implement another protocol-level entrypoint named `__validate_deploy__`. Check the [counterfactual deployments](guides/deployment)
 guide to learn how.

[](#sending_transactions)
Sending transactions
----------------------------------------------

Let’s now explore how to send transactions through these accounts.

### [](#starknet_account_2)
Starknet Account

First, let’s take the example account we created before and deploy it:

    #[starknet::contract(account)]
    mod MyAccount {
        use openzeppelin::account::AccountComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccountComponent, storage: account, event: AccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // Account Mixin
        #[abi(embed_v0)]
        impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
        impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            account: AccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccountEvent: AccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: felt252) {
            self.account.initializer(public_key);
        }
    }

To deploy the account variant, compile the contract and declare the class hash because custom accounts are likely not declared. This means that you’ll need an account already deployed.

Next, create the account JSON with Starknet Foundry’s [custom account setup](https://foundry-rs.github.io/starknet-foundry/starknet/account.html#custom-account-contract)
 and include the `--class-hash` flag with the declared class hash. The flag enables custom account variants.

|     |     |
| --- | --- |
|     | The following examples use `sncast` [v0.23.0](https://github.com/foundry-rs/starknet-foundry/releases/tag/v0.23.0)<br>. |

    $ sncast \
      --url http://127.0.0.1:5050 \
      account create \
      --name my-custom-account \
      --class-hash 0x123456...

This command will output the precomputed contract address and the recommended `max-fee`. To counterfactually deploy the account, send funds to the address and then deploy the custom account.

    $ sncast \
      --url http://127.0.0.1:5050 \
      account deploy \
      --name my-custom-account

Once the account is deployed, set the `--account` flag with the custom account name to send transactions from that account.

    $ sncast \
      --account my-custom-account \
      --url http://127.0.0.1:5050 \
      invoke \
      --contract-address 0x123... \
      --function "some_function" \
      --calldata 1 2 3

### [](#ethereum_account_2)
Ethereum Account

First, let’s take the example account we created before and deploy it:

    #[starknet::contract(account)]
    mod MyEthAccount {
        use openzeppelin::account::EthAccountComponent;
        use openzeppelin::account::interface::EthPublicKey;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // EthAccount Mixin
        #[abi(embed_v0)]
        impl EthAccountMixinImpl =
            EthAccountComponent::EthAccountMixinImpl<ContractState>;
        impl EthAccountInternalImpl = EthAccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            eth_account: EthAccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            EthAccountEvent: EthAccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: EthPublicKey) {
            self.eth_account.initializer(public_key);
        }
    }

Special tooling is required in order to deploy and send transactions with an Ethereum-flavored account contract. The following examples utilize the [StarknetJS](https://www.starknetjs.com/)
 library.

Compile and declare the contract on the target network. Next, precompute the EthAccount contract address using the declared class hash.

|     |     |
| --- | --- |
|     | The following examples use unreleased features from StarknetJS (`starknetjs@next`) at commit [d002baea0abc1de3ac6e87a671f3dec3757437b3](https://github.com/starknet-io/starknet.js/commit/d002baea0abc1de3ac6e87a671f3dec3757437b3)<br>. |

    import * as dotenv from 'dotenv';
    import { CallData, EthSigner, hash } from 'starknet';
    import { ABI as ETH_ABI } from '../abis/eth_account.js';
    dotenv.config();
    
    // Calculate EthAccount address
    const ethSigner = new EthSigner(process.env.ETH_PRIVATE_KEY);
    const ethPubKey = await ethSigner.getPubKey();
    const ethAccountClassHash = '<ETH_ACCOUNT_CLASS_HASH>';
    const ethCallData = new CallData(ETH_ABI);
    const ethAccountConstructorCalldata = ethCallData.compile('constructor', {
        public_key: ethPubKey
    })
    const salt = '0x12345';
    const deployerAddress = '0x0';
    const ethContractAddress = hash.calculateContractAddressFromHash(
        salt,
        ethAccountClassHash,
        ethAccountConstructorCalldata,
        deployerAddress
    );
    console.log('Pre-calculated EthAccount address: ', ethContractAddress);

Send funds to the pre-calculated EthAccount address and deploy the contract.

    import * as dotenv from 'dotenv';
    import { Account, CallData, EthSigner, RpcProvider, stark } from 'starknet';
    import { ABI as ETH_ABI } from '../abis/eth_account.js';
    dotenv.config();
    
    // Prepare EthAccount
    const provider = new RpcProvider({ nodeUrl: process.env.API_URL });
    const ethSigner = new EthSigner(process.env.ETH_PRIVATE_KEY);
    const ethPubKey = await ethSigner.getPubKey();
    const ethAccountAddress = '<ETH_ACCOUNT_ADDRESS>'
    const ethAccount = new Account(provider, ethAccountAddress, ethSigner);
    
    // Prepare payload
    const ethAccountClassHash = '<ETH_ACCOUNT_CLASS_HASH>'
    const ethCallData = new CallData(ETH_ABI);
    const ethAccountConstructorCalldata = ethCallData.compile('constructor', {
        public_key: ethPubKey
    })
    const salt = '0x12345';
    const deployPayload = {
        classHash: ethAccountClassHash,
        constructorCalldata: ethAccountConstructorCalldata,
        addressSalt: salt,
    };
    
    // Deploy
    const { suggestedMaxFee: feeDeploy } = await ethAccount.estimateAccountDeployFee(deployPayload);
    const { transaction_hash, contract_address } = await ethAccount.deployAccount(
        deployPayload,
        { maxFee: stark.estimatedFeeToMaxFee(feeDeploy, 100) }
    );
    await provider.waitForTransaction(transaction_hash);
    console.log('EthAccount deployed at: ', contract_address);

Once deployed, connect the EthAccount instance to the target contract which enables calls to come from the EthAccount. Here’s what an ERC20 transfer from an EthAccount looks like.

    import * as dotenv from 'dotenv';
    import { Account, RpcProvider, Contract, EthSigner } from 'starknet';
    dotenv.config();
    
    // Prepare EthAccount
    const provider = new RpcProvider({ nodeUrl: process.env.API_URL });
    const ethSigner = new EthSigner(process.env.ETH_PRIVATE_KEY);
    const ethAccountAddress = '<ETH_ACCOUNT_CONTRACT_ADDRESS>'
    const ethAccount = new Account(provider, ethAccountAddress, ethSigner);
    
    // Prepare target contract
    const erc20 = new Contract(compiledErc20.abi, erc20Address, provider);
    
    // Connect EthAccount with the target contract
    erc20.connect(ethAccount);
    
    // Execute ERC20 transfer
    const transferCall = erc20.populate('transfer', {
        recipient: recipient.address,
        amount: 50n
    });
    const tx = await erc20.transfer(
        transferCall.calldata, { maxFee: 900_000_000_000_000 }
    );
    await provider.waitForTransaction(tx.transaction_hash);

[← API Reference](/contracts-cairo/0.15.0/api/access)

[API Reference →](/contracts-cairo/0.15.0/api/account)




 Extensibility - OpenZeppelin Docs       

Extensibility
=============

|     |     |
| --- | --- |
|     | Expect this pattern to evolve (as it has already done) or even disappear if [proper extensibility features](https://community.starknet.io/t/contract-extensibility-pattern/210/11?u=martriay)<br> are implemented into Cairo. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [The extensibility problem](#the_extensibility_problem)
    
*   [The pattern ™️](#the_pattern)
    
    *   [Libraries](#libraries)
        
    *   [Contracts](#contracts)
        
    
*   [Presets](#presets)
    
*   [Function names and coding style](#function_names_and_coding_style)
    
*   [Emulating hooks](#emulating_hooks)
    

[](#the_extensibility_problem)
The extensibility problem
--------------------------------------------------------

Smart contract development is a critical task. As with all software development, it is error prone; but unlike most scenarios, a bug can result in major losses for organizations as well as individuals. Therefore writing complex smart contracts is a delicate task.

One of the best approaches to minimize introducing bugs is to reuse existing, battle-tested code, a.k.a. using libraries. But code reutilization in StarkNet’s smart contracts is not easy:

*   Cairo has no explicit smart contract extension mechanisms such as inheritance or composability.
    
*   Using imports for modularity can result in clashes (more so given that arguments are not part of the selector), and lack of overrides or aliasing leaves no way to resolve them.
    
*   Any `@external` function defined in an imported module will be automatically re-exposed by the importer (i.e. the smart contract).
    

To overcome these problems, this project builds on the following guidelines™.

[](#the_pattern)
The pattern
----------------------------

The idea is to have two types of Cairo modules: libraries and contracts. Libraries define reusable logic and storage variables which can then be extended and exposed by contracts. Contracts can be deployed, libraries cannot.

To minimize risk, boilerplate, and avoid function naming clashes, we follow these rules:

### [](#libraries)
Libraries

Considering the following types of functions:

*   `private`: private to a library, not meant to be used outside the module or imported.
    
*   `public`: part of the public API of a library.
    
*   `internal`: subset of `public` that is either discouraged or potentially unsafe (e.g. `_transfer` on ERC20).
    
*   `external`: subset of `public` that is ready to be exported as-is by contracts (e.g. `transfer` on ERC20).
    
*   `storage`: storage variable functions.
    

Then:

*   Must implement `public` and `external` functions under a namespace.
    
*   Must implement `private` functions outside the namespace to avoid exposing them.
    
*   Must prefix `internal` functions with an underscore (e.g. `ERC20._mint`).
    
*   Must not prefix `external` functions with an underscore (e.g. `ERC20.transfer`).
    
*   Must prefix `storage` functions with the name of the namespace to prevent clashing with other libraries (e.g. `ERC20balances`).
    
*   Must not implement any `@external`, `@view`, or `@constructor` functions.
    
*   Can implement initializers (never as `@constructor` or `@external`).
    
*   Must not call initializers on any function.
    

### [](#contracts)
Contracts

*   Can import from libraries.
    
*   Should implement `@external` functions if needed.
    
*   Should implement a `@constructor` function that calls initializers.
    
*   Must not call initializers in any function beside the constructor.
    

Note that since initializers will never be marked as `@external` and they won’t be called from anywhere but the constructor, there’s no risk of re-initialization after deployment. It’s up to the library developers not to make initializers interdependent to avoid weird dependency paths that may lead to double construction of libraries.

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets are:

*   [Account](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/account/presets/Account.cairo)
    
*   [ERC165](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/tests/mocks/ERC165.cairo)
    
*   [ERC20Mintable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
    
*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   [ERC20](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc20/presets/ERC20.cairo)
    
*   [ERC721MintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    
*   [ERC721EnumerableMintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/token/erc721/enumerable/presets/ERC721EnumerableMintableBurnable.cairo)
    

In previous versions of Cairo importing any function from a module would automatically import all `@external` functions. We used to leverage this behavior to just import the constructor of the preset contract to load it. Since Cairo v0.10, however, contracts that utilize the preset contracts should import all of the exposed functions from it. For example:

    %lang starknet
    
    from openzeppelin.token.erc20.presets.ERC20 import constructor

should now look like:

    %lang starknet
    
    from openzeppelin.token.erc20.presets.ERC20 import (
        constructor,
        name,
        symbol,
        totalSupply,
        decimals,
        balanceOf,
        allowance,
        transfer,
        transferFrom,
        approve,
        increaseAllowance,
        decreaseAllowance
    )

[](#function_names_and_coding_style)
Function names and coding style
--------------------------------------------------------------------

*   Following Cairo’s programming style, we use `snake_case` for library APIs (e.g. `ERC20.transfer_from`, `ERC721.safe_transfer_from`).
    
*   But for standard EVM ecosystem compatibility, we implement external functions in contracts using `camelCase` (e.g. `transferFrom` in a ERC20 contract).
    
*   Guard functions such as the so-called "only owner" are prefixed with `assert_` (e.g. `Ownable.assert_only_owner`).
    

[](#emulating_hooks)
Emulating hooks
------------------------------------

Unlike the Solidity version of [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts)
, this library does not implement [hooks](https://docs.openzeppelin.com/contracts/4.x/extending-contracts#using-hooks)
. The main reason being that Cairo does not support overriding functions.

This is what a hook looks like in Solidity:

    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }

Instead, the extensibility pattern allows us to simply extend the library implementation of a function (namely `transfer`) by adding lines before or after calling it. This way, we can get away with:

    @external
    func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        recipient: felt, amount: Uint256
    ) -> (success: felt) {
        Pausable.assert_not_paused();
        return ERC20.transfer(recipient, amount);
    }

[← Overview](/contracts-cairo/0.5.0/)

[Proxies and Upgrades →](/contracts-cairo/0.5.0/proxies)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. The `ERC721.cairo` contract implements an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC721](#ierc721)
    
*   [ERC721 Compatibility](#erc721_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC721 URIs](#interpreting_erc721_uris)
        
    *   [ERC721Received](#erc721received)
        
        *   [IERC721Receiver](#ierc721receiver)
            
        
    *   [Supporting Interfaces](#supporting_interfaces)
        
    *   [Ready\_to\_Use Presets](#ready_to_use_presets)
        
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC721MintableBurnable](#erc721mintableburnable)
        
    *   [ERC721MintablePausable](#erc721mintablepausable)
        
    *   [ERC721EnumerableMintableBurnable](#erc721enumerablemintableburnable)
        
        *   [IERC721Enumerable](#ierc721enumerable)
            
        
    *   [ERC721Metadata](#erc721metadata)
        
        *   [IERC721Metadata](#ierc721metadata)
            
        
    
*   [Utilities](#utilities)
    
    *   [ERC721Holder](#erc721_holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC721`](#ierc721_api)
        
        *   [`balanceOf`](#balanceof)
            
        *   [`ownerOf`](#ownerof)
            
        *   [`safeTransferFrom`](#safetransferfrom)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        *   [`setApprovalForAll`](#setapprovalforall)
            
        *   [`getApproved`](#getapproved)
            
        *   [`isApprovedForAll`](#isapprovedforall)
            
        
    *   [Events](#events)
        
        *   [`Approval (event)`](#approval_event)
            
        *   [`ApprovalForAll (event)`](#approvalforall_event)
            
        *   [`Transfer (event)`](#transfer_event)
            
        
    *   [`IERC721Metadata`](#ierc721metadata)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`tokenURI`](#tokenuri)
            
        
    *   [`IERC721Enumerable`](#ierc721enumerable)
        
        *   [`totalSupply`](#totalsupply)
            
        *   [`tokenByIndex`](#tokenbyindex)
            
        *   [`tokenOfOwnerByIndex`](#tokenofownerbyindex)
            
        
    *   [`IERC721Receiver`](#ierc721receiver_api)
        
        *   [`onERC721Received`](#onerc721received)
            
        
    

[](#ierc721)
IERC721
--------------------

    @contract_interface
    namespace IERC721 {
        func balanceOf(owner: felt) -> (balance: Uint256) {
        }
    
        func ownerOf(tokenId: Uint256) -> (owner: felt) {
        }
    
        func safeTransferFrom(from_: felt, to: felt, tokenId: Uint256, data_len: felt, data: felt*) {
        }
    
        func transferFrom(from_: felt, to: felt, tokenId: Uint256) {
        }
    
        func approve(approved: felt, tokenId: Uint256) {
        }
    
        func setApprovalForAll(operator: felt, approved: felt) {
        }
    
        func getApproved(tokenId: Uint256) -> (approved: felt) {
        }
    
        func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt) {
        }
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    }

### [](#erc721_compatibility)
ERC721 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard in the following ways:

*   It uses Cairo’s `uint256` instead of `felt`.
    
*   It returns `TRUE` as success.
    
*   It makes use of Cairo’s short strings to simulate `name` and `symbol`.
    

But some differences can still be found, such as:

*   `tokenURI` returns a felt representation of the queried token’s URI. The EIP721 standard, however, states that the return value should be of type string. If a token’s URI is not set, the returned value is `0`. Note that URIs cannot exceed 31 characters. See [Interpreting ERC721 URIs](#interpreting_erc721_uris)
    .
    
*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Solidity’s selector calculations. See [Supporting Interfaces](#supporting_interfaces)
    .
    
*   `safeTransferFrom` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721. The difference between both functions consists of accepting `data` as an argument. Because function overloading is currently not possible in Cairo, `safeTransferFrom` by default accepts the `data` argument. If `data` is not used, simply insert `0`.
    
*   `safeTransferFrom` is specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, it accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`.
    
*   `ERC165.register_interface` allows contracts to set and communicate which interfaces they support. This follows OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v0.4.0b/contracts/utils/introspection/ERC165Storage.sol)
    .
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info.
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) must support ERC165 by registering the `IERC721Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC721 transfers.
    
*   `ERC721Enumerable` tracks the total number of tokens with the `all_tokens` and `all_tokens_len` storage variables mimicking the array of the Solidity implementation.
    

[](#usage)
Usage
----------------

Use cases go from artwork, digital collectibles, physical property, and many more.

To show a standard use case, we’ll use the `ERC721Mintable` preset which allows for only the owner to `mint` and `burn` tokens. To create a token you need to first deploy both Account and ERC721 contracts respectively. As most StarkNet contracts, ERC721 expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it.

Considering that the ERC721 constructor method looks like this:

    func constructor(
        name: felt,          // Token name as Cairo short string
        symbol: felt,        // Token symbol as Cairo short string
        owner: felt          // Address designated as the contract owner
    ) {
    }

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc721 = await starknet.deploy(
        "contracts/token/erc721/presets/ERC721Mintable.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),                       # name\
            str_to_felt("TKN"),                         # symbol\
            account.contract_address                    # owner\
        ]
    )

To mint a non-fungible token, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    tokenId = uint(1)
    
    await signer.send_transaction(
        account, erc721.contract_address, 'mint', [\
            recipient_address,\
            *tokenId\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `transferFrom` and `safeTransferFrom` to transfer NFTs. If using `transferFrom`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.**

The `safeTransferFrom` method incorporates the following conditional logic:

1.  if the calling address is an account contract, the token transfer will behave as if `transferFrom` was called
    
2.  if the calling address is not an account contract, the safe function will check that the contract supports ERC721 tokens
    

The current implementation of `safeTansferFrom` checks for `onERC721Received` and requires that the recipient contract supports ERC165 and exposes the `supportsInterface` method. See [ERC721Received](#erc721received)
.

### [](#interpreting_erc721_uris)
Interpreting ERC721 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard set in [EIP721](https://eips.ethereum.org/EIPS/eip-721)<br>. Therefore, this library’s ERC721 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC721, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc721.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc721.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc721received)
ERC721Received

In order to be sure a contract can safely accept ERC721 tokens, said contract must implement the `ERC721_Receiver` interface (as expressed in the EIP721 specification). Methods such as `safeTransferFrom` and `safeMint` call the recipient contract’s `onERC721Received` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. `safeTransferFrom` requires a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC721 implementation requires that all contracts that support safe ERC721 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC721Receiver` magic value `0x150b7a02` (which invokes `onERC721Received`). If the recipient contract supports the `IAccount` magic value `0x50b70dcb`, `supportsInterface` should return `TRUE`. Otherwise, `safeTransferFrom` should fail.

#### [](#ierc721receiver)
IERC721Receiver

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

    @contract_interface
    namespace IERC721Receiver {
        func onERC721Received(
            operator: felt, from_: felt, tokenId: Uint256, data_len: felt data: felt*) -> (selector: felt) {
        }
    }

### [](#supporting_interfaces)
Supporting Interfaces

In order to ensure EVM/StarkNet compatibility, this ERC721 implementation does not calculate interface identifiers. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

Further, this implementation stores supported interfaces in a mapping (similar to OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v0.4.0b/contracts/utils/introspection/ERC165Storage.sol)
).

### [](#ready_to_use_presets)
Ready-to-Use Presets

ERC721 presets have been created to allow for quick deployments as-is. To be as explicit as possible, each preset includes the additional features they offer in the contract name. For example:

*   `ERC721MintableBurnable` includes `mint` and `burn`.
    
*   `ERC721MintablePausable` includes `mint`, `pause`, and `unpause`.
    
*   `ERC721EnumerableMintableBurnable` includes `mint`, `burn`, and [IERC721Enumerable](#ierc721enumerable)
     methods.
    

Ready-to-use presets are a great option for testing and prototyping. See [Presets](#presets)
.

[](#extensibility)
Extensibility
--------------------------------

Following the [contracts extensibility pattern](extensibility)
, this implementation is set up to include all ERC721 related storage and business logic under a namespace. Developers should be mindful of manually exposing the required methods from the namespace to comply with the standard interface. This is already done in the [preset contracts](#presets)
; however, additional functionality can be added. For instance, you could:

*   Implement a pausing mechanism.
    
*   Add roles such as _owner_ or _minter_.
    
*   Modify the `transferFrom` function to mimic the [`_beforeTokenTransfer` and `_afterTokenTransfer` hooks](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L335)
    .
    

Just be sure that the exposed `external` methods invoke their imported function logic a la `approve` invokes `ERC721.approve`. As an example, see below.

    from openzeppelin.token.erc721.library import ERC721
    
    @external
    func approve{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}(
        to: felt, tokenId: Uint256
    ) {
        ERC721.approve(to, tokenId)
        return()
    }

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset includes a contract owner, which is set in the `constructor`, to offer simple access control on sensitive methods such as `mint` and `burn`.

### [](#erc721mintableburnable)
ERC721MintableBurnable

The `ERC721MintableBurnable` preset offers a quick and easy setup for creating NFTs. The contract owner can create tokens with `mint`, whereas token owners can destroy their tokens with `burn`.

### [](#erc721mintablepausable)
ERC721MintablePausable

The `ERC721MintablePausable` preset creates a contract with pausable token transfers and minting capabilities. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug. In this preset, only the contract owner can `mint`, `pause`, and `unpause`.

### [](#erc721enumerablemintableburnable)
ERC721EnumerableMintableBurnable

The `ERC721EnumerableMintableBurnable` preset adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This allows contracts to publish its full list of NFTs and make them discoverable.

In regard to implementation, contracts should expose the following view methods:

*   `ERC721Enumerable.total_supply`
    
*   `ERC721Enumerable.token_by_index`
    
*   `ERC721Enumerable.token_of_owner_by_index`
    

In order for the tokens to be correctly indexed, the contract should also use the following methods (which supersede some of the base `ERC721` methods):

*   `ERC721Enumerable.transfer_from`
    
*   `ERC721Enumerable.safe_transfer_from`
    
*   `ERC721Enumerable._mint`
    
*   `ERC721Enumerable._burn`
    

#### [](#ierc721enumerable)
IERC721Enumerable

    @contract_interface
    namespace IERC721Enumerable {
        func totalSupply() -> (totalSupply: Uint256) {
        }
    
        func tokenByIndex(index: Uint256) -> (tokenId: Uint256) {
        }
    
        func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256) {
        }
    }

### [](#erc721metadata)
ERC721Metadata

The `ERC721Metadata` extension allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

We follow OpenZeppelin’s Solidity approach of integrating the Metadata methods `name`, `symbol`, and `tokenURI` into all ERC721 implementations. If preferred, a contract can be created that does not import the Metadata methods from the `ERC721` library. Note that the `IERC721Metadata` interface id should be removed from the constructor as well.

#### [](#ierc721metadata)
IERC721Metadata

    @contract_interface
    namespace IERC721Metadata {
        func name() -> (name: felt) {
        }
    
        func symbol() -> (symbol: felt) {
        }
    
        func tokenURI(tokenId: Uint256) -> (tokenURI: felt) {
        }
    }

[](#utilities)
Utilities
------------------------

### [](#erc721holder)
ERC721Holder

Implementation of the `IERC721Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC721.safeTransferFrom`, `IERC721.approve` or `IERC721.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC721Received](#erc721received)

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc721_api)
IERC721 API

    func balanceOf(owner: felt) -> (balance: Uint256) {
    }
    
    func ownerOf(tokenId: Uint256) -> (owner: felt) {
    }
    
    func safeTransferFrom(from_: felt, to: felt, tokenId: Uint256, data_len: felt, data: felt*) {
    }
    
    func transferFrom(from_: felt, to: felt, tokenId: Uint256) {
    }
    
    func approve(approved: felt, tokenId: Uint256) {
    }
    
    func setApprovalForAll(operator: felt, approved: felt) {
    }
    
    func getApproved(tokenId: Uint256) -> (approved: felt) {
    }
    
    func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt) {
    }

#### [](#balanceof)
`balanceOf`

Returns the number of tokens in `owner`'s account.

Parameters:

    owner: felt

Returns:

    balance: Uint256

#### [](#ownerof)
`ownerOf`

Returns the owner of the `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    owner: felt

#### [](#safetransferfrom)
`safeTransferFrom`

Safely transfers `tokenId` token from `from_` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [ERC721Received](#erc721received)
.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#transferfrom)
`transferFrom`

Transfers `tokenId` token from `from_` to `to`. **The caller is responsible to confirm that `to` is capable of receiving NFTs or else they may be permanently lost**.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

Returns: None.

#### [](#approve)
`approve`

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Emits an [Approval](#approval_event)
 event.

Parameters:

    to: felt
    tokenId: Uint256

Returns: None.

#### [](#getapproved)
`getApproved`

Returns the account approved for `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    operator: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.

Emits an [ApprovalForAll](#approvalforall_event)
 event.

Parameters:

    operator: felt

Returns: None.

#### [](#isapprovedforall)
`isApprovedForAll`

Returns if the `operator` is allowed to manage all of the assets of `owner`.

Parameters:

    owner: felt
    operator: felt

Returns:

    isApproved: felt

### [](#events)
Events

#### [](#approval_event)
`Approval (Event)`

Emitted when `owner` enables `approved` to manage the `tokenId` token.

Parameters:

    owner: felt
    approved: felt
    tokenId: Uint256

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    owner: felt
    operator: felt
    approved: felt

#### [](#transfer_event)
`Transfer (Event)`

Emitted when `tokenId` token is transferred from `from_` to `to`.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

* * *

### [](#ierc721metadata_api)
IERC721Metadata API

    func name() -> (name: felt) {
    }
    
    func symbol() -> (symbol: felt) {
    }
    
    func tokenURI(tokenId: Uint256) -> (tokenURI: felt) {
    }

#### [](#name)
`name`

Returns the token collection name.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the token collection symbol.

Parameters: None.

Returns:

    symbol: felt

#### [](#tokenuri)
`tokenURI`

Returns the Uniform Resource Identifier (URI) for `tokenID` token. If the URI is not set for the `tokenId`, the return value will be `0`.

Parameters:

    tokenId: Uint256

Returns:

    tokenURI: felt

* * *

### [](#ierc721enumerable_api)
IERC721Enumerable API

    func totalSupply() -> (totalSupply: Uint256) {
    }
    
    func tokenByIndex(index: Uint256) -> (tokenId: Uint256) {
    }
    
    func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256) {
    }

#### [](#totalsupply)
`totalSupply`

Returns the total amount of tokens stored by the contract.

Parameters: None

Returns:

    totalSupply: Uint256

#### [](#tokenbyindex)
`tokenByIndex`

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [balanceOf](#balanceof)
 to enumerate all of `owner`'s tokens.

Parameters:

    index: Uint256

Returns:

    tokenId: Uint256

#### [](#tokenofownerbyindex)
`tokenOfOwnerByIndex`

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [totalSupply](#totalsupply)
 to enumerate all tokens.

Parameters:

    owner: felt
    index: Uint256

Returns:

    tokenId: Uint256

* * *

### [](#ierc721receiver_api)
IERC721Receiver API

    func onERC721Received(
        operator: felt, from_: felt, tokenId: Uint256, data_len: felt data: felt*
    ) -> (selector: felt) {
    }

#### [](#onerc721received)
`onERC721Received`

Whenever an IERC721 `tokenId` token is transferred to this non-account contract via `safeTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC20](/contracts-cairo/0.5.0/erc20)

[Security →](/contracts-cairo/0.5.0/security)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides context, reasoning, and examples for methods and constants found in `tests/utils.py`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Constants](#constants)
    
*   [Strings](#strings)
    
    *   [`str_to_felt`](#str_to_felt)
        
    *   [`felt_to_str`](#felt_to_str)
        
    
*   [Uint256](#uint256)
    
    *   [`uint`](#uint)
        
    *   [`to_uint`](#to_uint)
        
    *   [`from_uint`](#from_uint)
        
    *   [`add_uint`](#add_uint)
        
    *   [`sub_uint`](#sub_uint)
        
    
*   [Assertions](#assertions)
    
    *   [`assert_revert`](#assert_revert)
        
    *   [`assert_revert_entry_point`](#assert_revert_entry_point)
        
    *   [`assert_events_emitted`](#assert_event_emitted)
        
    
*   [Memoization](#memoization)
    
    *   [`get_contract_class`](#get_contract_class)
        
    *   [`cached_contract`](#cached_contract)
        
    
*   [State](#state)
    
*   [Account](#account)
    
*   [MockSigner](#mocksigner)
    

[](#constants)
Constants
------------------------

To ease the readability of Cairo contracts, this project includes reusable [constant variables](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/utils/constants/library.cairo)
 like `UINT8_MAX`, or EIP165 interface IDs such as `IERC165_ID` or `IERC721_ID`. For more information on how interface ids are calculated, see the [ERC165 documentation](introspection#interface_calculations)
.

[](#strings)
Strings
--------------------

Cairo currently only provides support for short string literals (less than 32 characters). Note that short strings aren’t really strings, rather, they’re representations of Cairo field elements. The following methods provide a simple conversion to/from field elements.

### [](#str_to_felt)
`str_to_felt`

Takes an ASCII string and converts it to a field element via big endian representation.

### [](#felt_to_str)
`felt_to_str`

Takes an integer and converts it to an ASCII string by trimming the null bytes and decoding the remaining bits.

[](#uint256)
Uint256
--------------------

Cairo’s native data type is a field element (felt). Felts equate to 252 bits which poses a problem regarding 256-bit integer integration. To resolve the bit discrepancy, Cairo represents 256-bit integers as a struct of two 128-bit integers. Further, the low bits precede the high bits e.g.

    1 = (1, 0)
    1 << 128 = (0, 1)
    (1 << 128) - 1 = (340282366920938463463374607431768211455, 0)

### [](#uint)
`uint`

Converts a simple integer into a uint256-ish tuple.

> Note `to_uint` should be used in favor of `uint`, as `uint` only returns the low bits of the tuple.

### [](#to_uint)
`to_uint`

Converts an integer into a uint256-ish tuple.

    x = to_uint(340282366920938463463374607431768211456)
    print(x)
    # prints (0, 1)

### [](#from_uint)
`from_uint`

Converts a uint256-ish tuple into an integer.

    x = (0, 1)
    y = from_uint(x)
    print(y)
    # prints 340282366920938463463374607431768211456

### [](#add_uint)
`add_uint`

Performs addition between two uint256-ish tuples and returns the sum as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = add_uint(x, y)
    print(z)
    # prints (1, 1)

### [](#sub_uint)
`sub_uint`

Performs subtraction between two uint256-ish tuples and returns the difference as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = sub_uint(x, y)
    print(z)
    # prints (340282366920938463463374607431768211455, 0)

### [](#mul_uint)
`mul_uint`

Performs multiplication between two uint256-ish tuples and returns the product as a uint256-ish tuple.

    x = (0, 10)
    y = (2, 0)
    z = mul_uint(x, y)
    print(z)
    # prints (0, 20)

### [](#div_rem_uint)
`div_rem_uint`

Performs division between two uint256-ish tuples and returns both the quotient and remainder as uint256-ish tuples respectively.

    x = (1, 100)
    y = (0, 25)
    z = div_rem_uint(x, y)
    print(z)
    # prints ((4, 0), (1, 0))

[](#assertions)
Assertions
--------------------------

In order to abstract away some of the verbosity regarding test assertions on StarkNet transactions, this project includes the following helper methods:

### [](#assert_revert)
`assert_revert`

An asynchronous wrapper method that executes a try-except pattern for transactions that should fail. Note that this wrapper does not check for a StarkNet error code. This allows for more flexibility in checking that a transaction simply failed. If you wanted to check for an exact error code, you could use StarkNet’s [error\_codes module](https://github.com/starkware-libs/cairo-lang/blob/ed6cf8d6cec50a6ad95fa36d1eb4a7f48538019e/src/starkware/starknet/definitions/error_codes.py)
 and implement additional logic to the `assert_revert` method.

To successfully use this wrapper, the transaction method should be wrapped with `assert_revert`; however, `await` should precede the wrapper itself like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    )

This wrapper also includes the option to check that an error message was included in the reversion. To check that the reversion sends the correct error message, add the `reverted_with` keyword argument outside of the actual transaction (but still inside the wrapper) like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ]),
        reverted_with="insert error message here"
    )

### [](#assert_revert_entry_point)
`assert_revert_entry_point`

An extension of `assert_revert` that asserts an entry point error occurs with the given `invalid_selector` parameter. This assertion is especially useful in checking proxy/implementation contracts. To use `assert_revert_entry_point`:

    await assert_revert_entry_point(
        signer.send_transaction(
            account, contract.contract_address, 'nonexistent_selector', []
        ),
        invalid_selector='nonexistent_selector'
    )

### [](#assert_event_emitted)
`assert_event_emitted`

A helper method that checks a transaction receipt for the contract emitting the event (`from_address`), the emitted event itself (`name`), and the arguments emitted (`data`). To use `assert_event_emitted`:

    # capture the tx receipt
    tx_exec_info = await signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    
    # insert arguments to assert
    assert_event_emitted(
        tx_exec_info,
        from_address=contract.contract_address,
        name='Foo_emitted',
        data=[\
            account.contract_address,\
            recipient,\
            *token\
        ]
    )

[](#memoization)
Memoization
----------------------------

Memoizing functions allow for quicker and computationally cheaper calculations which is immensely beneficial while testing smart contracts.

### [](#get_contract_class)
`get_contract_class`

A helper method that returns the contract class from the contract’s name. To capture the contract class, simply add the contract’s name as an argument like this:

    contract_class = get_contract_class('ContractName')

If multiple contracts exist with the same name, then the contract’s path must be passed along with the `is_path` flag instead of the name. To pass the contract’s path:

    contract_class = get_contract_class('path/to/Contract.cairo', is_path=True)

### [](#cached_contract)
`cached_contract`

A helper method that returns the cached state of a given contract. It’s recommended to first deploy all the relevant contracts before caching the state. The requisite contracts in the testing module should each be instantiated with `cached_contract` in a fixture after the state has been copied. The memoization pattern with `cached_contract` should look something like this:

    # get contract classes
    @pytest.fixture(scope='module')
    def contract_classes():
      foo_cls = get_contract_class('Foo')
      return foo_cls
    
    # deploy contracts
    @pytest.fixture(scope='module')
    async def foo_init(contract_classes):
        foo_cls = contract_classes
        starknet = await Starknet.empty()
        foo = await starknet.deploy(
            contract_class=foo_cls,
            constructor_calldata=[]
        )
        return starknet.state, foo  # return state and all deployed contracts
    
    # memoization
    @pytest.fixture
    def foo_factory(contract_classes, foo_init):
        foo_cls = contract_classes                          # contract classes
        state, foo = foo_init                               # state and deployed contracts
        _state = state.copy()                               # copy the state
        cached_foo = cached_contract(_state, foo_cls, foo)  # cache contracts
        return cached_foo                                   # return cached contracts

[](#state)
State
----------------

The `State` class provides a wrapper for initializing the StarkNet state which acts as a helper for the `Account` class. This wrapper allows `Account` deployments to share the same initialized state without explicitly passing the instantiated StarkNet state to `Account`. Initializing the state should look like this:

    from utils import State
    
    starknet = await State.init()

[](#account)
Account
--------------------

The `Account` class abstracts away most of the boilerplate for deploying accounts. Instantiating accounts with this class requires the StarkNet state to be instantiated first with the `State.init()` method like this:

    from utils import State, Account
    
    starknet = await State.init()
    account1 = await Account.deploy(public_key)
    account2 = await Account.deploy(public_key)

The Account class also provides access to the account contract class which is useful for following the [Memoization](#memoization)
 pattern. To fetch the account contract class:

    fetch_class = Account.get_class

[](#mocksigner)
MockSigner
--------------------------

`MockSigner` is used to perform transactions with an instance of [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 on a given Account, crafting the transaction and managing nonces. The `Signer` instance manages signatures and is leveraged by `MockSigner` to operate with the Account contract’s `__execute__` method. See [MockSigner utility](accounts#mocksigner_utility)
 for more information.

[← Introspection](/contracts-cairo/0.5.0/introspection)

[Contracts for Solidity →](/contracts/5.x/)




 Introspection - OpenZeppelin Docs       

Introspection
=============

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [ERC165](#erc165)
    
    *   [Interface calculations](#interface_calculations)
        
    *   [Registering interfaces](#registering_interfaces)
        
    *   [Querying interfaces](#querying_interfaces)
        
    *   [IERC165](#ierc165)
        
    *   [IERC165 API Specification](#ierc165_api_specification)
        
        *   [`supportsInterface`](#supportsinterface)
            
        
    *   [ERC165 Library Functions](#erc165_library_functions)
        
        *   [`supports_interface`](#supportsinterface2)
            
        *   [`register_interface`](#register_interface)
            
        
    

[](#erc165)
ERC165
------------------

The ERC165 standard allows smart contracts to exercise [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
 on other contracts, that is, examining which functions can be called on them. This is usually referred to as a contract’s interface.

Cairo contracts, like Ethereum contracts, have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. ERC20 tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract declaring its interface can be very helpful in preventing errors.

It should be noted that the [constants library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/utils/constants/library.cairo)
 includes constant variables referencing all of the interface ids used in these contracts. This allows for more legible code i.e. using `IERC165_ID` instead of `0x01ffc9a7`.

### [](#interface_calculations)
Interface calculations

In order to ensure EVM/StarkNet compatibility, interface identifiers are not calculated on StarkNet. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, the contract should import the ERC165 library and register its support. It’s recommended to register interface support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    from openzeppelin.introspection.erc165.library import ERC165
    
    INTERFACE_ID = 0x12345678
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        ERC165.register_interface(INTERFACE_ID);
        return ();
    }

### [](#querying_interfaces)
Querying interfaces

To query a target contract’s support for an interface, the querying contract should call `supportsInterface` through IERC165 with the target contract’s address and the queried interface id. Here’s an example:

    from openzeppelin.introspection.erc265.IERC165 import IERC165
    
    INTERFACE_ID = 0x12345678
    
    func check_support{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        target_contract: felt
    ) -> (success: felt) {
        let (is_supported) = IERC165.supportsInterface(target_contract, INTERFACE_ID);
        return (is_supported);
    }

|     |     |
| --- | --- |
|     | `supportsInterface` is camelCased because it is an exposed contract method as part of ERC165’s interface. This differs from library methods (such as `supports_interface` from the [ERC165 library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.4.0b/src/openzeppelin/introspection/erc165/library.cairo)<br>) which are snake\_cased and not exposed. See the [Function names and coding style](extensibility#function_names_and_coding_style)<br> for more details. |

### [](#ierc165)
IERC165

    @contract_interface
    namespace IERC165 {
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    }

### [](#ierc165_api_specification)
IERC165 API Specification

    func supportsInterface(interfaceId: felt) -> (success: felt) {
    }

#### [](#supportsinterface)
`supportsInterface`

Returns true if this contract implements the interface defined by `interfaceId`.

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#erc165_library_functions)
ERC165 Library Functions

    func supports_interface(interface_id: felt) -> (success: felt) {
    }
    
    func register_interface(interface_id: felt) {
    }

#### [](#supportsinterface2)
`supports_interface`

Returns true if this contract implements the interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns:

    success: felt

#### [](#register_interface)
`register_interface`

Calling contract declares support for a specific interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns: None.

[← Security](/contracts-cairo/0.5.0/security)

[Utilities →](/contracts-cairo/0.5.0/utilities)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are derived from a private key, all Starknet accounts are contracts. This means there’s no Externally Owned Account (EOA) concept on Starknet.

Instead, the network features native account abstraction and signature validation happens at the contract level.

For a general overview of account abstraction, see [Starknet’s documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/introduction/)
. A more detailed discussion on the topic can be found in [Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

|     |     |
| --- | --- |
|     | For detailed information on the usage and implementation check the [API Reference](api/account)<br> section. |

[](#standard_account_interface)
Standard Account Interface
----------------------------------------------------------

Accounts in Starknet are smart contracts, and so they can be deployed and interacted with like any other contract, and can be extended to implement any custom logic. However, an account is a special type of contract that is used to validate and execute transactions. For this reason, it must implement a set of entrypoints that the protocol uses for this execution flow. The [SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 proposal defines a standard interface for accounts, supporting this execution flow and interoperability with DApps in the ecosystem.

### [](#isrc6_interface)
ISRC6 Interface

    /// Represents a call to a target contract function.
    struct Call {
        to: ContractAddress,
        selector: felt252,
        calldata: Array<felt252>
    }
    
    /// Standard Account Interface
    trait ISRC6 {
        /// Executes a transaction through the account.
        fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>;
    
        /// Asserts whether the transaction is valid to be executed.
        fn __validate__(calls: Array<Call>) -> felt252;
    
        /// Asserts whether a given signature for a given hash is valid.
        fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 adds the `is_valid_signature` method. This method is not used by the protocol, but it’s useful for DApps to verify the validity of signatures, supporting features like Sign In with Starknet.

SNIP-6 also defines that compliant accounts must implement the SRC5 interface following [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
, as a mechanism for detecting whether a contract is an account or not through introspection.

### [](#isrc5_interface)
ISRC5 Interface

    /// Standard Interface Detection
    trait ISRC5 {
        /// Queries if a contract implements a given interface.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[SNIP-6](https://github.com/ericnordelo/SNIPs/blob/feat/standard-account/SNIPS/snip-6.md)
 compliant accounts must return `true` when queried for the ISRC6 interface Id.

Even though these interfaces are not enforced by the protocol, it’s recommended to implement them for enabling interoperability with the ecosystem.

[](#protocol_level_methods)
Protocol-level methods
--------------------------------------------------

In this section we will describe the methods that the protocol uses for abstracting the accounts. The first two are required for enabling accounts to be used for executing transactions. The rest are optional:

1.  `__validate__` verifies the validity of the transaction to be executed. This is usually used to validate signatures, but the entrypoint implementation can be customized to feature any validation mechanism [with some limitations](https://docs.starknet.io/documentation/architecture_and_concepts/Accounts/validate_and_execute/#validate_limitations)
    .
    
2.  `__execute__` executes the transaction if the validation is successful.
    
3.  `__validate_declare__` optional entrypoint similar to `__validate__` but for transactions meant to declare other contracts.
    
4.  `__validate_deploy__` optional entrypoint similar to `__validate__` but meant for [counterfactual deployments](guides/deployment)
    .
    

|     |     |
| --- | --- |
|     | Although these entrypoints are available to the protocol for its regular transaction flow, they can also be called like any other method. |

[](#deploying_an_account)
Deploying an account
----------------------------------------------

In Starknet there are two ways of deploying smart contracts: using the `deploy_syscall` and doing counterfactual deployments. The former can be easily done with the [Universal Deployer Contract (UDC)](udc)
, a contract that wraps and exposes the `deploy_syscall` to provide arbitrary deployments through regular contract calls. But if you don’t have an account to invoke it, you will probably want to use the latter.

To do counterfactual deployments, you need to implement another protocol-level entrypoint named `__validate_deploy__`. Check the [counterfactual deployments](guides/deployment)
 guide to learn how.

[](#sending_transactions)
Sending transactions
----------------------------------------------

Contracts for Cairo offers two flavors of components to use for creating accounts: `AccountComponent` and `EthAccountComponent`. Though the ISRC6 interface is agnostic regarding validation schemes, both available components utilize public-private key pairs that control the account. The public key is set in the constructor.

Mixin implementations are available to use for both components which include basic account functionality as well as additional features such as the ability to:

*   View and transfer the account’s public key.
    
*   Declare contract class hashes.
    
*   Counterfactually deploy.
    

### [](#accountcomponent)
AccountComponent

To create an account, implement the [AccountMixin](api/account#AccountComponent-Embeddable-Mixin-Impl)
 and set up the constructor to initialize the contract. The [initializer](api/account#AccountComponent-initializer)
 method sets the public key for the account contract and registers the account interface id. A vanilla account contract looks like this:

    #[starknet::contract(account)]
    mod MyAccount {
        use openzeppelin::account::AccountComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccountComponent, storage: account, event: AccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // Account Mixin
        #[abi(embed_v0)]
        impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
        impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            account: AccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccountEvent: AccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: felt252) {
            self.account.initializer(public_key);
        }
    }

To deploy the Contracts for Cairo account variant, compile the contract and declare the class hash because custom accounts are likely not declared. This means that you’ll need an account already deployed.

Next, create the account JSON with Starknet Foundry’s [custom account setup](https://foundry-rs.github.io/starknet-foundry/starknet/account.html#custom-account-contract)
 and include the `--class-hash` flag with the declared class hash. The flag enables custom account variants.

|     |     |
| --- | --- |
|     | The following examples use `sncast` [v0.23.0](https://github.com/foundry-rs/starknet-foundry/releases/tag/v0.23.0)<br>. |

    $ sncast \
      --url http://127.0.0.1:5050 \
      account create \
      --name my-custom-account \
      --class-hash 0x123456...

This command will output the precomputed contract address and the recommended `max-fee`. To counterfactually deploy the account, send funds to the address and then deploy the custom account.

    $ sncast \
      --url http://127.0.0.1:5050 \
      account deploy \
      --name my-custom-account

Once the account is deployed, set the `--account` flag with the custom account name to send transactions from that account.

    $ sncast \
      --account my-custom-account \
      --url http://127.0.0.1:5050 \
      invoke \
      --contract-address 0x123... \
      --function "some_function" \
      --calldata 1 2 3

### [](#ethaccountcomponent)
EthAccountComponent

To create an Ethereum-flavored account, implement the [EthAccountMixin](api/account#EthAccountComponent-Embeddable-Mixin-Impl)
 and set up the constructor to initialize the contract. Since this is an EthAccount, the [initializer](api/account#EthAccountComponent-initializer)
 expects the `EthPublicKey` type (alias for `Secp256k1Point`) to store as the account’s public key. The contract also requires the `Secp256K1Impl` implementation in order to serialize and deserialize the `EthPublicKey` type. A basic Ethereum-flavored account contract looks like this:

    #[starknet::contract(account)]
    mod MyEthAccount {
        use openzeppelin::account::EthAccountComponent;
        use openzeppelin::account::interface::EthPublicKey;
        use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // EthAccount Mixin
        #[abi(embed_v0)]
        impl EthAccountMixinImpl =
            EthAccountComponent::EthAccountMixinImpl<ContractState>;
        impl EthAccountInternalImpl = EthAccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            eth_account: EthAccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            EthAccountEvent: EthAccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: EthPublicKey) {
            self.eth_account.initializer(public_key);
        }
    }

Special tooling is required in order to deploy and send transactions with an Ethereum-flavored account contract. The following examples utilize the [StarknetJS](https://www.starknetjs.com/)
 library.

Compile and declare the contract on the target network. Next, precompute the EthAccount contract address using the declared class hash.

|     |     |
| --- | --- |
|     | The following examples use unreleased features from StarknetJS (`starknetjs@next`) at commit [d002baea0abc1de3ac6e87a671f3dec3757437b3](https://github.com/starknet-io/starknet.js/commit/d002baea0abc1de3ac6e87a671f3dec3757437b3)<br>. |

    import * as dotenv from 'dotenv';
    import { CallData, EthSigner, hash } from 'starknet';
    import { ABI as ETH_ABI } from '../abis/eth_account.js';
    dotenv.config();
    
    // Calculate EthAccount address
    const ethSigner = new EthSigner(process.env.ETH_PRIVATE_KEY);
    const ethPubKey = await ethSigner.getPubKey();
    const ethAccountClassHash = '<ETH_ACCOUNT_CLASS_HASH>';
    const ethCallData = new CallData(ETH_ABI);
    const ethAccountConstructorCalldata = ethCallData.compile('constructor', {
        public_key: ethPubKey
    })
    const salt = '0x12345';
    const deployerAddress = '0x0';
    const ethContractAddress = hash.calculateContractAddressFromHash(
        salt,
        ethAccountClassHash,
        ethAccountConstructorCalldata,
        deployerAddress
    );
    console.log('Pre-calculated EthAccount address: ', ethContractAddress);

Send funds to the pre-calculated EthAccount address and deploy the contract.

    import * as dotenv from 'dotenv';
    import { Account, CallData, EthSigner, RpcProvider, stark } from 'starknet';
    import { ABI as ETH_ABI } from '../abis/eth_account.js';
    dotenv.config();
    
    // Prepare EthAccount
    const provider = new RpcProvider({ nodeUrl: process.env.API_URL });
    const ethSigner = new EthSigner(process.env.ETH_PRIVATE_KEY);
    const ethPubKey = await ethSigner.getPubKey();
    const ethAccountAddress = '<ETH_ACCOUNT_ADDRESS>'
    const ethAccount = new Account(provider, ethAccountAddress, ethSigner);
    
    // Prepare payload
    const ethAccountClassHash = '<ETH_ACCOUNT_CLASS_HASH>'
    const ethCallData = new CallData(ETH_ABI);
    const ethAccountConstructorCalldata = ethCallData.compile('constructor', {
        public_key: ethPubKey
    })
    const salt = '0x12345';
    const deployPayload = {
        classHash: ethAccountClassHash,
        constructorCalldata: ethAccountConstructorCalldata,
        addressSalt: salt,
    };
    
    // Deploy
    const { suggestedMaxFee: feeDeploy } = await ethAccount.estimateAccountDeployFee(deployPayload);
    const { transaction_hash, contract_address } = await ethAccount.deployAccount(
        deployPayload,
        { maxFee: stark.estimatedFeeToMaxFee(feeDeploy, 100) }
    );
    await provider.waitForTransaction(transaction_hash);
    console.log('EthAccount deployed at: ', contract_address);

Once deployed, connect the EthAccount instance to the target contract which enables calls to come from the EthAccount. Here’s what an ERC20 transfer from an EthAccount looks like.

    import * as dotenv from 'dotenv';
    import { Account, RpcProvider, Contract, EthSigner } from 'starknet';
    dotenv.config();
    
    // Prepare EthAccount
    const provider = new RpcProvider({ nodeUrl: process.env.API_URL });
    const ethSigner = new EthSigner(process.env.ETH_PRIVATE_KEY);
    const ethAccountAddress = '<ETH_ACCOUNT_CONTRACT_ADDRESS>'
    const ethAccount = new Account(provider, ethAccountAddress, ethSigner);
    
    // Prepare target contract
    const erc20 = new Contract(compiledErc20.abi, erc20Address, provider);
    
    // Connect EthAccount with the target contract
    erc20.connect(ethAccount);
    
    // Execute ERC20 transfer
    const transferCall = erc20.populate('transfer', {
        recipient: recipient.address,
        amount: 50n
    });
    const tx = await erc20.transfer(
        transferCall.calldata, { maxFee: 900_000_000_000_000 }
    );
    await provider.waitForTransaction(tx.transaction_hash);

[← API Reference](/contracts-cairo/0.13.0/api/access)

[API Reference →](/contracts-cairo/0.13.0/api/account)




 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#OwnableComponent)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControlComponent)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#OwnableComponent)
`OwnableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::OwnableComponent;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

[Embeddable Mixin Implementations](../components#mixins)

OwnableMixinImpl

*   [`OwnableImpl`](#OwnableComponent-Embeddable-Impls-OwnableImpl)
    
*   [`OwnableCamelOnlyImpl`](#OwnableComponent-Embeddable-Impls-OwnableCamelOnlyImpl)
    

OwnableTwoStepMixinImpl

*   [`OwnableTwoStepImpl`](#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl)
    
*   [`OwnableTwoStepCamelOnlyImpl`](#OwnableComponent-Embeddable-Impls-OwnableTwoStepCamelOnlyImpl)
    

Embeddable Implementations

OwnableImpl

*   [`owner(self)`](#OwnableComponent-owner)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-renounce_ownership)
    

OwnableTwoStepImpl

*   [`owner(self)`](#OwnableComponent-two-step-owner)
    
*   [`pending_owner(self)`](#OwnableComponent-two-step-pending_owner)
    
*   [`accept_ownership(self)`](#OwnableComponent-two-step-accept_ownership)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-two-step-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-two-step-renounce_ownership)
    

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#OwnableComponent-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-renounceOwnership)
    

OwnableTwoStepCamelOnlyImpl

*   [`pendingOwner(self)`](#OwnableComponent-two-step-pendingOwner)
    
*   [`acceptOwnership(self)`](#OwnableComponent-two-step-acceptOwnership)
    
*   [`transferOwnership(self, new_owner)`](#OwnableComponent-two-step-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-two-step-renounceOwnership)
    

Internal Implementations

InternalImpl

*   [`initializer(self, owner)`](#OwnableComponent-initializer)
    
*   [`assert_only_owner(self)`](#OwnableComponent-assert_only_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#OwnableComponent-_transfer_ownership)
    
*   [`_propose_owner(self, new_owner)`](#OwnableComponent-_propose_owner)
    
*   [`_accept_ownership(self)`](#OwnableComponent-_accept_ownership)
    

Events

*   [`OwnershipTransferStarted(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferStarted)
    
*   [`OwnershipTransferred(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferred)
    

#### [](#OwnableComponent-Embeddable-Functions)
Embeddable functions

#### [](#OwnableComponent-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-Embeddable-Functions-Two-Step)
Embeddable functions (two step transfer)

#### [](#OwnableComponent-two-step-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-two-step-pending_owner)
`pending_owner(self: @ContractState) → ContractAddress` external

Returns the address of the pending owner.

#### [](#OwnableComponent-two-step-accept_ownership)
`accept_ownership(ref self: ContractState)` external

Transfers ownership of the contract to the pending owner. Can only be called by the pending owner. Resets pending owner to zero address.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-two-step-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Starts the two step ownership transfer process, by setting the pending owner. Can only be called by the current owner.

Emits an [OwnershipTransferStarted](#OwnableComponent-OwnershipTransferStarted)
 event.

#### [](#OwnableComponent-two-step-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#OwnableComponent-transfer_ownership)
.

#### [](#OwnableComponent-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#OwnableComponent-renounce_ownership)
.

#### [](#OwnableComponent-two-step-pendingOwner)
`pendingOwner(self: @ContractState)` external

See [pending\_owner](#OwnableComponent-two-step-pending_owner)
.

#### [](#OwnableComponent-two-step-acceptOwnership)
`acceptOwnership(self: @ContractState)` external

See [accept\_ownership](#OwnableComponent-two-step-accept_ownership)
.

#### [](#OwnableComponent-two-step-transferOwnership)
`transferOwnership(self: @ContractState)` external

See [transfer\_ownership](#OwnableComponent-two-step-transfer_ownership)
.

#### [](#OwnableComponent-two-step-renounceOwnership)
`renounceOwnership(self: @ContractState)` external

See [renounce\_ownership](#OwnableComponent-two-step-renounce_ownership)
.

#### [](#OwnableComponent-Internal-Functions)
Internal functions

#### [](#OwnableComponent-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#OwnableComponent-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-_propose_owner)
`_propose_owner(ref self: ContractState, new_owner: ContractAddress)` internal

Sets a new pending owner in a two step transfer.

Internal function without access restriction.

Emits an [OwnershipTransferStarted](#OwnableComponent-OwnershipTransferStarted)
 event.

#### [](#OwnableComponent-_accept_ownership)
`_accept_ownership(ref self: ContractState)` internal

Transfers ownership to the pending owner. Resets pending owner to zero address. Calls [\_transfer\_ownership](#OwnableComponent-_transfer_ownership)
.

Internal function without access restriction.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-Events)
Events

#### [](#OwnableComponent-OwnershipTransferStarted)
`OwnershipTransferStarted(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the pending owner is updated.

#### [](#OwnableComponent-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/access/accesscontrol/interface.cairo)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [set\_role\_admin](#AccessControlComponent-set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControlComponent)
`AccessControlComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControlComponent;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControlComponent-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [set\_role\_admin](#AccessControlComponent-set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

[Embeddable Mixin Implementations](../components#mixins)

AccessControlMixinImpl

*   [`AccessControlImpl`](#AccessControlComponent-Embeddable-Impls-AccessControlImpl)
    
*   [`AccessControlCamelImpl`](#AccessControlComponent-Embeddable-Impls-AccessControlCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControlComponent-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControlComponent-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControlComponent-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControlComponent-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControlComponent-renounce_role)
    

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControlComponent-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControlComponent-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControlComponent-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControlComponent-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControlComponent-renounceRole)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self)`](#AccessControlComponent-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControlComponent-assert_only_role)
    
*   [`set_role_admin(self, role, admin_role)`](#AccessControlComponent-set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControlComponent-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControlComponent-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControlComponent-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControlComponent-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControlComponent-RoleRevoked)
    

#### [](#AccessControlComponent-Embeddable-Functions)
Embeddable functions

#### [](#AccessControlComponent-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControlComponent-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

To change a role’s admin, use [set\_role\_admin](#AccessControlComponent-set_role_admin)
.

#### [](#AccessControlComponent-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControlComponent-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControlComponent-has_role)
.

#### [](#AccessControlComponent-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControlComponent-get_role_admin)
.

#### [](#AccessControlComponent-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControlComponent-grant_role)
.

#### [](#AccessControlComponent-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControlComponent-revoke_role)
.

#### [](#AccessControlComponent-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControlComponent-renounce_role)
.

#### [](#AccessControlComponent-Internal-Functions)
Internal functions

#### [](#AccessControlComponent-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControlComponent-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControlComponent-set_role_admin)
`set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Internal function without access restriction.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControlComponent-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-Events)
Events

#### [](#AccessControlComponent-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControlComponent-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControlComponent-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access](/contracts-cairo/0.15.0/access)

[Accounts →](/contracts-cairo/0.15.0/accounts)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. The `ERC721.cairo` contract implements an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC721](#ierc721)
    
*   [ERC721 Compatibility](#erc721_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC721 URIs](#interpreting_erc721_uris)
        
    *   [ERC721Received](#erc721received)
        
        *   [IERC721Receiver](#ierc721receiver)
            
        
    *   [Supporting Interfaces](#supporting_interfaces)
        
    *   [Ready\_to\_Use Presets](#ready_to_use_presets)
        
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC721MintableBurnable](#erc721mintableburnable)
        
    *   [ERC721MintablePausable](#erc721mintablepausable)
        
    *   [ERC721EnumerableMintableBurnable](#erc721enumerablemintableburnable)
        
        *   [IERC721Enumerable](#ierc721enumerable)
            
        
    *   [ERC721Metadata](#erc721metadata)
        
        *   [IERC721Metadata](#ierc721metadata)
            
        
    
*   [Utilities](#utilities)
    
    *   [ERC721Holder](#erc721_holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC721`](#ierc721_api)
        
        *   [`balanceOf`](#balanceof)
            
        *   [`ownerOf`](#ownerof)
            
        *   [`safeTransferFrom`](#safetransferfrom)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        *   [`setApprovalForAll`](#setapprovalforall)
            
        *   [`getApproved`](#getapproved)
            
        *   [`isApprovedForAll`](#isapprovedforall)
            
        
    *   [Events](#events)
        
        *   [`Approval (event)`](#approval_event)
            
        *   [`ApprovalForAll (event)`](#approvalforall_event)
            
        *   [`Transfer (event)`](#transfer_event)
            
        
    *   [`IERC721Metadata`](#ierc721metadata)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`tokenURI`](#tokenuri)
            
        
    *   [`IERC721Enumerable`](#ierc721enumerable)
        
        *   [`totalSupply`](#totalsupply)
            
        *   [`tokenByIndex`](#tokenbyindex)
            
        *   [`tokenOfOwnerByIndex`](#tokenofownerbyindex)
            
        
    *   [`IERC721Receiver`](#ierc721receiver_api)
        
        *   [`onERC721Received`](#onerc721received)
            
        
    

[](#ierc721)
IERC721
--------------------

    @contract_interface
    namespace IERC721 {
        func balanceOf(owner: felt) -> (balance: Uint256) {
        }
    
        func ownerOf(tokenId: Uint256) -> (owner: felt) {
        }
    
        func safeTransferFrom(from_: felt, to: felt, tokenId: Uint256, data_len: felt, data: felt*) {
        }
    
        func transferFrom(from_: felt, to: felt, tokenId: Uint256) {
        }
    
        func approve(approved: felt, tokenId: Uint256) {
        }
    
        func setApprovalForAll(operator: felt, approved: felt) {
        }
    
        func getApproved(tokenId: Uint256) -> (approved: felt) {
        }
    
        func isApprovedForAll(owner: felt, operator: felt) -> (approved: felt) {
        }
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    }

### [](#erc721_compatibility)
ERC721 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard in the following ways:

*   It uses Cairo’s `uint256` instead of `felt`.
    
*   It returns `TRUE` as success.
    
*   It makes use of Cairo’s short strings to simulate `name` and `symbol`.
    

But some differences can still be found, such as:

*   `tokenURI` returns a felt representation of the queried token’s URI. The EIP721 standard, however, states that the return value should be of type string. If a token’s URI is not set, the returned value is `0`. Note that URIs cannot exceed 31 characters. See [Interpreting ERC721 URIs](#interpreting_erc721_uris)
    .
    
*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Solidity’s selector calculations. See [Supporting Interfaces](#supporting_interfaces)
    .
    
*   `safeTransferFrom` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721. The difference between both functions consists of accepting `data` as an argument. Because function overloading is currently not possible in Cairo, `safeTransferFrom` by default accepts the `data` argument. If `data` is not used, simply insert `0`.
    
*   `safeTransferFrom` is specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, it accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`.
    
*   `ERC165.register_interface` allows contracts to set and communicate which interfaces they support. This follows OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v0.6.0/contracts/utils/introspection/ERC165Storage.sol)
    .
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info.
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) must support ERC165 by registering the `IERC721Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC721 transfers.
    
*   `ERC721Enumerable` tracks the total number of tokens with the `all_tokens` and `all_tokens_len` storage variables mimicking the array of the Solidity implementation.
    

[](#usage)
Usage
----------------

Use cases go from artwork, digital collectibles, physical property, and many more.

To show a standard use case, we’ll use the `ERC721Mintable` preset which allows for only the owner to `mint` and `burn` tokens. To create a token you need to first deploy both Account and ERC721 contracts respectively. As most StarkNet contracts, ERC721 expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it.

Considering that the ERC721 constructor method looks like this:

    func constructor(
        name: felt,          // Token name as Cairo short string
        symbol: felt,        // Token symbol as Cairo short string
        owner: felt          // Address designated as the contract owner
    ) {
    }

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc721 = await starknet.deploy(
        "contracts/token/erc721/presets/ERC721Mintable.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),                       # name\
            str_to_felt("TKN"),                         # symbol\
            account.contract_address                    # owner\
        ]
    )

To mint a non-fungible token, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    tokenId = uint(1)
    
    await signer.send_transaction(
        account, erc721.contract_address, 'mint', [\
            recipient_address,\
            *tokenId\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `transferFrom` and `safeTransferFrom` to transfer NFTs. If using `transferFrom`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.**

The `safeTransferFrom` method incorporates the following conditional logic:

1.  if the calling address is an account contract, the token transfer will behave as if `transferFrom` was called
    
2.  if the calling address is not an account contract, the safe function will check that the contract supports ERC721 tokens
    

The current implementation of `safeTansferFrom` checks for `onERC721Received` and requires that the recipient contract supports ERC165 and exposes the `supportsInterface` method. See [ERC721Received](#erc721received)
.

### [](#interpreting_erc721_uris)
Interpreting ERC721 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard set in [EIP721](https://eips.ethereum.org/EIPS/eip-721)<br>. Therefore, this library’s ERC721 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC721, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc721.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc721.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc721received)
ERC721Received

In order to be sure a contract can safely accept ERC721 tokens, said contract must implement the `ERC721_Receiver` interface (as expressed in the EIP721 specification). Methods such as `safeTransferFrom` and `safeMint` call the recipient contract’s `onERC721Received` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. `safeTransferFrom` requires a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC721 implementation requires that all contracts that support safe ERC721 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC721Receiver` magic value `0x150b7a02` (which invokes `onERC721Received`). If the recipient contract supports the `IAccount` magic value `0x50b70dcb`, `supportsInterface` should return `TRUE`. Otherwise, `safeTransferFrom` should fail.

#### [](#ierc721receiver)
IERC721Receiver

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

    @contract_interface
    namespace IERC721Receiver {
        func onERC721Received(
            operator: felt, from_: felt, tokenId: Uint256, data_len: felt data: felt*) -> (selector: felt) {
        }
    }

### [](#supporting_interfaces)
Supporting Interfaces

In order to ensure EVM/StarkNet compatibility, this ERC721 implementation does not calculate interface identifiers. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

Further, this implementation stores supported interfaces in a mapping (similar to OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v0.6.0/contracts/utils/introspection/ERC165Storage.sol)
).

### [](#ready_to_use_presets)
Ready-to-Use Presets

ERC721 presets have been created to allow for quick deployments as-is. To be as explicit as possible, each preset includes the additional features they offer in the contract name. For example:

*   `ERC721MintableBurnable` includes `mint` and `burn`.
    
*   `ERC721MintablePausable` includes `mint`, `pause`, and `unpause`.
    
*   `ERC721EnumerableMintableBurnable` includes `mint`, `burn`, and [IERC721Enumerable](#ierc721enumerable)
     methods.
    

Ready-to-use presets are a great option for testing and prototyping. See [Presets](#presets)
.

[](#extensibility)
Extensibility
--------------------------------

Following the [contracts extensibility pattern](extensibility)
, this implementation is set up to include all ERC721 related storage and business logic under a namespace. Developers should be mindful of manually exposing the required methods from the namespace to comply with the standard interface. This is already done in the [preset contracts](#presets)
; however, additional functionality can be added. For instance, you could:

*   Implement a pausing mechanism.
    
*   Add roles such as _owner_ or _minter_.
    
*   Modify the `transferFrom` function to mimic the [`_beforeTokenTransfer` and `_afterTokenTransfer` hooks](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L335)
    .
    

Just be sure that the exposed `external` methods invoke their imported function logic a la `approve` invokes `ERC721.approve`. As an example, see below.

    from openzeppelin.token.erc721.library import ERC721
    
    @external
    func approve{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}(
        to: felt, tokenId: Uint256
    ) {
        ERC721.approve(to, tokenId)
        return()
    }

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset includes a contract owner, which is set in the `constructor`, to offer simple access control on sensitive methods such as `mint` and `burn`.

### [](#erc721mintableburnable)
ERC721MintableBurnable

The `ERC721MintableBurnable` preset offers a quick and easy setup for creating NFTs. The contract owner can create tokens with `mint`, whereas token owners can destroy their tokens with `burn`.

### [](#erc721mintablepausable)
ERC721MintablePausable

The `ERC721MintablePausable` preset creates a contract with pausable token transfers and minting capabilities. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug. In this preset, only the contract owner can `mint`, `pause`, and `unpause`.

### [](#erc721enumerablemintableburnable)
ERC721EnumerableMintableBurnable

The `ERC721EnumerableMintableBurnable` preset adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This allows contracts to publish its full list of NFTs and make them discoverable.

In regard to implementation, contracts should expose the following view methods:

*   `ERC721Enumerable.total_supply`
    
*   `ERC721Enumerable.token_by_index`
    
*   `ERC721Enumerable.token_of_owner_by_index`
    

In order for the tokens to be correctly indexed, the contract should also use the following methods (which supersede some of the base `ERC721` methods):

*   `ERC721Enumerable.transfer_from`
    
*   `ERC721Enumerable.safe_transfer_from`
    
*   `ERC721Enumerable._mint`
    
*   `ERC721Enumerable._burn`
    

#### [](#ierc721enumerable)
IERC721Enumerable

    @contract_interface
    namespace IERC721Enumerable {
        func totalSupply() -> (totalSupply: Uint256) {
        }
    
        func tokenByIndex(index: Uint256) -> (tokenId: Uint256) {
        }
    
        func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256) {
        }
    }

### [](#erc721metadata)
ERC721Metadata

The `ERC721Metadata` extension allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

We follow OpenZeppelin’s Solidity approach of integrating the Metadata methods `name`, `symbol`, and `tokenURI` into all ERC721 implementations. If preferred, a contract can be created that does not import the Metadata methods from the `ERC721` library. Note that the `IERC721Metadata` interface id should be removed from the constructor as well.

#### [](#ierc721metadata)
IERC721Metadata

    @contract_interface
    namespace IERC721Metadata {
        func name() -> (name: felt) {
        }
    
        func symbol() -> (symbol: felt) {
        }
    
        func tokenURI(tokenId: Uint256) -> (tokenURI: felt) {
        }
    }

[](#utilities)
Utilities
------------------------

### [](#erc721holder)
ERC721Holder

Implementation of the `IERC721Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC721.safeTransferFrom`, `IERC721.approve` or `IERC721.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC721Received](#erc721received)

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc721_api)
IERC721 API

    func balanceOf(owner: felt) -> (balance: Uint256) {
    }
    
    func ownerOf(tokenId: Uint256) -> (owner: felt) {
    }
    
    func safeTransferFrom(from_: felt, to: felt, tokenId: Uint256, data_len: felt, data: felt*) {
    }
    
    func transferFrom(from_: felt, to: felt, tokenId: Uint256) {
    }
    
    func approve(approved: felt, tokenId: Uint256) {
    }
    
    func setApprovalForAll(operator: felt, approved: felt) {
    }
    
    func getApproved(tokenId: Uint256) -> (approved: felt) {
    }
    
    func isApprovedForAll(owner: felt, operator: felt) -> (approved: felt) {
    }

#### [](#balanceof)
`balanceOf`

Returns the number of tokens in `owner`'s account.

Parameters:

    owner: felt

Returns:

    balance: Uint256

#### [](#ownerof)
`ownerOf`

Returns the owner of the `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    owner: felt

#### [](#safetransferfrom)
`safeTransferFrom`

Safely transfers `tokenId` token from `from_` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [ERC721Received](#erc721received)
.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#transferfrom)
`transferFrom`

Transfers `tokenId` token from `from_` to `to`. **The caller is responsible to confirm that `to` is capable of receiving NFTs or else they may be permanently lost**.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

Returns: None.

#### [](#approve)
`approve`

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Emits an [Approval](#approval_event)
 event.

Parameters:

    to: felt
    tokenId: Uint256

Returns: None.

#### [](#getapproved)
`getApproved`

Returns the account approved for `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    operator: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.

Emits an [ApprovalForAll](#approvalforall_event)
 event.

Parameters:

    operator: felt

Returns: None.

#### [](#isapprovedforall)
`isApprovedForAll`

Returns if the `operator` is allowed to manage all of the assets of `owner`.

Parameters:

    owner: felt
    operator: felt

Returns:

    approved: felt

### [](#events)
Events

#### [](#approval_event)
`Approval (Event)`

Emitted when `owner` enables `approved` to manage the `tokenId` token.

Parameters:

    owner: felt
    approved: felt
    tokenId: Uint256

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    owner: felt
    operator: felt
    approved: felt

#### [](#transfer_event)
`Transfer (Event)`

Emitted when `tokenId` token is transferred from `from_` to `to`.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

* * *

### [](#ierc721metadata_api)
IERC721Metadata API

    func name() -> (name: felt) {
    }
    
    func symbol() -> (symbol: felt) {
    }
    
    func tokenURI(tokenId: Uint256) -> (tokenURI: felt) {
    }

#### [](#name)
`name`

Returns the token collection name.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the token collection symbol.

Parameters: None.

Returns:

    symbol: felt

#### [](#tokenuri)
`tokenURI`

Returns the Uniform Resource Identifier (URI) for `tokenID` token. If the URI is not set for the `tokenId`, the return value will be `0`.

Parameters:

    tokenId: Uint256

Returns:

    tokenURI: felt

* * *

### [](#ierc721enumerable_api)
IERC721Enumerable API

    func totalSupply() -> (totalSupply: Uint256) {
    }
    
    func tokenByIndex(index: Uint256) -> (tokenId: Uint256) {
    }
    
    func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256) {
    }

#### [](#totalsupply)
`totalSupply`

Returns the total amount of tokens stored by the contract.

Parameters: None

Returns:

    totalSupply: Uint256

#### [](#tokenbyindex)
`tokenByIndex`

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [balanceOf](#balanceof)
 to enumerate all of `owner`'s tokens.

Parameters:

    index: Uint256

Returns:

    tokenId: Uint256

#### [](#tokenofownerbyindex)
`tokenOfOwnerByIndex`

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [totalSupply](#totalsupply)
 to enumerate all tokens.

Parameters:

    owner: felt
    index: Uint256

Returns:

    tokenId: Uint256

* * *

### [](#ierc721receiver_api)
IERC721Receiver API

    func onERC721Received(
        operator: felt, from_: felt, tokenId: Uint256, data_len: felt data: felt*
    ) -> (selector: felt) {
    }

#### [](#onerc721received)
`onERC721Received`

Whenever an IERC721 `tokenId` token is transferred to this non-account contract via `safeTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC20](/contracts-cairo/0.6.0/erc20)

[ERC1155 →](/contracts-cairo/0.6.0/erc1155)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides context, reasoning, and examples for methods and constants found in `tests/utils.py`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Constants](#constants)
    
*   [Strings](#strings)
    
    *   [`str_to_felt`](#str_to_felt)
        
    *   [`felt_to_str`](#felt_to_str)
        
    
*   [Uint256](#uint256)
    
    *   [`uint`](#uint)
        
    *   [`to_uint`](#to_uint)
        
    *   [`from_uint`](#from_uint)
        
    *   [`add_uint`](#add_uint)
        
    *   [`sub_uint`](#sub_uint)
        
    
*   [Assertions](#assertions)
    
    *   [`assert_revert`](#assert_revert)
        
    *   [`assert_revert_entry_point`](#assert_revert_entry_point)
        
    *   [`assert_events_emitted`](#assert_event_emitted)
        
    
*   [Memoization](#memoization)
    
    *   [`get_contract_class`](#get_contract_class)
        
    *   [`cached_contract`](#cached_contract)
        
    
*   [State](#state)
    
*   [Account](#account)
    
*   [MockSigner](#mocksigner)
    

[](#constants)
Constants
------------------------

To ease the readability of Cairo contracts, this project includes reusable [constant variables](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 like `UINT8_MAX`, or EIP165 interface IDs such as `IERC165_ID` or `IERC721_ID`. For more information on how interface ids are calculated, see the [ERC165 documentation](introspection#interface_calculations)
.

[](#strings)
Strings
--------------------

Cairo currently only provides support for short string literals (less than 32 characters). Note that short strings aren’t really strings, rather, they’re representations of Cairo field elements. The following methods provide a simple conversion to/from field elements.

### [](#str_to_felt)
`str_to_felt`

Takes an ASCII string and converts it to a field element via big endian representation.

### [](#felt_to_str)
`felt_to_str`

Takes an integer and converts it to an ASCII string by trimming the null bytes and decoding the remaining bits.

[](#uint256)
Uint256
--------------------

Cairo’s native data type is a field element (felt). Felts equate to 252 bits which poses a problem regarding 256-bit integer integration. To resolve the bit discrepancy, Cairo represents 256-bit integers as a struct of two 128-bit integers. Further, the low bits precede the high bits e.g.

    1 = (1, 0)
    1 << 128 = (0, 1)
    (1 << 128) - 1 = (340282366920938463463374607431768211455, 0)

### [](#uint)
`uint`

Converts a simple integer into a uint256-ish tuple.

> Note `to_uint` should be used in favor of `uint`, as `uint` only returns the low bits of the tuple.

### [](#to_uint)
`to_uint`

Converts an integer into a uint256-ish tuple.

    x = to_uint(340282366920938463463374607431768211456)
    print(x)
    # prints (0, 1)

### [](#from_uint)
`from_uint`

Converts a uint256-ish tuple into an integer.

    x = (0, 1)
    y = from_uint(x)
    print(y)
    # prints 340282366920938463463374607431768211456

### [](#add_uint)
`add_uint`

Performs addition between two uint256-ish tuples and returns the sum as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = add_uint(x, y)
    print(z)
    # prints (1, 1)

### [](#sub_uint)
`sub_uint`

Performs subtraction between two uint256-ish tuples and returns the difference as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = sub_uint(x, y)
    print(z)
    # prints (340282366920938463463374607431768211455, 0)

### [](#mul_uint)
`mul_uint`

Performs multiplication between two uint256-ish tuples and returns the product as a uint256-ish tuple.

    x = (0, 10)
    y = (2, 0)
    z = mul_uint(x, y)
    print(z)
    # prints (0, 20)

### [](#div_rem_uint)
`div_rem_uint`

Performs division between two uint256-ish tuples and returns both the quotient and remainder as uint256-ish tuples respectively.

    x = (1, 100)
    y = (0, 25)
    z = div_rem_uint(x, y)
    print(z)
    # prints ((4, 0), (1, 0))

[](#assertions)
Assertions
--------------------------

In order to abstract away some of the verbosity regarding test assertions on StarkNet transactions, this project includes the following helper methods:

### [](#assert_revert)
`assert_revert`

An asynchronous wrapper method that executes a try-except pattern for transactions that should fail. Note that this wrapper does not check for a StarkNet error code. This allows for more flexibility in checking that a transaction simply failed. If you wanted to check for an exact error code, you could use StarkNet’s [error\_codes module](https://github.com/starkware-libs/cairo-lang/blob/ed6cf8d6cec50a6ad95fa36d1eb4a7f48538019e/src/starkware/starknet/definitions/error_codes.py)
 and implement additional logic to the `assert_revert` method.

To successfully use this wrapper, the transaction method should be wrapped with `assert_revert`; however, `await` should precede the wrapper itself like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    )

This wrapper also includes the option to check that an error message was included in the reversion. To check that the reversion sends the correct error message, add the `reverted_with` keyword argument outside of the actual transaction (but still inside the wrapper) like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ]),
        reverted_with="insert error message here"
    )

### [](#assert_revert_entry_point)
`assert_revert_entry_point`

An extension of `assert_revert` that asserts an entry point error occurs with the given `invalid_selector` parameter. This assertion is especially useful in checking proxy/implementation contracts. To use `assert_revert_entry_point`:

    await assert_revert_entry_point(
        signer.send_transaction(
            account, contract.contract_address, 'nonexistent_selector', []
        ),
        invalid_selector='nonexistent_selector'
    )

### [](#assert_event_emitted)
`assert_event_emitted`

A helper method that checks a transaction receipt for the contract emitting the event (`from_address`), the emitted event itself (`name`), and the arguments emitted (`data`). To use `assert_event_emitted`:

    # capture the tx receipt
    tx_exec_info = await signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    
    # insert arguments to assert
    assert_event_emitted(
        tx_exec_info,
        from_address=contract.contract_address,
        name='Foo_emitted',
        data=[\
            account.contract_address,\
            recipient,\
            *token\
        ]
    )

[](#memoization)
Memoization
----------------------------

Memoizing functions allow for quicker and computationally cheaper calculations which is immensely beneficial while testing smart contracts.

### [](#get_contract_class)
`get_contract_class`

A helper method that returns the contract class from the contract’s name. To capture the contract class, simply add the contract’s name as an argument like this:

    contract_class = get_contract_class('ContractName')

If multiple contracts exist with the same name, then the contract’s path must be passed along with the `is_path` flag instead of the name. To pass the contract’s path:

    contract_class = get_contract_class('path/to/Contract.cairo', is_path=True)

### [](#cached_contract)
`cached_contract`

A helper method that returns the cached state of a given contract. It’s recommended to first deploy all the relevant contracts before caching the state. The requisite contracts in the testing module should each be instantiated with `cached_contract` in a fixture after the state has been copied. The memoization pattern with `cached_contract` should look something like this:

    # get contract classes
    @pytest.fixture(scope='module')
    def contract_classes():
      foo_cls = get_contract_class('Foo')
      return foo_cls
    
    # deploy contracts
    @pytest.fixture(scope='module')
    async def foo_init(contract_classes):
        foo_cls = contract_classes
        starknet = await Starknet.empty()
        foo = await starknet.deploy(
            contract_class=foo_cls,
            constructor_calldata=[]
        )
        return starknet.state, foo  # return state and all deployed contracts
    
    # memoization
    @pytest.fixture(scope='module')
    def foo_factory(contract_classes, foo_init):
        foo_cls = contract_classes                          # contract classes
        state, foo = foo_init                               # state and deployed contracts
        _state = state.copy()                               # copy the state
        cached_foo = cached_contract(_state, foo_cls, foo)  # cache contracts
        return cached_foo                                   # return cached contracts

[](#state)
State
----------------

The `State` class provides a wrapper for initializing the StarkNet state which acts as a helper for the `Account` class. This wrapper allows `Account` deployments to share the same initialized state without explicitly passing the instantiated StarkNet state to `Account`. Initializing the state should look like this:

    from utils import State
    
    starknet = await State.init()

[](#account)
Account
--------------------

The `Account` class abstracts away most of the boilerplate for deploying accounts. Instantiating accounts with this class requires the StarkNet state to be instantiated first with the `State.init()` method like this:

    from utils import State, Account
    
    starknet = await State.init()
    account1 = await Account.deploy(public_key)
    account2 = await Account.deploy(public_key)

The Account class also provides access to the account contract class which is useful for following the [Memoization](#memoization)
 pattern. To fetch the account contract class:

    fetch_class = Account.get_class

[](#mocksigner)
MockSigner
--------------------------

`MockSigner` is used to perform transactions with an instance of [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 on a given Account, crafting the transaction and managing nonces. The `Signer` instance manages signatures and is leveraged by `MockSigner` to operate with the Account contract’s `__execute__` method. See [MockSigner utility](accounts#mocksigner_utility)
 for more information.

[← Introspection](/contracts-cairo/0.3.2/introspection)

[Contracts for Solidity →](/contracts/5.x/)




 Introspection - OpenZeppelin Docs       

Introspection
=============

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [ERC165](#erc165)
    
    *   [Interface calculations](#interface_calculations)
        
    *   [Registering interfaces](#registering_interfaces)
        
    *   [Querying interfaces](#querying_interfaces)
        
    *   [IERC165](#ierc165)
        
    *   [IERC165 API Specification](#ierc165_api_specification)
        
        *   [`supportsInterface`](#supportsinterface)
            
        
    *   [ERC165 Library Functions](#erc165_library_functions)
        
        *   [`supports_interface`](#supportsinterface2)
            
        *   [`register_interface`](#register_interface)
            
        
    

[](#erc165)
ERC165
------------------

The ERC165 standard allows smart contracts to exercise [type introspection](https://en.wikipedia.org/wiki/Type_introspection)
 on other contracts, that is, examining which functions can be called on them. This is usually referred to as a contract’s interface.

Cairo contracts, like Ethereum contracts, have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. ERC20 tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract declaring its interface can be very helpful in preventing errors.

It should be noted that the [constants library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 includes constant variables referencing all of the interface ids used in these contracts. This allows for more legible code i.e. using `IERC165_ID` instead of `0x01ffc9a7`.

### [](#interface_calculations)
Interface calculations

In order to ensure EVM/StarkNet compatibility, interface identifiers are not calculated on StarkNet. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, the contract should import the ERC165 library and register its support. It’s recommended to register interface support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    from openzeppelin.introspection.erc165.library import ERC165
    
    INTERFACE_ID = 0x12345678
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        ERC165.register_interface(INTERFACE_ID)
        return ()
    end

### [](#querying_interfaces)
Querying interfaces

To query a target contract’s support for an interface, the querying contract should call `supportsInterface` through IERC165 with the target contract’s address and the queried interface id. Here’s an example:

    from openzeppelin.introspection.erc265.IERC165 import IERC165
    
    INTERFACE_ID = 0x12345678
    
    func check_support{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            target_contract: felt,
        ) -> (success: felt):
        let (is_supported) = IERC165.supportsInterface(target_contract, INTERFACE_ID)
        return (is_supported)
    end

|     |     |
| --- | --- |
|     | `supportsInterface` is camelCased because it is an exposed contract method as part of ERC165’s interface. This differs from library methods (such as `supports_interface` from the [ERC165 library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/introspection/erc165/library.cairo)<br>) which are snake\_cased and not exposed. See the [Function names and coding style](extensibility#function_names_and_coding_style)<br> for more details. |

### [](#ierc165)
IERC165

    @contract_interface
    namespace IERC165:
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#ierc165_api_specification)
IERC165 API Specification

    func supportsInterface(interfaceId: felt) -> (success: felt):
    end

#### [](#supportsinterface)
`supportsInterface`

Returns true if this contract implements the interface defined by `interfaceId`.

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#erc165_library_functions)
ERC165 Library Functions

    func supports_interface(interface_id: felt) -> (success: felt):
    end
    
    func register_interface(interface_id: felt):
    end

#### [](#supportsinterface2)
`supports_interface`

Returns true if this contract implements the interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns:

    success: felt

#### [](#register_interface)
`register_interface`

Calling contract declares support for a specific interface defined by `interface_id`.

Parameters:

    interface_id: felt

Returns: None.

[← Security](/contracts-cairo/0.3.2/security)

[Utilities →](/contracts-cairo/0.3.2/utilities)




 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [OwnableComponent](api/access#OwnableComponent)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#OwnableComponent-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        // Ownable Mixin
        #[abi(embed_v0)]
        impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `OwnableMixinImpl` implementation:

    #[starknet::interface]
    pub trait OwnableABI {
        // IOwnable
        fn owner() -> ContractAddress;
        fn transfer_ownership(new_owner: ContractAddress);
        fn renounce_ownership();
    
        // IOwnableCamelOnly
        fn transferOwnership(newOwner: ContractAddress);
        fn renounceOwnership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

### [](#two_step_transfer)
Two step transfer

The component also offers a more robust way of transferring ownership via the [OwnableTwoStepImpl](api/access#OwnableTwoStepImpl)
 implementation. A two step transfer mechanism helps to prevent unintended and irreversible owner transfers. Simply replace the `OwnableMixinImpl` with its respective two step variant:

    #[abi(embed_v0)]
    impl OwnableTwoStepMixinImpl = OwnableComponent::OwnableTwoStepMixinImpl<ContractState>;

#### [](#interface-twostep)
Interface

This is the full interface of the two step `OwnableTwoStepMixinImpl` implementation:

    #[starknet::interface]
    pub trait OwnableTwoStepABI {
        // IOwnableTwoStep
        fn owner() -> ContractAddress;
        fn pending_owner() -> ContractAddress;
        fn accept_ownership();
        fn transfer_ownership(new_owner: ContractAddress);
        fn renounce_ownership();
    
        // IOwnableTwoStepCamelOnly
        fn pendingOwner() -> ContractAddress;
        fn acceptOwnership();
        fn transferOwnership(newOwner: ContractAddress);
        fn renounceOwnership();
    }

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#OwnableComponent-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing [AccessControl](api/access#AccessControlComponent)
 on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20.mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20.mint(recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControlComponent)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#OwnableComponent)
. Where [AccessControl](api/access#AccessControlComponent)
 shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20.mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20.mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20.burn(account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControlComponent-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControlComponent-grant_role)
 and [`revoke_role`](api/access#AccessControlComponent-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControlComponent-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20.mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20.mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20.burn(account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControlMixinImpl` implementation:

    #[starknet::interface]
    pub trait AccessControlABI {
        // IAccessControl
        fn has_role(role: felt252, account: ContractAddress) -> bool;
        fn get_role_admin(role: felt252) -> felt252;
        fn grant_role(role: felt252, account: ContractAddress);
        fn revoke_role(role: felt252, account: ContractAddress);
        fn renounce_role(role: felt252, account: ContractAddress);
    
        // IAccessControlCamel
        fn hasRole(role: felt252, account: ContractAddress) -> bool;
        fn getRoleAdmin(role: felt252) -> felt252;
        fn grantRole(role: felt252, account: ContractAddress);
        fn revokeRole(role: felt252, account: ContractAddress);
        fn renounceRole(role: felt252, account: ContractAddress);
    
        // ISRC5
        fn supports_interface(interface_id: felt252) -> bool;
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← SNIP12 and Typed Messages](/contracts-cairo/0.15.0/guides/snip12)

[API Reference →](/contracts-cairo/0.15.0/api/access)




 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/access/ownable/ownable.cairo)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#OwnableComponent-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        #[abi(embed_v0)]
        impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
        #[abi(embed_v0)]
        impl OwnableCamelOnlyImpl =
            OwnableComponent::OwnableCamelOnlyImpl<ContractState>;
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `Ownable` implementation:

    trait IOwnable {
        /// Returns the current owner.
        fn owner() -> ContractAddress;
    
        /// Transfers the ownership from the current owner to a new owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

### [](#two_step_transfer)
Two step transfer

The component also offers a more robust way of transferring ownership via the [OwnableTwoStepImpl](api/access#OwnableTwoStepImpl)
 implementation. A two step transfer mechanism helps to prevent unintended and irreversible owner transfers. Simply replace the `OwnableImpl` and `OwnableCamelOnlyImpl` with their respective two step variants:

    #[abi(embed_v0)]
    impl OwnableTwoStepImpl = OwnableComponent::OwnableTwoStepImpl<ContractState>;
    #[abi(embed_v0)]
    impl OwnableTwoStepCamelOnlyImpl =
        OwnableComponent::OwnableTwoStepCamelOnlyImpl<ContractState>;

#### [](#interface-twostep)
Interface

This is the full interface of the two step `Ownable` implementation:

    trait IOwnableTwoStep {
        /// Returns the address of the current owner.
        fn owner() -> ContractAddress;
    
        /// Returns the address of the pending owner.
        fn pending_owner() -> ContractAddress;
    
        /// Finishes the two-step ownership transfer process
        /// by accepting the ownership.
        fn accept_ownership();
    
        /// Starts the two-step ownership transfer process
        /// by setting the pending owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#OwnableComponent-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing `AccessControl` on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControlComponent)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#OwnableComponent)
. Where `AccessControl` shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControlComponent-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControlComponent-grant_role)
 and [`revoke_role`](api/access#AccessControlComponent-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControlComponent-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::ERC20Component;
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControl` implementation:

    trait IAccessControl {
        /// Returns whether the account has the role or not.
        fn has_role(role: felt252, account: ContractAddress) -> bool;
    
        /// Returns the adming role that controls `role`.
        fn get_role_admin(role: felt252) -> felt252;
    
        /// Grants `role` to `account`.
        fn grant_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from `account`.
        fn revoke_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from self.
        fn renounce_role(role: felt252, account: ContractAddress);
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← Counterfactual Deployments](/contracts-cairo/0.10.0/guides/deployment)

[API Reference →](/contracts-cairo/0.10.0/api/access)




 Access Control - OpenZeppelin Docs       

Access Control
==============

This directory provides ways to restrict who can access the functions of a contract or when they can do it.

*   [Ownable](#OwnableComponent)
     is a simple mechanism with a single "owner" role that can be assigned to a single account. This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it.
    
*   [AccessControl](#AccessControlComponent)
     provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
    

[](#authorization)
Authorization
--------------------------------

### [](#OwnableComponent)
`OwnableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/access/ownable/ownable.cairo)

    use openzeppelin::access::ownable::OwnableComponent;

`Ownable` provides a basic access control mechanism where an account (an owner) can be granted exclusive access to specific functions.

This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner.

[Embeddable Mixin Implementations](../components#mixins)

OwnableMixinImpl

*   [`OwnableImpl`](#OwnableComponent-Embeddable-Impls-OwnableImpl)
    
*   [`OwnableCamelOnlyImpl`](#OwnableComponent-Embeddable-Impls-OwnableCamelOnlyImpl)
    

OwnableTwoStepMixinImpl

*   [`OwnableTwoStepImpl`](#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl)
    
*   [`OwnableTwoStepCamelOnlyImpl`](#OwnableComponent-Embeddable-Impls-OwnableTwoStepCamelOnlyImpl)
    

Embeddable Implementations

OwnableImpl

*   [`owner(self)`](#OwnableComponent-owner)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-renounce_ownership)
    

OwnableTwoStepImpl

*   [`owner(self)`](#OwnableComponent-two-step-owner)
    
*   [`pending_owner(self)`](#OwnableComponent-two-step-pending_owner)
    
*   [`accept_ownership(self)`](#OwnableComponent-two-step-accept_ownership)
    
*   [`transfer_ownership(self, new_owner)`](#OwnableComponent-two-step-transfer_ownership)
    
*   [`renounce_ownership(self)`](#OwnableComponent-two-step-renounce_ownership)
    

OwnableCamelOnlyImpl

*   [`transferOwnership(self, newOwner)`](#OwnableComponent-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-renounceOwnership)
    

OwnableTwoStepCamelOnlyImpl

*   [`pendingOwner(self)`](#OwnableComponent-two-step-pendingOwner)
    
*   [`acceptOwnership(self)`](#OwnableComponent-two-step-acceptOwnership)
    
*   [`transferOwnership(self, new_owner)`](#OwnableComponent-two-step-transferOwnership)
    
*   [`renounceOwnership(self)`](#OwnableComponent-two-step-renounceOwnership)
    

Internal Implementations

InternalImpl

*   [`initializer(self, owner)`](#OwnableComponent-initializer)
    
*   [`assert_only_owner(self)`](#OwnableComponent-assert_only_owner)
    
*   [`_accept_ownership(self)`](#OwnableComponent-_accept_ownership)
    
*   [`_propose_owner(self, new_owner)`](#OwnableComponent-_propose_owner)
    
*   [`_transfer_ownership(self, new_owner)`](#OwnableComponent-_transfer_ownership)
    

Events

*   [`OwnershipTransferStarted(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferStarted)
    
*   [`OwnershipTransferred(previous_owner, new_owner)`](#OwnableComponent-OwnershipTransferred)
    

#### [](#OwnableComponent-Embeddable-Functions)
Embeddable functions

#### [](#OwnableComponent-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-Embeddable-Functions-Two-Step)
Embeddable functions (two step transfer)

#### [](#OwnableComponent-two-step-owner)
`owner(self: @ContractState) → ContractAddress` external

Returns the address of the current owner.

#### [](#OwnableComponent-two-step-pending_owner)
`pending_owner(self: @ContractState) → ContractAddress` external

Returns the address of the pending owner.

#### [](#OwnableComponent-two-step-accept_ownership)
`accept_ownership(ref self: ContractState)` external

Transfers ownership of the contract to the pending owner. Can only be called by the pending owner. Resets pending owner to zero address.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-two-step-transfer_ownership)
`transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` external

Starts the two step ownership transfer process, by setting the pending owner. Can only be called by the current owner.

Emits an [OwnershipTransferStarted](#OwnableComponent-OwnershipTransferStarted)
 event.

#### [](#OwnableComponent-two-step-renounce_ownership)
`renounce_ownership(ref self: ContractState)` external

Leaves the contract without owner. It will not be possible to call `assert_only_owner` functions anymore. Can only be called by the current owner.

|     |     |
| --- | --- |
|     | Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |

#### [](#OwnableComponent-transferOwnership)
`transferOwnership(ref self: ContractState, newOwner: ContractAddress)` external

See [transfer\_ownership](#OwnableComponent-transfer_ownership)
.

#### [](#OwnableComponent-renounceOwnership)
`renounceOwnership(ref self: ContractState)` external

See [renounce\_ownership](#OwnableComponent-renounce_ownership)
.

#### [](#OwnableComponent-two-step-pendingOwner)
`pendingOwner(self: @ContractState)` external

See [pending\_owner](#OwnableComponent-two-step-pending_owner)
.

#### [](#OwnableComponent-two-step-acceptOwnership)
`acceptOwnership(self: @ContractState)` external

See [accept\_ownership](#OwnableComponent-two-step-accept_ownership)
.

#### [](#OwnableComponent-two-step-transferOwnership)
`transferOwnership(self: @ContractState)` external

See [transfer\_ownership](#OwnableComponent-two-step-transfer_ownership)
.

#### [](#OwnableComponent-two-step-renounceOwnership)
`renounceOwnership(self: @ContractState)` external

See [renounce\_ownership](#OwnableComponent-two-step-renounce_ownership)
.

#### [](#OwnableComponent-Internal-Functions)
Internal functions

#### [](#OwnableComponent-initializer)
`initializer(ref self: ContractState, owner: ContractAddress)` internal

Initializes the contract and sets `owner` as the initial owner.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-assert_only_owner)
`assert_only_owner(self: @ContractState)` internal

Panics if called by any account other than the owner.

#### [](#OwnableComponent-_accept_ownership)
`_accept_ownership(ref self: ContractState)` internal

Transfers ownership to the pending owner. Resets pending owner to zero address. Calls [\_transfer\_ownership](#OwnableComponent-_transfer_ownership)
.

Internal function without access restriction.

#### [](#OwnableComponent-_propose_owner)
`_propose_owner(ref self: ContractState, new_owner: ContractAddress)` internal

Sets a new pending owner in a two step transfer.

Internal function without access restriction.

Emits an [OwnershipTransferStarted](#OwnableComponent-OwnershipTransferStarted)
 event.

#### [](#OwnableComponent-_transfer_ownership)
`_transfer_ownership(ref self: ContractState, new_owner: ContractAddress)` internal

Transfers ownership of the contract to a new account (`new_owner`). Internal function without access restriction.

Emits an [OwnershipTransferred](#OwnableComponent-OwnershipTransferred)
 event.

#### [](#OwnableComponent-Events)
Events

#### [](#OwnableComponent-OwnershipTransferStarted)
`OwnershipTransferStarted(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the pending owner is updated.

#### [](#OwnableComponent-OwnershipTransferred)
`OwnershipTransferred(previous_owner: ContractAddress, new_owner: ContractAddress)` event

Emitted when the ownership is transferred.

### [](#IAccessControl)
`IAccessControl`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/access/accesscontrol/interface.cairo)

    use openzeppelin::access::accesscontrol::interface::IAccessControl;

External interface of AccessControl.

[SRC5 ID](introspection#ISRC5)

0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751

Functions

*   [`has_role(role, account)`](#IAccessControl-has_role)
    
*   [`get_role_admin(role)`](#IAccessControl-get_role_admin)
    
*   [`grant_role(role, account)`](#IAccessControl-grant_role)
    
*   [`revoke_role(role, account)`](#IAccessControl-revoke_role)
    
*   [`renounce_role(role, account)`](#IAccessControl-renounce_role)
    

Events

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#IAccessControl-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#IAccessControl-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#IAccessControl-RoleRevoked)
    

#### [](#IAccessControl-Functions)
Functions

#### [](#IAccessControl-has_role)
`has_role(role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#IAccessControl-get_role_admin)
`get_role_admin(role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#IAccessControl-grant_role)
`grant_role(role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-revoke_role)
`revoke_role(role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

#### [](#IAccessControl-renounce_role)
`renounce_role(role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#IAccessControl-grant_role)
 and [revoke\_role](#IAccessControl-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

#### [](#IAccessControl-Events)
Events

#### [](#IAccessControl-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 not being emitted signaling this.

#### [](#IAccessControl-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

#### [](#IAccessControl-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

Emitted when `account` is revoked `role`.

`sender` is the account that originated the contract call:

*   if using `revoke_role`, it is the admin role bearer.
    
*   if using `renounce_role`, it is the role bearer (i.e. `account`).
    

### [](#AccessControlComponent)
`AccessControlComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/access/accesscontrol/accesscontrol.cairo)

    use openzeppelin::access::accesscontrol::AccessControlComponent;

Component that allows contracts to implement role-based access control mechanisms. Roles are referred to by their `felt252` identifier:

    const MY_ROLE: felt252 = selector!("MY_ROLE");

Roles can be used to represent a set of permissions. To restrict access to a function call, use [`assert_only_role`](#AccessControlComponent-assert_only_role)
:

    (...)
    
    #[external(v0)]
    fn foo(ref self: ContractState) {
        self.accesscontrol.assert_only_role(MY_ROLE);
    
        // Do something
    }

Roles can be granted and revoked dynamically via the [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
 functions. Each role has an associated admin role, and only accounts that have a role’s admin role can call [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

|     |     |
| --- | --- |
|     | The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. |

[Embeddable Mixin Implementations](../components#mixins)

AccessControlMixinImpl

*   [`AccessControlImpl`](#AccessControlComponent-Embeddable-Impls-AccessControlImpl)
    
*   [`AccessControlCamelImpl`](#AccessControlComponent-Embeddable-Impls-AccessControlCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

AccessControlImpl

*   [`has_role(self, role, account)`](#AccessControlComponent-has_role)
    
*   [`get_role_admin(self, role)`](#AccessControlComponent-get_role_admin)
    
*   [`grant_role(self, role, account)`](#AccessControlComponent-grant_role)
    
*   [`revoke_role(self, role, account)`](#AccessControlComponent-revoke_role)
    
*   [`renounce_role(self, role, account)`](#AccessControlComponent-renounce_role)
    

AccessControlCamelImpl

*   [`hasRole(self, role, account)`](#AccessControlComponent-hasRole)
    
*   [`getRoleAdmin(self, role)`](#AccessControlComponent-getRoleAdmin)
    
*   [`grantRole(self, role, account)`](#AccessControlComponent-grantRole)
    
*   [`revokeRole(self, role, account)`](#AccessControlComponent-revokeRole)
    
*   [`renounceRole(self, role, account)`](#AccessControlComponent-renounceRole)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal Implementations

InternalImpl

*   [`initializer(self)`](#AccessControlComponent-initializer)
    
*   [`assert_only_role(self, role)`](#AccessControlComponent-assert_only_role)
    
*   [`_set_role_admin(self, role, admin_role)`](#AccessControlComponent-_set_role_admin)
    
*   [`_grant_role(self, role, account)`](#AccessControlComponent-_grant_role)
    
*   [`_revoke_role(self, role, account)`](#AccessControlComponent-_revoke_role)
    

Events

IAccessControl

*   [`RoleAdminChanged(role, previous_admin_role, new_admin_role)`](#AccessControlComponent-RoleAdminChanged)
    
*   [`RoleGranted(role, account, sender)`](#AccessControlComponent-RoleGranted)
    
*   [`RoleRevoked(role, account, sender)`](#AccessControlComponent-RoleRevoked)
    

#### [](#AccessControlComponent-Embeddable-Functions)
Embeddable functions

#### [](#AccessControlComponent-has_role)
`has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

Returns `true` if `account` has been granted `role`.

#### [](#AccessControlComponent-get_role_admin)
`get_role_admin(self: @ContractState, role: felt252) → felt252` external

Returns the admin role that controls `role`. See [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
.

To change a role’s admin, use [\_set\_role\_admin](#AccessControlComponent-_set_role_admin)
.

#### [](#AccessControlComponent-grant_role)
`grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Grants `role` to `account`.

If `account` had not been already granted `role`, emits a [RoleGranted](#IAccessControl-RoleGranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-revoke_role)
`revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from `account`.

If `account` had been granted `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-renounce_role)
`renounce_role(ref self: ContractState, role: felt252, account: ContractAddress)` external

Revokes `role` from the calling account.

Roles are often managed via [grant\_role](#AccessControlComponent-grant_role)
 and [revoke\_role](#AccessControlComponent-revoke_role)
. This function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling account had been revoked `role`, emits a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

Requirements:

*   the caller must be `account`.
    

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-supports_interface)
`supports_interface(self: @ContractState, interface_id: felt252) → bool` external

See [ISRC5::supports\_interface](introspection#ISRC5-supports_interface)
.

#### [](#AccessControlComponent-hasRole)
`hasRole(self: @ContractState, role: felt252, account: ContractAddress) → bool` external

See [has\_role](#AccessControlComponent-has_role)
.

#### [](#AccessControlComponent-getRoleAdmin)
`getRoleAdmin(self: @ContractState, role: felt252) → felt252` external

See [get\_role\_admin](#AccessControlComponent-get_role_admin)
.

#### [](#AccessControlComponent-grantRole)
`grantRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [grant\_role](#AccessControlComponent-grant_role)
.

#### [](#AccessControlComponent-revokeRole)
`revokeRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [revoke\_role](#AccessControlComponent-revoke_role)
.

#### [](#AccessControlComponent-renounceRole)
`renounceRole(ref self: ContractState, role: felt252, account: ContractAddress)` external

See [renounce\_role](#AccessControlComponent-renounce_role)
.

#### [](#AccessControlComponent-Internal-Functions)
Internal functions

#### [](#AccessControlComponent-initializer)
`initializer(ref self: ContractState)` internal

Initializes the contract by registering the [IAccessControl](#IAccessControl)
 interface ID.

#### [](#AccessControlComponent-assert_only_role)
`assert_only_role(self: @ContractState, role: felt252)` internal

Panics if called by any account without the given `role`.

#### [](#AccessControlComponent-_set_role_admin)
`_set_role_admin(ref self: ContractState, role: felt252, admin_role: felt252)` internal

Sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#IAccessControl-RoleAdminChanged)
 event.

#### [](#AccessControlComponent-_grant_role)
`_grant_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Grants `role` to `account`.

Internal function without access restriction.

May emit a [RoleGranted](#IAccessControl-RoleGranted)
 event.

#### [](#AccessControlComponent-_revoke_role)
`_revoke_role(ref self: ContractState, role: felt252, account: ContractAddress)` internal

Revokes `role` from `account`.

Internal function without access restriction.

May emit a [RoleRevoked](#IAccessControl-RoleRevoked)
 event.

#### [](#AccessControlComponent-Events)
Events

#### [](#AccessControlComponent-RoleAdminChanged)
`RoleAdminChanged(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)` event

See [IAccessControl::RoleAdminChanged](#IAccessControl-RoleAdminChanged)
.

#### [](#AccessControlComponent-RoleGranted)
`RoleGranted(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleGranted](#IAccessControl-RoleGranted)
.

#### [](#AccessControlComponent-RoleRevoked)
`RoleRevoked(role: felt252, account: ContractAddress, sender: ContractAddress)` event

See [IAccessControl::RoleRevoked](#IAccessControl-RoleRevoked)
.

[← Access](/contracts-cairo/0.13.0/access)

[Accounts →](/contracts-cairo/0.13.0/accounts)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

The ERC1155 multi token standard is a specification for [fungibility-agnostic](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
 token contracts. The ERC1155 library implements an approximation of [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC1155](#ierc1155)
    
*   [ERC1155 Compatibility](#erc1155_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC1155 URIs](#interpreting_erc1155_uris)
        
    *   [ERC1155Received](#erc1155received)
        
    
*   [Presets](#presets)
    
*   [Utilities](#utilities)
    
    *   [ERC1155Holder](#erc1155holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC1155`](#ierc1155_api)
        
    *   [Events](#events)
        
    *   [`IERC1155Metadata`](#ierc1155metadata_api)
        
    *   [`IERC1155Receiver`](#ierc1155receiver_api)
        
    

[](#ierc1155)
IERC1155
----------------------

    @contract_interface
    namespace IERC1155 {
        func balanceOf(account: felt, id: Uint256) -> (balance: Uint256) {
        }
    
        func balanceOfBatch(
            accounts_len: felt,
            accounts: felt*,
            ids_len: felt,
             ids: Uint256*
        ) -> (
            balances_len: felt,
            balances: Uint256*
        ) {
        }
    
        func isApprovedForAll(
            account: felt,
            operator: felt
        ) -> (approved: felt) {
        }
    
        func setApprovalForAll(operator: felt, approved: felt) {
        }
    
        func safeTransferFrom(
            from_: felt,
            to: felt,
            id: Uint256,
            value: Uint256,
            data_len: felt,
            data: felt*
        ) {
        }
    
        func safeBatchTransferFrom(
            from_: felt,
            to: felt,
            ids_len: felt,
            ids: Uint256*,
            values_len: felt,
            values: Uint256*,
            data_len: felt,
            data: felt*,
        ) {
        }
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    }

### [](#erc1155_compatibility)
ERC1155 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC1155 standard in the following ways:

*   It uses Cairo’s `uint256` instead of `felt`.
    
*   It returns `TRUE` as success.
    

But some differences can still be found, such as:

*   It implements an `uri()` function that returns the same URI for **all** token types. It relies on the token type ID substitution mechanism [defined in the EIP](https://eips.ethereum.org/EIPS/eip-1155#metadata)
    . Clients calling this function must replace the `{id}` substring with the actual token type ID.
    
*   `safeTransferFrom` and `safeBatchTransferFrom` are specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, the `data` argument accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`.
    
*   `IERC1155Receiver` compliant contracts (`ERC1155Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info.
    
*   `IERC1155Receiver` compliant contracts (`ERC1155Holder`) must support ERC165 by registering the `IERC1155Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC1155 transfers.
    

[](#usage)
Usage
----------------

To show a standard use case, we’ll use the `ERC1155MintableBurnable` preset which allows for only the owner to `mint` tokens. To create a token, you need to first deploy both Account and ERC1155 contracts respectively.

Considering that the ERC1155 constructor method looks like this:

    func constructor(
        uri: felt,      // Token URI as Cairo short string
        owner: felt     // Address designated as the contract owner
    ) {
    }

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc1155 = await starknet.deploy(
        "contracts/token/erc1155/presets/ERC1155MintableBurnable.cairo",
        constructor_calldata=[\
            str_to_felt("http://my.uri/{id}"),        # uri\
            account.contract_address                  # owner\
        ]
    )

To mint tokens, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    token_id = uint(1)
    mint_value = uint(1000)
    
    await signer.send_transaction(
        account, erc1155.contract_address, 'mint', [\
            recipient_address,\
            *token_id,\
            *mint_value,\
            0 # data\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `safeTransferFrom` and `safeBatchTransferFrom` to transfer assets. These methods incorporate the following conditional logic:

1.  If the receiving address [is identified as an account](accounts#account_introspection_with_erc165)
    , the tokens will be transferred.
    
2.  If the receiving address is not an account contract, the function will check that the receiver supports ERC1155 tokens before sending them.
    

The current implementation requires recipient contracts to support ERC165 and expose the `supportsInterface` method. See [ERC1155Received](#erc1155received)
.

### [](#interpreting_erc1155_uris)
Interpreting ERC1155 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard. Therefore, this library’s ERC1155 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC1155, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc1155.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc1155.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc1155received)
ERC1155Received

In order to be sure a contract can safely accept ERC1155 tokens, said contract must implement the [`IERC1155Receiver`](#ierc1155receiver_api)
 interface (as expressed in the EIP1155 specification). Methods such as `safeTransferFrom` and `safeBatchTransferFrom` call the recipient contract’s `onERC1155Received` or `onERC1155BatchReceived` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. Transfer functions require a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC1155 implementation requires that all contracts that support safe ERC1155 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC1155Receiver` magic value `00x4e2312e0` (which invokes `onERC1155Received` and `onERC1155BatchReceived`). If the recipient contract supports the `IAccount` magic value, `supportsInterface` should return `TRUE`. Otherwise, transfer functions should fail.

[](#presets)
Presets
--------------------

### [](#erc1155mintableburnable)
ERC1155MintableBurnable

The [`ERC1155MintableBurnable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc1155/presets/ERC1155MintableBurnable.cairo)
 preset offers a quick and easy setup for creating ERC1155 tokens. Its constructor takes three arguments: `name`, `symbol`, and an `owner` address which will be capable of minting tokens.

[](#utilities)
Utilities
------------------------

### [](#erc1155holder)
ERC1155Holder

Implementation of the `IERC1155Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC1155.safeTransferFrom`, `IERC1155.approve` or `IERC1155.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC1155Received](#erc1155received)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc1155_api)
IERC1155 API

    func balanceOf(account: felt, id: Uint256) -> (balance: Uint256) {
    }
    
    func balanceOfBatch(
        accounts_len: felt,
        accounts: felt*,
        ids_len: felt,
        ids: Uint256*
    ) -> (
        balances_len: felt,
        balances: Uint256*
    ) {
    }
    
    func isApprovedForAll(account: felt, operator: felt) -> (approved: felt) {
    }
    
    func setApprovalForAll(operator: felt, approved: felt) {
    }
    
    func safeTransferFrom(
        from_: felt,
        to: felt,
        id: Uint256,
        value: Uint256,
        data_len: felt,
        data: felt*
    ) {
    }
    
    func safeBatchTransferFrom(
        from_: felt,
        to: felt,
        ids_len: felt,
        ids: Uint256*,
        values_len: felt,
        values: Uint256*,
        data_len: felt,
        data: felt*,
    ) {
    }

#### [](#balanceof)
`balanceOf`

Returns the number of `id` tokens of `account`.

Parameters:

    account: felt
    id: Uint256

Returns:

    balance: Uint256

#### [](#balanceofbatch)
`balanceOfBatch`

Get the balance of multiple account/token pairs.

Parameters:

    accounts_len: felt
    accounts: felt*
    ids_len: felt
    ids: Uint156*

Returns:

    balances_len: felt
    balances: Uint256*

#### [](#isapprovedforall)
`isApprovedForAll`

Get whether `operator` is approved by `account` for all tokens.

Parameters:

    account: felt
    operator: felt

Returns:

    approved: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Enable or disable approval for a third party ("operator") to manage all of the caller’s tokens.

Parameters:

    operator: felt
    approved: felt

Returns: None.

#### [](#safetransferfrom)
`safeTransferFrom`

Transfers `value` amount of token `id` from `from_` to `to`, checking first that contract recipients are aware and capable of handling ERC1155 tokens to prevent locking them forever. For information regarding how contracts communicate their awareness of the ERC1155 protocol, see [ERC1155Received](#erc1155received)
.

Emits a [TransferSingle](#transfersingle_event)
 event.

Parameters:

    from_: felt
    to: felt
    id: Uint256
    value: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#safebatchtransferfrom)
`safeBatchTransferFrom`

Batch version of [`safeTransferFrom`](#safetransferfrom)
. Emits a [TransferBatch](#transferbatch_event)
 event.

Parameters:

    from_: felt
    to: felt
    ids_len: felt
    ids: Uint256*
    values_len: felt
    values: Uint256*
    data_len: felt
    data: felt*

Returns: None.

* * *

### [](#events)
Events

#### [](#transfersingle_event)
`TransferSingle (Event)`

Emitted when `operator` sends `value` amount of `id` token from `from_` to `to`.

Parameters:

    operator: felt
    from_: felt
    to: felt
    id: Uint256
    value: Uint256

#### [](#transferbatch_event)
`TransferBatch (Event)`

Emitted when `operator` sends multiple `values` of multiple token `ids` from `from_` to `to`.

Parameters:

    operator: felt
    from_: felt
    to: felt
    ids_len: felt
    ids: Uint256*
    values_len: felt
    values: Uint256*

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    account: felt
    operator: felt
    approved: felt

* * *

### [](#ierc1155metadata_api)
IERC1155Metadata API

    func uri(id: Uint256) -> (uri: felt) {
    }

#### [](#uri)
`uri`

Returns the Uniform Resource Identifier (URI) for a token `id`, although this implementation returns the same URI for **all** token types. It relies on the token type ID substitution mechanism [defined in the EIP](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

Parameters:

    id: Uint256

Returns:

    uri: felt

* * *

### [](#ierc1155receiver_api)
IERC1155Receiver API

    func onERC1155Received(
        operator: felt,
        from_: felt,
        tokenId: Uint256,
        data_len: felt,
        data: felt*
    ) -> (selector: felt) {
    }
    
    func onERC1155BatchReceived(
        operator: felt,
        from_: felt,
        ids_len: felt,
        ids: Uint256*,
        values_len: felt,
        values: Uint256*,
        data_len: felt,
        data: felt*,
    ) -> (selector: felt) {
    }

#### [](#onerc1155received)
`onERC1155Received`

Whenever any IERC1155 token is transferred or minted to this non-account contract by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    id: Uint256
    value: Uint156
    data_len: felt
    data: felt*

Returns:

    selector: felt

#### [](#onerc1155batchreceived)
`onERC1155BatchReceived`

Whenever any IERC1155 token is transferred to this non-account contract via `safeBatchTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    ids_len: felt
    ids: Uint256*
    values_len: felt
    values: Uint156*
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC721](/contracts-cairo/0.6.0/erc721)

[Security →](/contracts-cairo/0.6.0/security)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

Access control—​that is, "who is allowed to do this thing"--is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Ownable](#ownable)
    
    *   [Quickstart](#quickstart)
        
    *   [Ownable library API](#ownable_library_api)
        
    *   [Ownable events](#ownable_events)
        
    
*   [AccessControl](#accesscontrol)
    
    *   [Usage](#usage)
        
    *   [Granting and revoking roles](#granting_and_revoking_roles)
        
    *   [Creating role identifiers](#creating_role_identifiers)
        
    *   [AccessControl library API](#accesscontrol_library_api)
        
    *   [AccessControl events](#accesscontrol_events)
        
    

[](#ownable)
Ownable
--------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/access/ownable/library.cairo)
 for implementing ownership in your contracts.

### [](#quickstart)
Quickstart

Integrating [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/access/ownable/library.cairo)
 into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [initializer](#initializer)
 like this:

    from openzeppelin.access.ownable.library import Ownable
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) {
        Ownable.initializer(owner);
        return ();
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    from openzeppelin.access.ownable.library import Ownable
    
    func protected_function{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
        Ownable.assert_only_owner();
        return ();
    }

### [](#ownable_library_api)
Ownable library API

    func initializer(owner: felt) {
    }
    
    func assert_only_owner() {
    }
    
    func owner() -> (owner: felt) {
    }
    
    func transfer_ownership(new_owner: felt) {
    }
    
    func renounce_ownership() {
    }
    
    func _transfer_ownership(new_owner: felt) {
    }

#### [](#initializer)
`initializer`

Initializes Ownable access control and should be called in the implementing contract’s constructor. Assigns `owner` as the initial owner address of the contract.

This must be called only once.

Parameters:

    owner: felt

Returns: None.

#### [](#assert_only_owner)
`assert_only_owner`

Reverts if called by any account other than the owner. In case of renounced ownership, any call from the default zero address will also be reverted.

Parameters: None.

Returns: None.

#### [](#owner)
`owner`

Returns the address of the current owner.

Parameters: None.

Returns:

    owner: felt

#### [](#transfer_ownership)
`transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

#### [](#renounce_ownership)
`renounce_ownership`

Leaves the contract without owner. It will not be possible to call functions with `assert_only_owner` anymore. Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters: None.

Returns: None.

#### [](#transfer-ownership-internal)
`_transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). [`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

### [](#ownable_events)
Ownable events

    func OwnershipTransferred(previousOwner: felt, newOwner: felt) {
    }

#### [](#ownershiptransferred)
OwnershipTransferred

Emitted when ownership of a contract is transferred from `previousOwner` to `newOwner`.

Parameters:

    previousOwner: felt
    newOwner: felt

[](#accesscontrol)
AccessControl
--------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [assert\_only\_owner](#assert_only_owner)
. This check can be enforced through [assert\_only\_role](#assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role (see [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers).

Here’s a simple example of implementing `AccessControl` on a portion of an [ERC20 token contract](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 which defines and sets the 'minter' role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        name: felt, symbol: felt, decimals: felt, minter: felt
    ) {
        ERC20.initializer(name, symbol, decimals);
        AccessControl.initializer();
        AccessControl._grant_role(MINTER_ROLE, minter);
        return ();
    }
    
    @external
    func mint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        to: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(MINTER_ROLE);
        ERC20._mint(to, amount);
        return ();
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](#accesscontrol)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](#ownable)
. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens, and by using `assert_only_role`:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        name: felt, symbol: felt, decimals: felt, minter: felt, burner: felt
    ) {
        ERC20.initializer(name, symbol, decimals);
        AccessControl.initializer();
        AccessControl._grant_role(MINTER_ROLE, minter);
        AccessControl._grant_role(BURNER_ROLE, burner);
        return ();
    }
    
    @external
    func mint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        to: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(MINTER_ROLE);
        ERC20._mint(to, amount);
        return ();
    }
    
    @external
    func burn{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        from_: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(BURNER_ROLE);
        ERC20._burn(from_, amount);
        return ();
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses `_grant_role`, an [`internal`](extensibility#the_pattern)
 function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `assert_only_role` check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the `grant_role` and `revoke_role` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_set_role_admin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    from openzeppelin.utils.constants import DEFAULT_ADMIN_ROLE
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        name: felt, symbol: felt, decimals: felt, admin: felt,
    ) {
        ERC20.initializer(name, symbol, decimals);
        AccessControl.initializer();
    
        AccessControl._grant_role(DEFAULT_ADMIN_ROLE, admin);
        return ();
    }
    
    @external
    func mint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        to: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(MINTER_ROLE);
        ERC20._mint(to, amount);
        return ();
    }
    
    @external
    func burn{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        from_: felt, amount: Uint256
    ) {
        AccessControl.assert_only_role(BURNER_ROLE);
        ERC20._burn(from_, amount);
        return ();
    }

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

The following example uses the [AccessControl mock contract](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/tests/mocks/AccessControl.cairo)
 which exposes the role management functions. To grant and revoke roles in Python, for example:

    MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    # grants MINTER_ROLE and BURNER_ROLE to account1 and account2 respectively
    await signer.send_transactions(
        admin, [\
            (accesscontrol.contract_address, 'grantRole', [MINTER_ROLE, account1.contract_address]),\
            (accesscontrol.contract_address, 'grantRole', [BURNER_ROLE, account2.contract_address])\
        ]
    )
    
    # revokes MINTER_ROLE from account1
    await signer.send_transaction(
        admin,
        accesscontrol.contract_address,
        'revokeRole',
        [MINTER_ROLE, account1.contract_address]
    )

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier. For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements store a maximum of 252 bits. Even further, a declared _constant_ field element in a StarkNet contract stores even less (see [cairo\_constants](https://github.com/starkware-libs/cairo-lang/blob/release-v0.6.0/src/starkware/cairo/lang/cairo_constants.py#L1)
). With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use the first or last 251 bits of keccak256 hash digests.
    
*   Use Cairo’s [hash2](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash.cairo)
    .
    

### [](#accesscontrol_library_api)
AccessControl library API

    func initializer() {
    }
    
    func assert_only_role(role: felt) {
    }
    
    func has_role(role: felt, user: felt) -> (has_role: felt) {
    }
    
    func get_role_admin(role: felt) -> (admin: felt) {
    }
    
    func grant_role(role: felt, user: felt) {
    }
    
    func revoke_role(role: felt, user: felt) {
    }
    
    func renounce_role(role: felt, user: felt) {
    }
    
    func _grant_role(role: felt, user: felt) {
    }
    
    func _revoke_role(role: felt, user: felt) {
    }
    
    func _set_role_admin(role: felt, admin_role: felt) {
    }

#### [](#initializer-accesscontrol)
`initializer`

Initializes AccessControl and should be called in the implementing contract’s constructor.

This must only be called once.

Parameters: None.

Returns: None.

#### [](#assert_only_role)
`assert_only_role`

Checks that an account has a specific role. Reverts with a message including the required role.

Parameters:

    role: felt

Returns: None.

#### [](#has_role)
has\_role

Returns `TRUE` if `user` has been granted `role`, `FALSE` otherwise.

Parameters:

    role: felt
    user: felt

Returns:

    has_role: felt

#### [](#get_role_admin)
`get_role_admin`

Returns the admin role that controls `role`. See [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
.

To change a role’s admin, use [`_set_role_admin`](#set_role_admin)
.

Parameters:

    role: felt

Returns:

    admin: felt

#### [](#grant_role)
`grant_role`

Grants `role` to `user`.

If `user` had not been already granted `role`, emits a [RoleGranted](#rolegranted)
 event.

Requirements:

*   The caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revoke_role)
`revoke_role`

Revokes `role` from `user`.

If `user` had been granted `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   The caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#renounce_role)
`renounce_role`

Revokes `role` from the calling `user`.

Roles are often managed via [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling `user` had been revoked `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   The caller must be `user`.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#grantrole-internal)
`_grant_role`

Grants `role` to `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleGranted](#rolegranted)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revokerole-internal)
`_revoke_role`

Revokes `role` from `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleRevoked](#rolerevoked)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#setroleadmin)
`_set_role_admin`

[`internal`](extensibility#the_pattern)
 function that sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#roleadminchanged)
 event.

Parameters:

    role: felt
    admin_role: felt

Returns: None.

### [](#accesscontrol_events)
AccessControl events

    func RoleGranted(role: felt, account: felt, sender: felt) {
    }
    
    func RoleRevoked(role: felt, account: felt, sender: felt) {
    }
    
    func RoleAdminChanged(role: felt, previousAdminRole: felt, newAdminRole: felt) {
    }

#### [](#rolegranted)
`RoleGranted`

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

Parameters:

    role: felt
    account: felt
    sender: felt

#### [](#rolerevoked)
`RoleRevoked`

Emitted when account is revoked role.

`sender` is the account that originated the contract call:

*   If using [revoke\_role](#revoke_role)
    , it is the admin role bearer.
    
*   If using [renounce\_role](#renounce_role)
    , it is the role bearer (i.e. `account`).
    

    role: felt
    account: felt
    sender: felt

#### [](#roleadminchanged)
`RoleAdminChanged`

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`.

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite `RoleAdminChanged` not being emitted signaling this.

    role: felt
    previousAdminRole: felt
    newAdminRole: felt

[← Accounts](/contracts-cairo/0.6.0/accounts)

[ERC20 →](/contracts-cairo/0.6.0/erc20)




 Presets - OpenZeppelin Docs       

Presets
=======

Presets are ready-to-deploy contracts provided by the library. Since presets are intended to be very simple and as generic as possible, there’s no support for custom or complex contracts such as `ERC20Pausable` or `ERC721Mintable`.

|     |     |
| --- | --- |
|     | For contract customization and combination of modules you can use [Wizard for Cairo](https://wizard.openzeppelin.com)<br>, our code-generation tool. |

[](#available_presets)
Available presets
----------------------------------------

List of available presets and their corresponding [Sierra class hashes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash)
.

|     |     |
| --- | --- |
|     | Class hashes were computed using [cairo 2.5.3](https://crates.io/crates/cairo-lang-compiler/2.5.3)<br>. |

 
| Name | Sierra Class Hash |
| --- | --- |
| `[Account](api/account#Account) ` | `0x004ca5c0b1af6115858708bd1fabd2e9bb306012b31a741acbf69b8a9f35d688` |
| `[ERC20](api/erc20#ERC20) ` | `0x03b6024fbaf5276e4aa0b4632b80caa6228dbf7b3fe2a0d6144aacb5eb14f1a0` |
| `[ERC721](api/erc721#ERC721) ` | `0x060a1eeded2f1633b2ee71b6ee3de0d4466198d4097f23c6ad62b6f11e8f9775` |
| `[ERC1155](api/erc1155#ERC1155) ` | `0x0518be7d9fa527c78d6929bf9e638e9c98b6077722e27e9546cc4342e830386e` |
| `[EthAccountUpgradeable](api/account#EthAccountUpgradeable) ` | `0x0359eceac190c19d22e2831f3bd2ecde9f1b1d034d0790e5dd6b3c91651bda97` |

|     |     |
| --- | --- |
|     | [starkli](https://book.starkli.rs/introduction)<br> class-hash command can be used to compute the class hash from a Sierra artifact. |

[← Components](/contracts-cairo/0.10.0/components)

[Interfaces and Dispatchers →](/contracts-cairo/0.10.0/interfaces)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: felt252
        ) -> felt252;
    }

[← Interfaces and Dispatchers](/contracts-cairo/0.15.0/interfaces)

[SNIP12 and Typed Messages →](/contracts-cairo/0.15.0/guides/snip12)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: felt252
        ) -> felt252;
    }

[← Interfaces and Dispatchers](/contracts-cairo/0.13.0/interfaces)

[SNIP12 and Typed Messages →](/contracts-cairo/0.13.0/guides/snip12)




 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    pub trait IERC20<TState> {
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes functions from different traits such as `IERC20` and `IERC20Camel`.

    #[starknet::interface]
    pub trait ERC20ABI<TState> {
        // IERC20
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    
        // IERC20Metadata
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
    
        // IERC20CamelOnly
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    pub struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    pub trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> ByteArray;
        fn symbol(self: @DualCaseERC20) -> ByteArray;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    pub trait IERC20<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    pub trait IERC20Camel<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, fallback, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Presets](/contracts-cairo/0.15.0/presets)

[Counterfactual Deployments →](/contracts-cairo/0.15.0/guides/deployment)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. The `ERC721.cairo` contract implements an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [IERC721](#ierc721)
    
*   [ERC721 Compatibility](#erc721_compatibility)
    
*   [Usage](#usage)
    
    *   [Token Transfers](#token_transfers)
        
    *   [Interpreting ERC721 URIs](#interpreting_erc721_uris)
        
    *   [ERC721Received](#erc721received)
        
        *   [IERC721Receiver](#ierc721receiver)
            
        
    *   [Supporting Interfaces](#supporting_interfaces)
        
    *   [Ready\_to\_Use Presets](#ready_to_use_presets)
        
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC721MintableBurnable](#erc721mintableburnable)
        
    *   [ERC721MintablePausable](#erc721mintablepausable)
        
    *   [ERC721EnumerableMintableBurnable](#erc721enumerablemintableburnable)
        
        *   [IERC721Enumerable](#ierc721enumerable)
            
        
    *   [ERC721Metadata](#erc721metadata)
        
        *   [IERC721Metadata](#ierc721metadata)
            
        
    
*   [Utilities](#utilities)
    
    *   [ERC721Holder](#erc721_holder)
        
    
*   [API Specification](#api_specification)
    
    *   [`IERC721`](#ierc721_api)
        
        *   [`balanceOf`](#balanceof)
            
        *   [`ownerOf`](#ownerof)
            
        *   [`safeTransferFrom`](#safetransferfrom)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        *   [`setApprovalForAll`](#setapprovalforall)
            
        *   [`getApproved`](#getapproved)
            
        *   [`isApprovedForAll`](#isapprovedforall)
            
        
    *   [Events](#events)
        
        *   [`Approval (event)`](#approval_event)
            
        *   [`ApprovalForAll (event)`](#approvalforall_event)
            
        *   [`Transfer (event)`](#transfer_event)
            
        
    *   [`IERC721Metadata`](#ierc721metadata)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`tokenURI`](#tokenuri)
            
        
    *   [`IERC721Enumerable`](#ierc721enumerable)
        
        *   [`totalSupply`](#totalsupply)
            
        *   [`tokenByIndex`](#tokenbyindex)
            
        *   [`tokenOfOwnerByIndex`](#tokenofownerbyindex)
            
        
    *   [`IERC721Receiver`](#ierc721receiver_api)
        
        *   [`onERC721Received`](#onerc721received)
            
        
    

[](#ierc721)
IERC721
--------------------

    @contract_interface
    namespace IERC721:
        func balanceOf(owner: felt) -> (balance: Uint256):
        end
    
        func ownerOf(tokenId: Uint256) -> (owner: felt):
        end
    
        func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    
        func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
        func approve(approved: felt, tokenId: Uint256):
        end
    
        func setApprovalForAll(operator: felt, approved: felt):
        end
    
        func getApproved(tokenId: Uint256) -> (approved: felt):
        end
    
        func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
        end
    
        --------------- IERC165 ---------------
    
        func supportsInterface(interfaceId: felt) -> (success: felt):
        end
    end

### [](#erc721_compatibility)
ERC721 Compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `tokenURI` returns a felt representation of the queried token’s URI. The EIP721 standard, however, states that the return value should be of type string. If a token’s URI is not set, the returned value is `0`. Note that URIs cannot exceed 31 characters. See [Interpreting ERC721 URIs](#interpreting_erc721_uris)
    
*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Solidity’s selector calculations. See [Supporting Interfaces](#supporting_interfaces)
    
*   `safeTransferFrom` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721. The difference between both functions consists of accepting `data` as an argument. Because function overloading is currently not possible in Cairo, `safeTransferFrom` by default accepts the `data` argument. If `data` is not used, simply insert `0`.
    
*   `safeTransferFrom` is specified such that the optional `data` argument should be of type bytes. In Solidity, this means a dynamically-sized array. To be as close as possible to the standard, it accepts a dynamic array of felts. In Cairo, arrays are expressed with the array length preceding the actual array; hence, the method accepts `data_len` and `data` respectively as types `felt` and `felt*`
    
*   `ERC165.register_interface` allows contracts to set and communicate which interfaces they support. This follows OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) return a hardcoded selector id according to EVM selectors, since selectors are calculated differently in Cairo. This is in line with the ERC165 interfaces design choice towards EVM compatibility. See the [Introspection docs](introspection)
     for more info
    
*   `IERC721Receiver` compliant contracts (`ERC721Holder`) must support ERC165 by registering the `IERC721Receiver` selector id in its constructor and exposing the `supportsInterface` method. In doing so, recipient contracts (both accounts and non-accounts) can be verified that they support ERC721 transfers
    
*   `ERC721Enumerable` tracks the total number of tokens with the `all_tokens` and `all_tokens_len` storage variables mimicking the array of the Solidity implementation.
    

[](#usage)
Usage
----------------

Use cases go from artwork, digital collectibles, physical property, and many more.

To show a standard use case, we’ll use the `ERC721Mintable` preset which allows for only the owner to `mint` and `burn` tokens. To create a token you need to first deploy both Account and ERC721 contracts respectively. As most StarkNet contracts, ERC721 expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it.

Considering that the ERC721 constructor method looks like this:

    func constructor(
        name: felt,          # Token name as Cairo short string
        symbol: felt,        # Token symbol as Cairo short string
        owner: felt          # Address designated as the contract owner
    ):

Deployment of both contracts looks like this:

    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    erc721 = await starknet.deploy(
        "contracts/token/erc721/presets/ERC721Mintable.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),                       # name\
            str_to_felt("TKN"),                         # symbol\
            account.contract_address                    # owner\
        ]
    )

To mint a non-fungible token, send a transaction like this:

    signer = MockSigner(PRIVATE_KEY)
    tokenId = uint(1)
    
    await signer.send_transaction(
        account, erc721.contract_address, 'mint', [\
            recipient_address,\
            *tokenId\
        ]
    )

### [](#token_transfers)
Token Transfers

This library includes `transferFrom` and `safeTransferFrom` to transfer NFTs. If using `transferFrom`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.**

The `safeTransferFrom` method incorporates the following conditional logic:

1.  if the calling address is an account contract, the token transfer will behave as if `transferFrom` was called
    
2.  if the calling address is not an account contract, the safe function will check that the contract supports ERC721 tokens
    

The current implementation of `safeTansferFrom` checks for `onERC721Received` and requires that the recipient contract supports ERC165 and exposes the `supportsInterface` method. See [ERC721Received](#erc721received)
.

### [](#interpreting_erc721_uris)
Interpreting ERC721 URIs

Token URIs in Cairo are stored as single field elements. Each field element equates to 252-bits (or 31.5 bytes) which means that a token’s URI can be no longer than 31 characters.

|     |     |
| --- | --- |
|     | Storing the URI as an array of felts was considered to accommodate larger strings. While this approach is more flexible regarding URIs, a returned array further deviates from the standard set in [EIP721](https://eips.ethereum.org/EIPS/eip-721)<br>. Therefore, this library’s ERC721 implementation sets URIs as a single field element. |

The `utils.py` module includes utility methods for converting to/from Cairo field elements. To properly interpret a URI from ERC721, simply trim the null bytes and decode the remaining bits as an ASCII string. For example:

    # HELPER METHODS
    def str_to_felt(text):
        b_text = bytes(text, 'ascii')
        return int.from_bytes(b_text, "big")
    
    def felt_to_str(felt):
        b_felt = felt.to_bytes(31, "big")
        return b_felt.decode()
    
    token_id = uint(1)
    sample_uri = str_to_felt('mock://mytoken')
    
    await signer.send_transaction(
        account, erc721.contract_address, 'setTokenURI', [\
            *token_id, sample_uri]
    )
    
    felt_uri = await erc721.tokenURI(first_token_id).call()
    string_uri = felt_to_str(felt_uri)

### [](#erc721received)
ERC721Received

In order to be sure a contract can safely accept ERC721 tokens, said contract must implement the `ERC721_Receiver` interface (as expressed in the EIP721 specification). Methods such as `safeTransferFrom` and `safeMint` call the recipient contract’s `onERC721Received` method. If the contract fails to return the correct magic value, the transaction fails.

StarkNet contracts that support safe transfers, however, must also support [ERC165](introspection#erc165)
 and include `supportsInterface` as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. `safeTransferFrom` requires a means of differentiating between account and non-account contracts. Currently, StarkNet does not support error handling from the contract level; therefore, the current ERC721 implementation requires that all contracts that support safe ERC721 transfers (both accounts and non-accounts) include the `supportsInterface` method. Further, `supportsInterface` should return `TRUE` if the recipient contract supports the `IERC721Receiver` magic value `0x150b7a02` (which invokes `onERC721Received`). If the recipient contract supports the `IAccount` magic value `0x50b70dcb`, `supportsInterface` should return `TRUE`. Otherwise, `safeTransferFrom` should fail.

#### [](#ierc721receiver)
IERC721Receiver

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

    @contract_interface
    namespace IERC721Receiver:
        func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
        end
    end

### [](#supporting_interfaces)
Supporting Interfaces

In order to ensure EVM/StarkNet compatibility, this ERC721 implementation does not calculate interface identifiers. Instead, the interface IDs are hardcoded from their EVM calculations. On the EVM, the interface ID is calculated from the selector’s first four bytes of the hash of the function’s signature while Cairo selectors are 252 bytes long. Due to this difference, hardcoding EVM’s already-calculated interface IDs is the most consistent approach to both follow the EIP165 standard and EVM compatibility.

Further, this implementation stores supported interfaces in a mapping (similar to OpenZeppelin’s [ERC165Storage](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165Storage.sol)
).

### [](#ready_to_use_presets)
Ready-to-Use Presets

ERC721 presets have been created to allow for quick deployments as-is. To be as explicit as possible, each preset includes the additional features they offer in the contract name. For example:

*   `ERC721MintableBurnable` includes `mint` and `burn`
    
*   `ERC721MintablePausable` includes `mint`, `pause`, and `unpause`
    
*   `ERC721EnumerableMintableBurnable` includes `mint`, `burn`, and [IERC721Enumerable](#ierc721enumerable)
     methods
    

Ready-to-use presets are a great option for testing and prototyping. See [Presets](#presets)
.

[](#extensibility)
Extensibility
--------------------------------

Following the [contracts extensibility pattern](extensibility)
, this implementation is set up to include all ERC721 related storage and business logic under a namespace. Developers should be mindful of manually exposing the required methods from the namespace to comply with the standard interface. This is already done in the [preset contracts](#presets)
; however, additional functionality can be added. For instance, you could:

*   Implement a pausing mechanism
    
*   Add roles such as _owner_ or _minter_
    
*   Modify the `transferFrom` function to mimic the [`_beforeTokenTransfer` and `_afterTokenTransfer` hooks](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L335)
    

Just be sure that the exposed `external` methods invoke their imported function logic a la `approve` invokes `ERC721.approve`. As an example, see below.

    from openzeppelin.token.erc721.library import ERC721
    
    @external
    func approve{
            pedersen_ptr: HashBuiltin*,
            syscall_ptr: felt*,
            range_check_ptr
        }(to: felt, tokenId: Uint256):
        ERC721.approve(to, tokenId)
        return()
    end

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset includes a contract owner, which is set in the `constructor`, to offer simple access control on sensitive methods such as `mint` and `burn`.

### [](#erc721mintableburnable)
ERC721MintableBurnable

The `ERC721MintableBurnable` preset offers a quick and easy setup for creating NFTs. The contract owner can create tokens with `mint`, whereas token owners can destroy their tokens with `burn`.

### [](#erc721mintablepausable)
ERC721MintablePausable

The `ERC721MintablePausable` preset creates a contract with pausable token transfers and minting capabilities. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug. In this preset, only the contract owner can `mint`, `pause`, and `unpause`.

### [](#erc721enumerablemintableburnable)
ERC721EnumerableMintableBurnable

The `ERC721EnumerableMintableBurnable` preset adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This allows contracts to publish its full list of NFTs and make them discoverable.

In regard to implementation, contracts should expose the following view methods:

*   `ERC721Enumerable.total_supply`
    
*   `ERC721Enumerable.token_by_index`
    
*   `ERC721Enumerable.token_of_owner_by_index`
    

In order for the tokens to be correctly indexed, the contract should also use the following methods (which supercede some of the base `ERC721` methods):

*   `ERC721Enumerable.transfer_from`
    
*   `ERC721Enumerable.safe_transfer_from`
    
*   `ERC721Enumerable._mint`
    
*   `ERC721Enumerable._burn`
    

#### [](#ierc721enumerable)
IERC721Enumerable

    @contract_interface
    namespace IERC721Enumerable:
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
        end
    
        func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
        end
    end

### [](#erc721metadata)
ERC721Metadata

The `ERC721Metadata` extension allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

We follow OpenZeppelin’s Solidity approach of integrating the Metadata methods `name`, `symbol`, and `tokenURI` into all ERC721 implementations. If preferred, a contract can be created that does not import the Metadata methods from the `ERC721` library. Note that the `IERC721Metadata` interface id should be removed from the constructor as well.

#### [](#ierc721metadata)
IERC721Metadata

    @contract_interface
    namespace IERC721Metadata:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
        end
    end

[](#utilities)
Utilities
------------------------

### [](#erc721holder)
ERC721Holder

Implementation of the `IERC721Receiver` interface.

Accepts all token transfers. Make sure the contract is able to use its token with `IERC721.safeTransferFrom`, `IERC721.approve` or `IERC721.setApprovalForAll`.

Also utilizes the ERC165 method `supportsInterface` to determine if the contract is an account. See [ERC721Received](#erc721received)

[](#api_specification)
API Specification
----------------------------------------

### [](#ierc721_api)
IERC721 API

    func balanceOf(owner: felt) -> (balance: Uint256):
    end
    
    func ownerOf(tokenId: Uint256) -> (owner: felt):
    end
    
    func safeTransferFrom(
            from_: felt,
            to: felt,
            tokenId: Uint256,
            data_len: felt,
            data: felt*
        ):
    end
    
    func transferFrom(from_: felt, to: felt, tokenId: Uint256):
        end
    
    func approve(approved: felt, tokenId: Uint256):
    end
    
    func setApprovalForAll(operator: felt, approved: felt):
    end
    
    func getApproved(tokenId: Uint256) -> (approved: felt):
    end
    
    func isApprovedForAll(owner: felt, operator: felt) -> (isApproved: felt):
    end

#### [](#balanceof)
`balanceOf`

Returns the number of tokens in `owner`'s account.

Parameters:

    owner: felt

Returns:

    balance: Uint256

#### [](#ownerof)
`ownerOf`

Returns the owner of the `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    owner: felt

#### [](#safetransferfrom)
`safeTransferFrom`

Safely transfers `tokenId` token from `from_` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [ERC721Received](#erc721received)
.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns: None.

#### [](#transferfrom)
`transferFrom`

Transfers `tokenId` token from `from_` to `to`. **The caller is responsible to confirm that `to` is capable of receiving NFTs or else they may be permanently lost**.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

Returns: None.

#### [](#approve)
`approve`

Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.

Emits an [Approval](#approval_event)
 event.

Parameters:

    to: felt
    tokenId: Uint256

Returns: None.

#### [](#getapproved)
`getApproved`

Returns the account approved for `tokenId` token.

Parameters:

    tokenId: Uint256

Returns:

    operator: felt

#### [](#setapprovalforall)
`setApprovalForAll`

Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.

Emits an [ApprovalForAll](#approvalforall_event)
 event.

Parameters:

    operator: felt

Returns: None.

#### [](#isapprovedforall)
`isApprovedForAll`

Returns if the `operator` is allowed to manage all of the assets of `owner`.

Parameters:

    owner: felt
    operator: felt

Returns:

    isApproved: felt

### [](#events)
Events

#### [](#approval_event)
`Approval (Event)`

Emitted when `owner` enables `approved` to manage the `tokenId` token.

Parameters:

    owner: felt
    approved: felt
    tokenId: Uint256

#### [](#approvalforall_event)
`ApprovalForAll (Event)`

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.

Parameters:

    owner: felt
    operator: felt
    approved: felt

#### [](#transfer_event)
`Transfer (Event)`

Emitted when `tokenId` token is transferred from `from_` to `to`.

Parameters:

    from_: felt
    to: felt
    tokenId: Uint256

* * *

### [](#ierc721metadata_api)
IERC721Metadata API

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func tokenURI(tokenId: Uint256) -> (tokenURI: felt):
    end

#### [](#name)
`name`

Returns the token collection name.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the token collection symbol.

Parameters: None.

Returns:

    symbol: felt

#### [](#tokenuri)
`tokenURI`

Returns the Uniform Resource Identifier (URI) for `tokenID` token. If the URI is not set for the `tokenId`, the return value will be `0`.

Parameters:

    tokenId: Uint256

Returns:

    tokenURI: felt

* * *

### [](#ierc721enumerable_api)
IERC721Enumerable API

    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func tokenByIndex(index: Uint256) -> (tokenId: Uint256):
    end
    
    func tokenOfOwnerByIndex(owner: felt, index: Uint256) -> (tokenId: Uint256):
    end

#### [](#totalsupply)
`totalSupply`

Returns the total amount of tokens stored by the contract.

Parameters: None

Returns:

    totalSupply: Uint256

#### [](#tokenbyindex)
`tokenByIndex`

Returns a token ID owned by `owner` at a given `index` of its token list. Use along with [balanceOf](#balanceof)
 to enumerate all of `owner`'s tokens.

Parameters:

    index: Uint256

Returns:

    tokenId: Uint256

#### [](#tokenofownerbyindex)
`tokenOfOwnerByIndex`

Returns a token ID at a given `index` of all the tokens stored by the contract. Use along with [totalSupply](#totalsupply)
 to enumerate all tokens.

Parameters:

    owner: felt
    index: Uint256

Returns:

    tokenId: Uint256

* * *

### [](#ierc721receiver_api)
IERC721Receiver API

    func onERC721Received(
            operator: felt,
            from_: felt,
            tokenId: Uint256,
            data_len: felt
            data: felt*
        ) -> (selector: felt):
    end

#### [](#onerc721received)
`onERC721Received`

Whenever an IERC721 `tokenId` token is transferred to this non-account contract via `safeTransferFrom` by `operator` from `from_`, this function is called.

Parameters:

    operator: felt
    from_: felt
    tokenId: Uint256
    data_len: felt
    data: felt*

Returns:

    selector: felt

[← ERC20](/contracts-cairo/0.3.2/erc20)

[Security →](/contracts-cairo/0.3.2/security)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are directly derived from a private key, there’s no native account concept on StarkNet.

Instead, signature validation has to be done at the contract level. To relieve smart contract applications such as ERC20 tokens or exchanges from this responsibility, we make use of Account contracts to deal with transaction authentication.

For a general overview of the account abstraction, see StarkWare’s [StarkNet Alpha 0.10](https://medium.com/starkware/starknet-alpha-0-10-0-923007290470)
. A more detailed discussion on the topic can be found in [StarkNet Account Abstraction Part 1](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Account entrypoints](#account_entrypoints)
    
    *   [`Counterfactual deployments`](#counterfactual_deployments)
        
    
*   [Standard interface](#standard_interface)
    
*   [Keys, signatures and signers](#keys_signatures_and_signers)
    
    *   [Signature validation](#signature_validation)
        
    *   [Signer](#signer)
        
    *   [MockSigner utility](#mocksigner_utility)
        
    *   [MockEthSigner utility](#mockethsigner_utility)
        
    
*   [Call and AccountCallArray format](#call_and_accountcallarray_format)
    
    *   [Call](#call)
        
    *   [AccountCallArray](#accountcallarray)
        
    
*   [Multicall transactions](#multicall_transactions)
    
*   [API Specification](#api_specification)
    
    *   [`constructor`](#constructor)
        
    *   [`getPublicKey`](#getpublickey)
        
    *   [`supportsInterface`](#supportsinterface)
        
    *   [`setPublicKey`](#setpublickey)
        
    *   [`isValidSignature`](#isvalidsignature)
        
    *   [`__validate__`](#validate)
        
    *   [`__validate_declare__`](#validate_declare)
        
    *   [`__validate_deploy__`](#validate_deploy)
        
    *   [`__execute__`](#execute)
        
    
*   [Presets](#presets)
    
    *   [Account](#account)
        
    *   [Eth Account](#eth_account)
        
    
*   [Account introspection with ERC165](#account_introspection_with_erc165)
    
*   [Extending the Account contract](#extending_the_account_contract)
    
*   [L1 escape hatch mechanism](#l1_escape_hatch_mechanism)
    
*   [Paying for gas](#paying_for_gas)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Account contract is deployed to StarkNet.
    
2.  Signed transactions can now be sent to the Account contract which validates and executes them.
    

In Python, this would look as follows:

    from starkware.starknet.testing.starknet import Starknet
    from utils import get_contract_class
    from signers import MockSigner
    
    signer = MockSigner(123456789987654321)
    
    starknet = await Starknet.empty()
    
    # 1. Deploy Account
    account = await starknet.deploy(
        get_contract_class("Account"),
        constructor_calldata=[signer.public_key]
    )
    
    # 2. Send transaction through Account
    await signer.send_transaction(account, some_contract_address, 'some_function', [some_parameter])

[](#account_entrypoints)
Account entrypoints
--------------------------------------------

Account contracts have only three entry points for all user interactions:

1.  [`__validate_declare__`](#validate_declare)
     validates the declaration signature prior to the declaration. As of Cairo v0.10.0, contract classes should be declared from an Account contract.
    
2.  [`__validate__`](#validate)
     verifies the transaction signature before executing the transaction with `__execute__`.
    
3.  [`__execute__`](#execute)
     acts as the state-changing entry point for all user interaction with any contract, including managing the account contract itself. That’s why if you want to change the public key controlling the Account, you would send a transaction targeting the very Account contract:
    

    await signer.send_transaction(
        account,
        account.contract_address,
        'set_public_key',
        [NEW_KEY]
    )

Or if you want to update the Account’s L1 address on the `AccountRegistry` contract, you would

    await signer.send_transaction(account, registry.contract_address, 'set_L1_address', [NEW_ADDRESS])

|     |     |
| --- | --- |
|     | You can read more about how messages are structured and hashed in the [Account message scheme discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/24)<br>. For more information on the design choices and implementation of multicall, you can read the [How should Account multicall work discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/27)<br>. |

The `__validate__` and `__execute__` methods accept the same arguments; however, `__execute__` returns a transaction response:

    func __validate__(
        call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*) {
    }
    
    func __execute__(
        call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
    ) -> (response_len: felt, response: felt*) {
    }

Where:

*   `call_array_len` is the number of calls.
    
*   `call_array` is an array representing each `Call`.
    
*   `calldata_len` is the number of calldata parameters.
    
*   `calldata` is an array representing the function parameters.
    

|     |     |
| --- | --- |
|     | The scheme of building multicall transactions within the `__execute__` method will change once StarkNet allows for pointers in struct arrays. In which case, multiple transactions can be passed to (as opposed to built within) `__execute__`. |

There’s a fourth canonical entrypoint for accounts, the `__validate_deploy__` method. It is **only callable by the protocol** during the execution of a `DeployAccount` type of transaction, but not by any other contract. This entrypoint is for counterfactual deployments.

### [](#counterfactual_deployments)
Counterfactual Deployments

Counterfactual means something that hasn’t happened.

A deployment is said to be counterfactual when the deployed contract pays for it. It’s called like this because we need to send the funds to the address before deployment. A deployment that hasn’t happened.

The steps are the following:

1.  Precompute the `address` given a `class_hash`, `salt`, and constructor `calldata`.
    
2.  Send funds to `address`.
    
3.  Send a `DeployAccount` type transaction.
    
4.  The protocol will then validate with `__validate_deploy__`.
    
5.  If successful, the protocol deploys the contract and the contract itself pays for the transaction.
    

Since `address` will ultimately depend on the `class_hash` and `calldata`, it’s safe for the protocol to validate the signature and spend the funds on that address.

[](#standard_interface)
Standard interface
------------------------------------------

The [`IAccount.cairo`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/account/IAccount.cairo)
 contract interface contains the standard account interface proposed in [#41](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and adopted by OpenZeppelin and Argent. It implements [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and it is agnostic of signature validation. Further, nonce management is handled on the protocol level.

|     |     |
| --- | --- |
|     | `__validate_deploy__` is not part of the interface since it’s only callable by the protocol. Also contracts don’t need to implement it to be considered accounts. |

    struct Call {
        to: felt,
        selector: felt,
        calldata_len: felt,
        calldata: felt*,
    }
    
    // Tmp struct introduced while we wait for Cairo to support passing `[Call]` to __execute__
    struct CallArray {
        to: felt,
        selector: felt,
        data_offset: felt,
        data_len: felt,
    }
    
    
    @contract_interface
    namespace IAccount {
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    
        func isValidSignature(hash: felt, signature_len: felt, signature: felt*) -> (isValid: felt) {
        }
    
        func __validate__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) {
        }
    
        func __validate_declare__(class_hash: felt) {
        }
    
        func __execute__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
        }
    }

[](#keys_signatures_and_signers)
Keys, signatures and signers
-------------------------------------------------------------

While the interface is agnostic of signature validation schemes, this implementation assumes there’s a public-private key pair controlling the Account. That’s why the `constructor` function expects a `public_key` parameter to set it. Since there’s also a `setPublicKey()` method, accounts can be effectively transferred.

### [](#signature_validation)
Signature validation

Signature validation occurs separately from execution as of Cairo v0.10. Upon receiving transactions, an account contract first calls `__validate__`. An account will only execute a transaction if, and only if, the signature proves valid. This decoupling allows for a protocol-level distinction between invalid and reverted transactions. See [Account entrypoints](#account_entrypoints)
.

### [](#signer)
Signer

The signer is responsible for creating a transaction signature with the user’s private key for a given transaction. This implementation utilizes [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 class to create transaction signatures through the `Signer` method `sign_transaction`.

`sign_transaction` expects the following parameters per transaction:

*   `sender` the contract address invoking the tx.
    
*   `calls` a list containing a sublist of each call to be sent. Each sublist must consist of:
    
    1.  `to` the address of the target contract of the message.
        
    2.  `selector` the function to be called on the target contract.
        
    3.  `calldata` the parameters for the given `selector`.
        
    
*   `nonce` an unique identifier of this message to prevent transaction replays.
    
*   `max_fee` the maximum fee a user will pay.
    

Which returns:

*   `calldata` a list of arguments for each call.
    
*   `sig_r` the transaction signature.
    
*   `sig_s` the transaction signature.
    

While the `Signer` class performs much of the work for a transaction to be sent, it neither manages nonces nor invokes the actual transaction on the Account contract. To simplify Account management, most of this is abstracted away with `MockSigner`.

### [](#mocksigner_utility)
MockSigner utility

The `MockSigner` class in [signers.py](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/tests/signers.py)
 is used to perform transactions on a given Account, crafting the transaction and managing nonces.

|     |     |
| --- | --- |
|     | StarkNet’s testing framework does not currently support transaction invocations from account contracts. `MockSigner` therefore utilizes StarkNet’s API gateway to manually execute the `InvokeFunction` for testing. |

A `MockSigner` instance exposes the following methods:

*   `send_transaction(account, to, selector_name, calldata, nonce=None, max_fee=0)` returns a [future](https://docs.python.org/3/library/asyncio-future.html)
     of a signed transaction, ready to be sent.
    
*   `send_transactions(account, calls, nonce=None, max_fee=0)` returns a future of batched signed transactions, ready to be sent.
    
*   `declare_class(account, contract_name, nonce=None, max_fee=0)` returns a future of a declaration transaction.
    
*   `deploy_account(state, calldata, salt=0, nonce=0, max_fee=0)`: returns a future of a counterfactual deployment.
    

To use `MockSigner`, pass a private key when instantiating the class:

    from utils import MockSigner
    
    PRIVATE_KEY = 123456789987654321
    signer = MockSigner(PRIVATE_KEY)

Then send single transactions with the `send_transaction` method.

    await signer.send_transaction(account, contract_address, 'method_name', [])

If utilizing multicall, send multiple transactions with the `send_transactions` method.

    await signer.send_transactions(
        account,
        [\
            (contract_address, 'method_name', [param1, param2]),\
            (contract_address, 'another_method', [])\
        ]
    )

Use `declare_class` to declare a contract:

    await signer.declare_class(account, "MyToken")

And `deploy_account` to [counterfactually](#counterfactual_deployments)
 deploy an account:

    await signer.deploy_account(state, [signer.public_key])

### [](#mockethsigner_utility)
MockEthSigner utility

The `MockEthSigner` class in [signers.py](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/tests/signers.py)
 is used to perform transactions on a given Account with a secp256k1 curve key pair, crafting the transaction and managing nonces. It differs from the `MockSigner` implementation by:

*   Not using the public key but its derived address instead (the last 20 bytes of the keccak256 hash of the public key and adding `0x` to the beginning).
    
*   Signing the message with a secp256k1 curve address.
    

[](#call_and_accountcallarray_format)
`Call` and `AccountCallArray` format
--------------------------------------------------------------------------

The idea is for all user intent to be encoded into a `Call` representing a smart contract call. Users can also pack multiple messages into a single transaction (creating a multicall transaction). Cairo currently does not support arrays of structs with pointers which means the `__execute__` function cannot properly iterate through multiple `Call`s. Instead, this implementation utilizes a workaround with the `AccountCallArray` struct. See [Multicall transactions](#multicall_transactions)
.

### [](#call)
`Call`

A single `Call` is structured as follows:

    struct Call {
        to: felt
        selector: felt
        calldata_len: felt
        calldata: felt*
    }

Where:

*   `to` is the address of the target contract of the message.
    
*   `selector` is the selector of the function to be called on the target contract.
    
*   `calldata_len` is the number of calldata parameters.
    
*   `calldata` is an array representing the function parameters.
    

### [](#accountcallarray)
`AccountCallArray`

`AccountCallArray` is structured as:

    struct AccountCallArray {
        to: felt
        selector: felt
        data_offset: felt
        data_len: felt
    }

Where:

*   `to` is the address of the target contract of the message.
    
*   `selector` is the selector of the function to be called on the target contract.
    
*   `data_offset` is the starting position of the calldata array that holds the `Call`'s calldata.
    
*   `data_len` is the number of calldata elements in the `Call`.
    

[](#multicall_transactions)
Multicall transactions
--------------------------------------------------

A multicall transaction packs the `to`, `selector`, `calldata_offset`, and `calldata_len` of each call into the `AccountCallArray` struct and keeps the cumulative calldata for every call in a separate array. The `__execute__` function rebuilds each message by combining the `AccountCallArray` with its calldata (demarcated by the offset and calldata length specified for that particular call). The rebuilding logic is set in the internal `_from_call_array_to_call`.

This is the basic flow:

First, the user sends the messages for the transaction through a Signer instantiation which looks like this:

    await signer.send_transaction(
        account, [\
            (contract_address, 'contract_method', [arg_1]),\
            (contract_address, 'another_method', [arg_1, arg_2])\
        ]
    )

Then the `from_call_to_call_array` method in [Nile’s signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 converts each call into the `AccountCallArray` format and cumulatively stores the calldata of every call into a single array. Next, both arrays (as well as the `sender`, `nonce`, and `max_fee`) are used to create the transaction hash. The Signer then invokes `__execute__` with the signature and passes `AccountCallArray`, calldata, and nonce as arguments.

Finally, the `__execute__` method takes the `AccountCallArray` and calldata and builds an array of `Call`s (MultiCall).

|     |     |
| --- | --- |
|     | Every transaction utilizes `AccountCallArray`. A single `Call` is treated as a bundle with one message. |

[](#api_specification)
API Specification
----------------------------------------

This in a nutshell is the Account contract public API:

    namespace Account {
        func constructor(publicKey: felt) {
        }
    
        func getPublicKey() -> (publicKey: felt) {
        }
    
        func supportsInterface(interfaceId: felt) -> (success: felt) {
        }
    
        func setPublicKey(newPublicKey: felt) {
        }
    
        func isValidSignature(hash: felt, signature_len: felt, signature: felt*) -> (isValid: felt) {
        }
    
        func __validate__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
        }
    
        func __validate_declare__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
        }
    
        func __execute__(
            call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*
        ) -> (response_len: felt, response: felt*) {
    }

### [](#constructor)
`constructor`

Initializes and sets the public key for the Account contract.

Parameters:

    publicKey: felt

Returns: None.

### [](#getpublickey)
`getPublicKey`

Returns the public key associated with the Account.

Parameters: None.

Returns:

    publicKey: felt

### [](#supportsinterface)
`supportsInterface`

Returns `TRUE` if this contract implements the interface defined by `interfaceId`. Account contracts now implement ERC165 through static support (see [Account introspection with ERC165](#account_introspection_with_erc165)
).

Parameters:

    interfaceId: felt

Returns:

    success: felt

### [](#setpublickey)
`setPublicKey`

Sets the public key that will control this Account. It can be used to rotate keys for security, change them in case of compromised keys or even transferring ownership of the account.

Parameters:

    newPublicKey: felt

Returns: None.

### [](#isvalidsignature)
`isValidSignature`

This function is inspired by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and returns `TRUE` if a given signature is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    hash: felt
    signature_len: felt
    signature: felt*

Returns:

    isValid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#validate)
`__validate__`

Validates the transaction signature and is called prior to `__execute__`.

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*

Returns: None.

### [](#validate_declare)
`__validate_declare__`

Validates the signature for declaration transactions.

Parameters:

    class_hash: felt

Returns: None.

### [](#validate_deploy)
`__validate_deploy__`

Validates the signature for counterfactual deployment transactions.

It takes the `class_hash` of the account being deployed along with the `salt` and `calldata`, the latter being expanded. For example if the account is deployed with calldata `[arg_1, …​, arg_n]`:

Parameters:

    class_hash: felt
    salt: felt
    arg_1: felt
    ...
    arg_n: felt

Returns: None.

### [](#execute)
`__execute__`

This is the only external entrypoint to interact with the Account contract. It:

1.  Calls the target contract with the intended function selector and calldata parameters.
    
2.  Forwards the contract call response data as return value.
    

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*

|     |     |
| --- | --- |
|     | The current signature scheme expects a 2-element array like `[sig_r, sig_s]`. |

Returns:

    response_len: felt
    response: felt*

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset differs on the signature type being used by the Account.

### [](#account)
Account

The [`Account`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/account/presets/Account.cairo)
 preset uses StarkNet keys to validate transactions.

### [](#eth_account)
Eth Account

The [`EthAccount`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/account/presets/EthAccount.cairo)
 preset supports Ethereum addresses, validating transactions with secp256k1 keys.

[](#account_introspection_with_erc165)
Account introspection with ERC165
------------------------------------------------------------------------

Certain contracts like ERC721 or ERC1155 require a means to differentiate between account contracts and non-account contracts. For a contract to declare itself as an account, it should implement [ERC165](https://eips.ethereum.org/EIPS/eip-165)
 as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
.

To be in compliance with ERC165 specifications, we calculate the account contract ID as the XOR of `IAccount`'s equivalent EVM selectors (not StarkNet selectors). This magic value has been tracking the changes of the still evolving Account interface standard, and **its current value is `0xa66bd575`**.

Our ERC165 integration on StarkNet is inspired by OpenZeppelin’s Solidity implementation of [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
 which stores the interfaces that the implementing contract supports. In the case of account contracts, querying `supportsInterface` of an account’s address with the `IAccount` magic value should return `TRUE`.

|     |     |
| --- | --- |
|     | For Account contracts, ERC165 support is static and does not require Account contracts to register. |

[](#extending_the_account_contract)
Extending the Account contract
------------------------------------------------------------------

Account contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
.

To implement custom account contracts, it’s required by the StarkNet compiler that they include the three entrypoint functions `__validate__`, `__validate_declare__`, and `__execute__`.

`__validate__` and `__validate_declare__` should include the same signature validation method; whereas, `__execute__` should only handle the actual transaction. Incorporating a new validation scheme necessitates only that it’s invoked by both `__validate__` and `__validate_declare__`.

This is why the Account library comes with different flavors of signature validation methods like `is_valid_eth_signature` and the vanilla `is_valid_signature`.

Account contract developers are encouraged to implement the [standard Account interface](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and incorporate the custom logic thereafter.

|     |     |
| --- | --- |
|     | Due to current inconsistencies between the testing framework and the actual StarkNet network, extreme caution should be used when integrating new Account contracts. Instances have occurred where account functionality tests pass and transactions execute correctly on the local node; yet, they fail on public networks. For this reason, it’s highly encouraged that new account contracts are also deployed and tested on the public testnet. See [issue #386](https://github.com/OpenZeppelin/cairo-contracts/issues/386)<br> for more information. |

Some other validation schemes to look out for in the future:

*   Multisig.
    
*   Guardian logic like in [Argent’s account](https://github.com/argentlabs/argent-contracts-starknet/blob/de5654555309fa76160ba3d7393d32d2b12e7349/contracts/ArgentAccount.cairo)
    .
    

[](#l1_escape_hatch_mechanism)
L1 escape hatch mechanism
--------------------------------------------------------

[](#paying_for_gas)
Paying for gas
----------------------------------

[← Proxies and Upgrades](/contracts-cairo/0.6.0/proxies)

[Access Control →](/contracts-cairo/0.6.0/access)




 SNIP12 and Typed Messages - OpenZeppelin Docs       

SNIP12 and Typed Messages
=========================

Similar to [EIP712](https://eips.ethereum.org/EIPS/eip-712)
, [SNIP12](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md)
 is a standard for secure off-chain signature verification on Starknet. It provides a way to hash and sign generic typed structs rather than just strings. When building decentralized applications, usually you might need to sign a message with complex data. The purpose of signature verification is then to ensure that the received message was indeed signed by the expected signer, and it hasn’t been tampered with.

OpenZeppelin Contracts for Cairo provides a set of utilities to make the implementation of this standard as easy as possible, and in this guide we will walk you through the process of generating the hashes of typed messages using these utilities for on-chain signature verification. For that, let’s build an example with a custom [ERC20](../api/erc20#ERC20)
 contract adding an extra `transfer_with_signature` method.

|     |     |
| --- | --- |
|     | This is an educational example, and it is not intended to be used in production environments. |

[](#customerc20)
CustomERC20
----------------------------

Let’s start with a basic ERC20 contract leveraging the [ERC20Component](../api/erc20#ERC20Component)
, and let’s add the new function. Note that some declarations are omitted for brevity. The full example will be available at the end of the guide.

    #[starknet::contract]
    mod CustomERC20 {
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
    
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            initial_supply: u256,
            recipient: ContractAddress
        ) {
            self.erc20.initializer("MyToken", "MTK");
            self.erc20._mint(recipient, initial_supply);
        }
    
        #[external(v0)]
        fn transfer_with_signature(
            ref self: ContractState,
            recipient: ContractAddress,
            amount: u256,
            nonce: felt252,
            expiry: u64,
            signature: Array<felt252>
        ) {
            (...)
        }
    }

The `transfer_with_signature` function will allow a user to transfer tokens to another account by providing a signature. The signature will be generated off-chain, and it will be used to verify the message on-chain. Note that the message we need to verify is a struct with the following fields:

*   `recipient`: The address of the recipient.
    
*   `amount`: The amount of tokens to transfer.
    
*   `nonce`: A unique number to prevent replay attacks.
    
*   `expiry`: The timestamp when the signature expires.
    

Note that generating the hash of this message on-chain is a requirement to verify the signature, because if we accept the message as a parameter, it could be easily tampered with.

[](#generating_the_typed_message_hash)
Generating the Typed Message Hash
------------------------------------------------------------------------

To generate the hash of the message, we need to follow these steps:

### [](#1_define_the_message_struct)
1\. Define the message struct.

In this particular example, the message struct looks like this:

    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }

### [](#2_get_the_message_type_hash)
2\. Get the message type hash.

This is the `starknet_keccak(encode_type(message))` as defined in the [SNIP](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md#how-to-work-with-each-type)
.

In this case it can be computed as follows:

    let message_type_hash = selector!(
        "\"Message\"(\"recipient\":\"ContractAddress\",\"amount\":\"u256\",\"nonce\":\"felt\",\"expiry\":\"u64\")\"u256\"(\"low\":\"felt\",\"high\":\"felt\")"
    );

which is the same as:

    let message_type_hash = 0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;

|     |     |
| --- | --- |
|     | In practice it’s better to compute the type hash off-chain and hardcode it in the contract, since it is a constant value. |

### [](#3_implement_the_structhash_trait_for_the_struct)
3\. Implement the `StructHash` trait for the struct.

You can import the trait from: `openzeppelin::utils::snip12::StructHash`. And this implementation is nothing more than the encoding of the message as defined in the [SNIP](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md#how-to-work-with-each-type)
.

    use openzeppelin::utils::snip12::StructHash;
    
    use core::hash::HashStateExTrait;
    use hash::{HashStateTrait, Hash};
    use poseidon::PoseidonTrait;
    use starknet::ContractAddress;
    
    const MESSAGE_TYPE_HASH: felt252 =
        0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;
    
    #[derive(Copy, Drop, Hash)]
    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }
    
    impl StructHashImpl of StructHash<Message> {
        fn hash_struct(self: @Message) -> felt252 {
            let hash_state = PoseidonTrait::new();
            hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize()
        }
    }

### [](#4_implement_the_snip12metadata_trait)
4\. Implement the `SNIP12Metadata` trait.

This implementation determines the values of the domain separator. Only the `name` and `version` fields are required because the `chain_id` is obtained on-chain, and the `revision` is hardcoded to `1`.

    use openzeppelin::utils::snip12::SNIP12Metadata;
    
    impl SNIP12MetadataImpl of SNIP12Metadata {
        fn name() -> felt252 { 'DAPP_NAME' }
        fn version() -> felt252 { 'v1' }
    }

|     |     |
| --- | --- |
|     | These params could be set in the contract constructor, but then two storage reads would be executed every time a message hash needs to be generated, and this is unnecessary overhead. When Starknet implements immutable storage set in constructor, that approach will be more efficient. |

### [](#5_generate_the_hash)
5\. Generate the hash.

The final step is to use the `OffchainMessageHashImpl` implementation to generate the hash of the message using the `get_message_hash` function. The implementation is already available as a utility.

    use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl};
    
    use core::hash::HashStateExTrait;
    use hash::{HashStateTrait, Hash};
    use poseidon::PoseidonTrait;
    use starknet::ContractAddress;
    
    const MESSAGE_TYPE_HASH: felt252 =
        0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;
    
    #[derive(Copy, Drop, Hash)]
    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }
    
    impl StructHashImpl of StructHash<Message> {
        fn hash_struct(self: @Message) -> felt252 {
            let hash_state = PoseidonTrait::new();
            hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize()
        }
    }
    
    impl SNIP12MetadataImpl of SNIP12Metadata {
        fn name() -> felt252 { 'DAPP_NAME' }
        fn version() -> felt252 { 'v1' }
    }
    
    fn get_hash(
        account: ContractAddress,
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    ) -> felt252 {
        let message = Message {
            recipient,
            amount,
            nonce,
            expiry
        };
        message.get_message_hash(account)
    }

|     |     |
| --- | --- |
|     | The expected parameter for the `get_message_hash` function is the address of account that signed the message. |

[](#full_implementation)
Full Implementation
--------------------------------------------

Finally, the full implementation of the `CustomERC20` contract looks like this:

|     |     |
| --- | --- |
|     | We are using the [`DualCaseAccount`](../interfaces#dualcase_dispatchers)<br> to verify the signature, and the [`NoncesComponent`](../api/utilities#NoncesComponent)<br> to handle nonces to prevent replay attacks. |

    use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl};
    
    use core::hash::HashStateExTrait;
    use hash::{HashStateTrait, Hash};
    use poseidon::PoseidonTrait;
    use starknet::ContractAddress;
    
    const MESSAGE_TYPE_HASH: felt252 =
        0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;
    
    #[derive(Copy, Drop, Hash)]
    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }
    
    impl StructHashImpl of StructHash<Message> {
        fn hash_struct(self: @Message) -> felt252 {
            let hash_state = PoseidonTrait::new();
            hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize()
        }
    }
    
    #[starknet::contract]
    mod CustomERC20 {
        use openzeppelin::account::dual_account::{DualCaseAccount, DualCaseAccountABI};
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use openzeppelin::utils::cryptography::nonces::NoncesComponent;
        use starknet::ContractAddress;
    
        use super::{Message, OffchainMessageHashImpl, SNIP12Metadata};
    
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
        component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);
    
        #[abi(embed_v0)]
        impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[abi(embed_v0)]
        impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;
        impl NoncesInternalImpl = NoncesComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc20: ERC20Component::Storage,
            #[substorage(v0)]
            nonces: NoncesComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC20Event: ERC20Component::Event,
            #[flat]
            NoncesEvent: NoncesComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, initial_supply: u256, recipient: ContractAddress) {
            self.erc20.initializer("MyToken", "MTK");
            self.erc20._mint(recipient, initial_supply);
        }
    
        /// Required for hash computation.
        impl SNIP12MetadataImpl of SNIP12Metadata {
            fn name() -> felt252 {
                'CustomERC20'
            }
            fn version() -> felt252 {
                'v1'
            }
        }
    
        #[external(v0)]
        fn transfer_with_signature(
            ref self: ContractState,
            recipient: ContractAddress,
            amount: u256,
            nonce: felt252,
            expiry: u64,
            signature: Array<felt252>
        ) {
            assert(starknet::get_block_timestamp() <= expiry, 'Expired signature');
            let owner = starknet::get_caller_address();
    
            // Check and increase nonce
            self.nonces.use_checked_nonce(owner, nonce);
    
            // Build hash for calling `is_valid_signature`
            let message = Message { recipient, amount, nonce, expiry };
            let hash = message.get_message_hash(owner);
    
            let is_valid_signature_felt = DualCaseAccount { contract_address: owner }
                .is_valid_signature(hash, signature);
    
            // Check either 'VALID' or True for backwards compatibility
            let is_valid_signature = is_valid_signature_felt == starknet::VALIDATED
                || is_valid_signature_felt == 1;
            assert(is_valid_signature, 'Invalid signature');
    
            // Transfer tokens
            self.erc20._transfer(owner, recipient, amount);
        }
    }

[← Counterfactual Deployments](/contracts-cairo/0.13.0/guides/deployment)

[Access →](/contracts-cairo/0.13.0/access)




 Access - OpenZeppelin Docs       

Access
======

Access control—​that is, "who is allowed to do this thing"—is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#ownership_and_ownable)
Ownership and `Ownable`
--------------------------------------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/access/ownable/ownable.cairo)
 for implementing ownership in your contracts.

### [](#usage)
Usage

Integrating this component into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [`initializer`](api/access#OwnableComponent-initializer)
 like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        #[abi(embed_v0)]
        impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
        #[abi(embed_v0)]
        impl OwnableCamelOnlyImpl =
            OwnableComponent::OwnableCamelOnlyImpl<ContractState>;
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Set the initial owner of the contract
            self.ownable.initializer(owner);
        }
    
        (...)
    }

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        #[external(v0)]
        fn only_owner_allowed(ref self: ContractState) {
            // This function can only be called by the owner
            self.ownable.assert_only_owner();
    
            (...)
        }
    }

### [](#interface)
Interface

This is the full interface of the `Ownable` implementation:

    trait IOwnable {
        /// Returns the current owner.
        fn owner() -> ContractAddress;
    
        /// Transfers the ownership from the current owner to a new owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

Ownable also lets you:

*   `transfer_ownership` from the owner account to a new one, and
    
*   `renounce_ownership` for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
    

|     |     |
| --- | --- |
|     | Removing the owner altogether will mean that administrative tasks that are protected by `assert_only_owner` will no longer be callable! |

### [](#two_step_transfer)
Two step transfer

The component also offers a more robust way of transferring ownership via the [OwnableTwoStepImpl](api/access#OwnableTwoStepImpl)
 implementation. A two step transfer mechanism helps to prevent unintended and irreversible owner transfers. Simply replace the `OwnableImpl` and `OwnableCamelOnlyImpl` with their respective two step variants:

    #[abi(embed_v0)]
    impl OwnableTwoStepImpl = OwnableComponent::OwnableTwoStepImpl<ContractState>;
    #[abi(embed_v0)]
    impl OwnableTwoStepCamelOnlyImpl =
        OwnableComponent::OwnableTwoStepCamelOnlyImpl<ContractState>;

#### [](#interface-twostep)
Interface

This is the full interface of the two step `Ownable` implementation:

    trait IOwnableTwoStep {
        /// Returns the address of the current owner.
        fn owner() -> ContractAddress;
    
        /// Returns the address of the pending owner.
        fn pending_owner() -> ContractAddress;
    
        /// Finishes the two-step ownership transfer process
        /// by accepting the ownership.
        fn accept_ownership();
    
        /// Starts the two-step ownership transfer process
        /// by setting the pending owner.
        fn transfer_ownership(new_owner: ContractAddress);
    
        /// Renounces the ownership of the contract.
        fn renounce_ownership();
    }

[](#role_based_accesscontrol)
Role-Based `AccessControl`
--------------------------------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [`assert_only_owner`](api/access#OwnableComponent-assert_only_owner)
. This check can be enforced through [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage_2)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role. See [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers.

Here’s a simple example of implementing `AccessControl` on a portion of an ERC20 token contract which defines and sets a 'minter' role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
        use super::MINTER_ROLE;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    }

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](api/access#AccessControlComponent)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](api/access#OwnableComponent)
. Where `AccessControl` shines the most is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            ERC20Event: ERC20Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            minter: ContractAddress,
            burner: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(MINTER_ROLE, minter);
            self.accesscontrol._grant_role(BURNER_ROLE, burner);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](api/access#AccessControlComponent-_grant_role)
, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the [`assert_only_role`](api/access#AccessControlComponent-assert_only_role)
 check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the [`grant_role`](api/access#AccessControlComponent-grant_role)
 and [`revoke_role`](api/access#AccessControlComponent-revoke_role)
 functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless [`_set_role_admin`](api/access#AccessControlComponent-_set_role_admin)
 is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");
    const BURNER_ROLE: felt252 = selector!("BURNER_ROLE");
    
    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE;
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
        use super::{MINTER_ROLE, BURNER_ROLE};
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        // ERC20
        #[abi(embed_v0)]
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            initial_supply: u256,
            recipient: ContractAddress,
            admin: ContractAddress
        ) {
            // ERC20-related initialization
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, initial_supply);
    
            // AccessControl-related initialization
            self.accesscontrol.initializer();
            self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin);
        }
    
        /// This function can only be called by a minter.
        #[external(v0)]
        fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(MINTER_ROLE);
            self.erc20._mint(recipient, amount);
        }
    
        /// This function can only be called by a burner.
        #[external(v0)]
        fn burn(ref self: ContractState, account: ContractAddress, amount: u256) {
            self.accesscontrol.assert_only_role(BURNER_ROLE);
            self.erc20._burn(account, amount);
        }
    }

|     |     |
| --- | --- |
|     | The `grant_role` and `revoke_role` functions are automatically exposed as `external` functions from the `AccessControlImpl` by leveraging the `#[abi(embed_v0)]` annotation. |

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier.

For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements (`felt252`) store a maximum of 252 bits. With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   Use [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)
     instead.
    
*   Use Cairo friendly hashing algorithms like Poseidon, which are implemented in the [Cairo corelib](https://github.com/starkware-libs/cairo/blob/main/corelib/src/poseidon.cairo)
    .
    

|     |     |
| --- | --- |
|     | The `selector!` macro can be used to compute [sn\_keccak](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#starknet_keccak)<br> in Cairo. |

### [](#interface_2)
Interface

This is the full interface of the `AccessControl` implementation:

    trait IAccessControl {
        /// Returns whether the account has the role or not.
        fn has_role(role: felt252, account: ContractAddress) -> bool;
    
        /// Returns the admin role that controls `role`.
        fn get_role_admin(role: felt252) -> felt252;
    
        /// Grants `role` to `account`.
        fn grant_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from `account`.
        fn revoke_role(role: felt252, account: ContractAddress);
    
        /// Revokes `role` from self.
        fn renounce_role(role: felt252, account: ContractAddress);
    }

`AccessControl` also lets you `renounce_role` from the calling account. The method expects an account as input as an extra security measure, to ensure you are not renouncing a role from an unintended account.

[← SNIP12 and Typed Messages](/contracts-cairo/0.13.0/guides/snip12)

[API Reference →](/contracts-cairo/0.13.0/api/access)




 Counterfactual deployments - OpenZeppelin Docs       

Counterfactual deployments
==========================

A counterfactual contract is a contract we can interact with even before actually deploying it on-chain. For example, we can send funds or assign privileges to a contract that doesn’t yet exist. Why? Because deployments in Starknet are deterministic, allowing us to predict the address where our contract will be deployed. We can leverage this property to make a contract pay for its own deployment by simply sending funds in advance. We call this a counterfactual deployment.

This process can be described with the following steps:

|     |     |
| --- | --- |
|     | For testing this flow you can check the [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/starknet/account.html)<br> or the [Starkli](https://book.starkli.rs/accounts#account-deployment)<br> guides for deploying accounts. |

1.  Deterministically precompute the `contract_address` given a `class_hash`, `salt`, and constructor `calldata`. Note that the `class_hash` must be previously declared for the deployment to succeed.
    
2.  Send funds to the `contract_address`. Usually you will estimate the fee of the transaction first. Existing tools usually do this for you.
    
3.  Send a `DeployAccount` type transaction to the network.
    
4.  The protocol will then validate the transaction with the `__validate_deploy__` entrypoint of the contract to be deployed.
    
5.  If the validation succeeds, the protocol will charge the fee and then register the contract as deployed.
    

|     |     |
| --- | --- |
|     | Although this method is very popular to deploy accounts, this works for any kind of contract. |

[](#deployment_validation)
Deployment validation
------------------------------------------------

To be counterfactually deployed, the deploying contract must implement the `__validate_deploy__` entrypoint, called by the protocol when a `DeployAccount` transaction is sent to the network.

    trait IDeployable {
        /// Must return 'VALID' when the validation is successful.
        fn __validate_deploy__(
            class_hash: felt252, contract_address_salt: felt252, public_key: felt252
        ) -> felt252;
    }

[← Interfaces and Dispatchers](/contracts-cairo/0.10.0/interfaces)

[Access →](/contracts-cairo/0.10.0/access)




 Components - OpenZeppelin Docs       

Components
==========

The following documentation provides reasoning and examples on how to use Contracts for Cairo components.

Starknet components are separate modules that contain storage, events, and implementations that can be integrated into a contract. Components themselves cannot be declared or deployed. Another way to think of components is that they are abstract modules that must be instantiated.

|     |     |
| --- | --- |
|     | For more information on the construction and design of Starknet components, see the [Starknet Shamans post](https://community.starknet.io/t/cairo-components/101136#components-1)<br> and the [Cairo book](https://book.cairo-lang.org/ch99-01-05-00-components.html)<br>. |

[](#building_a_contract)
Building a contract
--------------------------------------------

### [](#setup)
Setup

The contract should first import the component and declare it with the `component!` macro:

    #[starknet::contract]
    mod MyContract {
        // Import the component
        use openzeppelin::security::InitializableComponent;
    
        // Declare the component
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    }

The `path` argument should be the imported component itself (in this case, [InitializableComponent](security#initializable)
). The `storage` and `event` arguments are the variable names that will be set in the `Storage` struct and `Event` enum, respectively. Note that even if the component doesn’t define any events, the compiler will still create an empty event enum inside the component module.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

The `#[substorage(v0)]` attribute must be included for each component in the `Storage` trait. This allows the contract to have indirect access to the component’s storage. See [Accessing component storage](#accessing_component_storage)
 for more on this.

The `#[flat]` attribute for events in the `Event` enum, however, is not required. For component events, the first key in the event log is the component ID. Flattening the component event removes it, leaving the event ID as the first key.

### [](#implementations)
Implementations

Components come with granular implementations of different interfaces. This allows contracts to integrate only the implementations that they’ll use and avoid unnecessary bloat. Integrating an implementation looks like this:

    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        // Gives the contract access to the implementation methods
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

Defining an `impl` gives the contract access to the methods within the implementation from the component. For example, `is_initialized` is defined in the `InitializableImpl`. A function on the contract level can expose it like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    
        #[external(v0)]
        fn is_initialized(ref self: ContractState) -> bool {
            self.initializable.is_initialized()
        }
    }

While there’s nothing wrong with manually exposing methods like in the previous example, this process can be tedious for implementations with many methods. Fortunately, a contract can embed implementations which will expose all of the methods of the implementation. To embed an implementation, add the `#[abi(embed_v0)]` attribute above the `impl`:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        // This attribute exposes the methods of the `impl`
        #[abi(embed_v0)]
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

`InitializableImpl` defines the `is_initialized` method in the component. By adding the embed attribute, `is_initialized` becomes a contract entrypoint for `MyContract`.

|     |     |
| --- | --- |
|     | Embeddable implementations, when available in this library’s components, are segregated from the internal component implementation which makes it easier to safely expose. Components also separate granular implementations from [mixin](#mixins)<br> implementations. The API documentation design reflects these groupings. See [ERC20Component](api/erc20#ERC20Component)<br> as an example which includes:<br><br>*   **Embeddable Mixin Implementation**<br>    <br>*   **Embeddable Implementations**<br>    <br>*   **Internal Implementations**<br>    <br>*   **Events** |

### [](#mixins)
Mixins

Mixins are impls made of a combination of smaller, more specific impls. While separating components into granular implementations offers flexibility, integrating components with many implementations can appear crowded especially if the contract uses all of them. Mixins simplify this by allowing contracts to embed groups of implementations with a single directive.

Compare the following code blocks to see the benefit of using a mixin when creating an account contract.

#### [](#account_without_mixin)
Account without mixin

    component!(path: AccountComponent, storage: account, event: AccountEvent);
    component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
    #[abi(embed_v0)]
    impl SRC6Impl = AccountComponent::SRC6Impl<ContractState>;
    #[abi(embed_v0)]
    impl DeclarerImpl = AccountComponent::DeclarerImpl<ContractState>;
    #[abi(embed_v0)]
    impl DeployableImpl = AccountComponent::DeployableImpl<ContractState>;
    #[abi(embed_v0)]
    impl PublicKeyImpl = AccountComponent::PublicKeyImpl<ContractState>;
    #[abi(embed_v0)]
    impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl<ContractState>;
    #[abi(embed_v0)]
    impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl<ContractState>;
    impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
    #[abi(embed_v0)]
    impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;

#### [](#account_with_mixin)
Account with mixin

    component!(path: AccountComponent, storage: account, event: AccountEvent);
    component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
    #[abi(embed_v0)]
    impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
    impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;

The rest of the setup for the contract, however, does not change. This means that component dependencies must still be included in the `Storage` struct and `Event` enum. Here’s a full example of an account contract that embeds the `AccountMixinImpl`:

    #[starknet::contract]
    mod Account {
        use openzeppelin::account::AccountComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccountComponent, storage: account, event: AccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // This embeds all of the methods from the many AccountComponent implementations
        // and also includes `supports_interface` from `SRC5Impl`
        #[abi(embed_v0)]
        impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
        impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            account: AccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccountEvent: AccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: felt252) {
            self.account.initializer(public_key);
        }
    }

### [](#initializers)
Initializers

|     |     |
| --- | --- |
|     | Failing to use a component’s `initializer` can result in irreparable contract deployments. Always read the API documentation for each integrated component. |

Some components require some sort of setup upon construction. Usually, this would be a job for a constructor; however, components themselves cannot implement constructors. Components instead offer `initializer`s within their `InternalImpl` to call from the contract’s constructor. Let’s look at how a contract would integrate [OwnableComponent](api/access#OwnableComponent)
:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        // Instantiate `InternalImpl` to give the contract access to the `initializer`
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Invoke ownable's `initializer`
            self.ownable.initializer(owner);
        }
    }

### [](#dependencies)
Dependencies

Some components include dependencies of other components. Contracts that integrate components with dependencies must also include the component dependency. For instance, [AccessControlComponent](api/access#AccessControlComponent)
 depends on [SRC5Component](api/introspection#SRC5Component)
. Creating a contract with `AccessControlComponent` should look like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl AccessControlCamelImpl =
            AccessControlComponent::AccessControlCamelImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        (...)
    }

[](#customization)
Customization
--------------------------------

|     |     |
| --- | --- |
|     | Customizing implementations and accessing component storage can potentially corrupt the state, bypass security checks, and undermine the component logic. **Exercise extreme caution**. See [Security](#security)<br>. |

### [](#custom_implementations)
Custom implementations

There are instances where a contract requires different or amended behaviors from a component implementation. In these scenarios, a contract must create a custom implementation of the interface. Let’s break down a pausable ERC20 contract to see what that looks like. Here’s the setup:

    #[starknet::contract]
    mod ERC20Pausable {
        use openzeppelin::security::pausable::PausableComponent;
        use openzeppelin::token::erc20::ERC20Component;
        // Import the ERC20 interfaces to create custom implementations
        use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly};
        use starknet::ContractAddress;
    
        component!(path: PausableComponent, storage: pausable, event: PausableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
        impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    
        // `ERC20MetadataImpl` can keep the embed directive because the implementation
        // will not change
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        // Do not add the embed directive to these implementations because
        // these will be customized
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
    
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    }

The first thing to notice is that the contract imports the interfaces of the implementations that will be customized. These will be used in the next code example.

Next, the contract includes the [ERC20Component](api/erc20#ERC20Component)
 implementations; however, `ERC20Impl` and `ERC20CamelOnlyImplt` are **not** embedded. Instead, we want to expose our custom implementation of an interface. The following example shows the pausable logic integrated into the ERC20 implementations:

    #[starknet::contract]
    mod ERC20Pausable {
        (...)
    
        // Custom ERC20 implementation
        #[external(v0)]
        impl CustomERC20Impl of IERC20<ContractState> {
            fn transfer(
                ref self: ContractState, recipient: ContractAddress, amount: u256
            ) -> bool {
                // Add the custom logic
                self.pausable.assert_not_paused();
                // Add the original implementation method from `IERC20Impl`
                self.erc20.transfer(recipient, amount)
            }
    
            fn total_supply(self: @ContractState) -> u256 {
                // This method's behavior does not change from the component
                // implementation, but this method must still be defined.
                // Simply add the original implementation method from `IERC20Impl`
                self.erc20.total_supply()
            }
    
            (...)
        }
    
        // Custom ERC20CamelOnly implementation
        #[external(v0)]
        impl CustomERC20CamelOnlyImpl of IERC20CamelOnly<ContractState> {
            fn totalSupply(self: @ContractState) -> u256 {
                self.erc20.total_supply()
            }
    
            fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {
                self.erc20.balance_of(account)
            }
    
            fn transferFrom(
                ref self: ContractState,
                sender: ContractAddress,
                recipient: ContractAddress,
                amount: u256
            ) -> bool {
                self.pausable.assert_not_paused();
                self.erc20.transfer_from(sender, recipient, amount)
            }
        }
    }

Notice that in the `CustomERC20Impl`, the `transfer` method integrates `pausable.assert_not_paused` as well as `erc20.transfer` from `PausableImpl` and `ERC20Impl` respectively. This is why the contract defined the `ERC20Impl` from the component in the previous example.

Creating a custom implementation of an interface must define **all** methods from that interface. This is true even if the behavior of a method does not change from the component implementation (as `total_supply` exemplifies in this example).

|     |     |
| --- | --- |
|     | The ERC20 documentation provides another custom implementation guide for [Customizing decimals](erc20#customizing_decimals)<br>. |

### [](#accessing_component_storage)
Accessing component storage

There may be cases where the contract must read or write to an integrated component’s storage. To do so, use the same syntax as calling an implementation method except replace the name of the method with the storage variable like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        (...)
    
        fn write_to_comp_storage(ref self: ContractState) {
            self.initializable.Initializable_initialized.write(true);
        }
    
        fn read_from_comp_storage(self: @ContractState) -> bool {
            self.initializable.Initializable_initialized.read()
        }
    }

[](#security)
Security
----------------------

The maintainers of OpenZeppelin Contracts for Cairo are mainly concerned with the correctness and security of the code as published in the library.

Customizing implementations and manipulating the component state may break some important assumptions and introduce vulnerabilities. While we try to ensure the components remain secure in the face of a wide range of potential customizations, this is done in a best-effort manner. Any and all customizations to the component logic should be carefully reviewed and checked against the source code of the component they are customizing so as to fully understand their impact and guarantee their security.

[← Wizard](/contracts-cairo/0.10.0/wizard)

[Presets →](/contracts-cairo/0.10.0/presets)




 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes functions from different traits such as `IERC20` and `IERC20Camel`.

    #[starknet::interface]
    trait ERC20ABI<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> ByteArray;
        fn symbol(self: @DualCaseERC20) -> ByteArray;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    trait IERC20Camel<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, fallback, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Presets](/contracts-cairo/0.10.0/presets)

[Counterfactual Deployments →](/contracts-cairo/0.10.0/guides/deployment)




 SNIP12 and Typed Messages - OpenZeppelin Docs       

SNIP12 and Typed Messages
=========================

Similar to [EIP712](https://eips.ethereum.org/EIPS/eip-712)
, [SNIP12](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md)
 is a standard for secure off-chain signature verification on Starknet. It provides a way to hash and sign generic typed structs rather than just strings. When building decentralized applications, usually you might need to sign a message with complex data. The purpose of signature verification is then to ensure that the received message was indeed signed by the expected signer, and it hasn’t been tampered with.

OpenZeppelin Contracts for Cairo provides a set of utilities to make the implementation of this standard as easy as possible, and in this guide we will walk you through the process of generating the hashes of typed messages using these utilities for on-chain signature verification. For that, let’s build an example with a custom [ERC20](../api/erc20#ERC20)
 contract adding an extra `transfer_with_signature` method.

|     |     |
| --- | --- |
|     | This is an educational example, and it is not intended to be used in production environments. |

[](#customerc20)
CustomERC20
----------------------------

Let’s start with a basic ERC20 contract leveraging the [ERC20Component](../api/erc20#ERC20Component)
, and let’s add the new function. Note that some declarations are omitted for brevity. The full example will be available at the end of the guide.

    #[starknet::contract]
    mod CustomERC20 {
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use starknet::ContractAddress;
    
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            initial_supply: u256,
            recipient: ContractAddress
        ) {
            self.erc20.initializer("MyToken", "MTK");
            self.erc20.mint(recipient, initial_supply);
        }
    
        #[external(v0)]
        fn transfer_with_signature(
            ref self: ContractState,
            recipient: ContractAddress,
            amount: u256,
            nonce: felt252,
            expiry: u64,
            signature: Array<felt252>
        ) {
            (...)
        }
    }

The `transfer_with_signature` function will allow a user to transfer tokens to another account by providing a signature. The signature will be generated off-chain, and it will be used to verify the message on-chain. Note that the message we need to verify is a struct with the following fields:

*   `recipient`: The address of the recipient.
    
*   `amount`: The amount of tokens to transfer.
    
*   `nonce`: A unique number to prevent replay attacks.
    
*   `expiry`: The timestamp when the signature expires.
    

Note that generating the hash of this message on-chain is a requirement to verify the signature, because if we accept the message as a parameter, it could be easily tampered with.

[](#generating_the_typed_message_hash)
Generating the Typed Message Hash
------------------------------------------------------------------------

To generate the hash of the message, we need to follow these steps:

### [](#1_define_the_message_struct)
1\. Define the message struct.

In this particular example, the message struct looks like this:

    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }

### [](#2_get_the_message_type_hash)
2\. Get the message type hash.

This is the `starknet_keccak(encode_type(message))` as defined in the [SNIP](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md#how-to-work-with-each-type)
.

In this case it can be computed as follows:

    let message_type_hash = selector!(
        "\"Message\"(\"recipient\":\"ContractAddress\",\"amount\":\"u256\",\"nonce\":\"felt\",\"expiry\":\"u64\")\"u256\"(\"low\":\"felt\",\"high\":\"felt\")"
    );

which is the same as:

    let message_type_hash = 0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;

|     |     |
| --- | --- |
|     | In practice it’s better to compute the type hash off-chain and hardcode it in the contract, since it is a constant value. |

### [](#3_implement_the_structhash_trait_for_the_struct)
3\. Implement the `StructHash` trait for the struct.

You can import the trait from: `openzeppelin::utils::snip12::StructHash`. And this implementation is nothing more than the encoding of the message as defined in the [SNIP](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md#how-to-work-with-each-type)
.

    use openzeppelin::utils::snip12::StructHash;
    
    use core::hash::HashStateExTrait;
    use hash::{HashStateTrait, Hash};
    use poseidon::PoseidonTrait;
    use starknet::ContractAddress;
    
    const MESSAGE_TYPE_HASH: felt252 =
        0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;
    
    #[derive(Copy, Drop, Hash)]
    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }
    
    impl StructHashImpl of StructHash<Message> {
        fn hash_struct(self: @Message) -> felt252 {
            let hash_state = PoseidonTrait::new();
            hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize()
        }
    }

### [](#4_implement_the_snip12metadata_trait)
4\. Implement the `SNIP12Metadata` trait.

This implementation determines the values of the domain separator. Only the `name` and `version` fields are required because the `chain_id` is obtained on-chain, and the `revision` is hardcoded to `1`.

    use openzeppelin::utils::snip12::SNIP12Metadata;
    
    impl SNIP12MetadataImpl of SNIP12Metadata {
        fn name() -> felt252 { 'DAPP_NAME' }
        fn version() -> felt252 { 'v1' }
    }

In the above example, no storage reads are required which avoids unnecessary extra gas costs, but in some cases we may need to read from storage to get the domain separator values. This can be accomplished even when the trait is not bounded to the ContractState, like this:

    use openzeppelin::utils::snip12::SNIP12Metadata;
    
    impl SNIP12MetadataImpl of SNIP12Metadata {
        fn name() -> felt252 {
            let state = unsafe_new_contract_state();
    
            // Some logic to get the name from storage
            state.erc20.name().at(0).unwrap().into()
        }
    
        fn version() -> felt252 { 'v1' }
    }

### [](#5_generate_the_hash)
5\. Generate the hash.

The final step is to use the `OffchainMessageHashImpl` implementation to generate the hash of the message using the `get_message_hash` function. The implementation is already available as a utility.

    use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl};
    
    use core::hash::HashStateExTrait;
    use hash::{HashStateTrait, Hash};
    use poseidon::PoseidonTrait;
    use starknet::ContractAddress;
    
    const MESSAGE_TYPE_HASH: felt252 =
        0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;
    
    #[derive(Copy, Drop, Hash)]
    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }
    
    impl StructHashImpl of StructHash<Message> {
        fn hash_struct(self: @Message) -> felt252 {
            let hash_state = PoseidonTrait::new();
            hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize()
        }
    }
    
    impl SNIP12MetadataImpl of SNIP12Metadata {
        fn name() -> felt252 { 'DAPP_NAME' }
        fn version() -> felt252 { 'v1' }
    }
    
    fn get_hash(
        account: ContractAddress,
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    ) -> felt252 {
        let message = Message {
            recipient,
            amount,
            nonce,
            expiry
        };
        message.get_message_hash(account)
    }

|     |     |
| --- | --- |
|     | The expected parameter for the `get_message_hash` function is the address of account that signed the message. |

[](#full_implementation)
Full Implementation
--------------------------------------------

Finally, the full implementation of the `CustomERC20` contract looks like this:

|     |     |
| --- | --- |
|     | We are using the [`DualCaseAccount`](../interfaces#dualcase_dispatchers)<br> to verify the signature, and the [`NoncesComponent`](../api/utilities#NoncesComponent)<br> to handle nonces to prevent replay attacks. |

    use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl};
    
    use core::hash::HashStateExTrait;
    use hash::{HashStateTrait, Hash};
    use poseidon::PoseidonTrait;
    use starknet::ContractAddress;
    
    const MESSAGE_TYPE_HASH: felt252 =
        0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1;
    
    #[derive(Copy, Drop, Hash)]
    struct Message {
        recipient: ContractAddress,
        amount: u256,
        nonce: felt252,
        expiry: u64
    }
    
    impl StructHashImpl of StructHash<Message> {
        fn hash_struct(self: @Message) -> felt252 {
            let hash_state = PoseidonTrait::new();
            hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize()
        }
    }
    
    #[starknet::contract]
    mod CustomERC20 {
        use openzeppelin::account::dual_account::{DualCaseAccount, DualCaseAccountABI};
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use openzeppelin::utils::cryptography::nonces::NoncesComponent;
        use starknet::ContractAddress;
    
        use super::{Message, OffchainMessageHashImpl, SNIP12Metadata};
    
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
        component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);
    
        #[abi(embed_v0)]
        impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        #[abi(embed_v0)]
        impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;
        impl NoncesInternalImpl = NoncesComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc20: ERC20Component::Storage,
            #[substorage(v0)]
            nonces: NoncesComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC20Event: ERC20Component::Event,
            #[flat]
            NoncesEvent: NoncesComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, initial_supply: u256, recipient: ContractAddress) {
            self.erc20.initializer("MyToken", "MTK");
            self.erc20.mint(recipient, initial_supply);
        }
    
        /// Required for hash computation.
        impl SNIP12MetadataImpl of SNIP12Metadata {
            fn name() -> felt252 {
                'CustomERC20'
            }
            fn version() -> felt252 {
                'v1'
            }
        }
    
        #[external(v0)]
        fn transfer_with_signature(
            ref self: ContractState,
            recipient: ContractAddress,
            amount: u256,
            nonce: felt252,
            expiry: u64,
            signature: Array<felt252>
        ) {
            assert(starknet::get_block_timestamp() <= expiry, 'Expired signature');
            let owner = starknet::get_caller_address();
    
            // Check and increase nonce
            self.nonces.use_checked_nonce(owner, nonce);
    
            // Build hash for calling `is_valid_signature`
            let message = Message { recipient, amount, nonce, expiry };
            let hash = message.get_message_hash(owner);
    
            let is_valid_signature_felt = DualCaseAccount { contract_address: owner }
                .is_valid_signature(hash, signature);
    
            // Check either 'VALID' or True for backwards compatibility
            let is_valid_signature = is_valid_signature_felt == starknet::VALIDATED
                || is_valid_signature_felt == 1;
            assert(is_valid_signature, 'Invalid signature');
    
            // Transfer tokens
            self.erc20._transfer(owner, recipient, amount);
        }
    }

[← Counterfactual Deployments](/contracts-cairo/0.15.0/guides/deployment)

[Access →](/contracts-cairo/0.15.0/access)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of methods and constants found in `openzeppelin/security/`.

|     |     |
| --- | --- |
|     | Expect this module to evolve. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Initializable](#initializable)
    
*   [Pausable](#pausable)
    
*   [Reentrancy Guard](#reentrancy_guard)
    
*   [SafeMath](#safemath)
    
    *   [SafeUint256](#safeuint256)
        
    

[](#initializable)
Initializable
--------------------------------

The Initializable library provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to setup a contract’s initial state when a constructor cannot be used.

The recommended pattern with Initializable is to include a check that the Initializable state is `False` and invoke `initialize` in the target function like this:

    from openzeppelin.security.initializable.library import Initializable
    
    @external
    func foo{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        let (initialized) = Initializable.initialized()
        assert initialized = FALSE
    
        Initializable.initialize()
        return ()
    end

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used on one function. |

[](#pausable)
Pausable
----------------------

The Pausable library allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To use the Pausable library, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when not paused, insert `assert_not_paused`. For methods that should be available only when paused, insert `assert_paused`. For example:

    from openzeppelin.security.pausable.library import Pausable
    
    @external
    func whenNotPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_not_paused()
    
        # function body
        return ()
    end
    
    @external
    func whenPaused{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }():
        Pausable.assert_paused()
    
        # function body
        return ()
    end

|     |     |
| --- | --- |
|     | `pause` and `unpause` already include these assertions. In other words, `pause` cannot be invoked when already paused and vice versa. |

For a list of full implementations utilizing the Pausable library, see:

*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [`reentrancy guard`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/reentrancyguard/library.cairo)
 library exposes two methods `_start` and `_end` to protect functions against reentrancy attacks. The protected function must call `ReentrancyGuard._start` before the first function statement, and `ReentrancyGuard._end` before the return statement, as shown below:

    from openzeppelin.security.reentrancyguard.library import ReentrancyGuard
    
    func test_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
       ReentrancyGuard._start()
       # function body
       ReentrancyGuard._end()
       return ()
    end

[](#safemath)
SafeMath
----------------------

### [](#safeuint256)
SafeUint256

The SafeUint256 namespace in the [SafeMath library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/safemath/library.cairo)
 offers arithmetic for unsigned 256-bit integers (uint256) by leveraging Cairo’s Uint256 library and integrating overflow checks. Some of Cairo’s Uint256 functions do not revert upon overflows. For instance, `uint256_add` will return a bit carry when the sum exceeds 256 bits. This library includes an additional assertion ensuring values do not overflow.

Using SafeUint256 methods is rather straightforward. Simply import SafeUint256 and insert the arithmetic method like this:

    from openzeppelin.security.safemath.library import SafeUint256
    
    func add_two_uints{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        } (a: Uint256, b: Uint256) -> (c: Uint256):
        let (c: Uint256) = SafeUint256.add(a, b)
        return (c)
    end

[← ERC721](/contracts-cairo/0.3.2/erc721)

[Introspection →](/contracts-cairo/0.3.2/introspection)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `ERC20.cairo` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Interface](#interface)
    
    *   [ERC20 compatibility](#erc20_compatibility)
        
    
*   [Usage](#usage)
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC20 (basic)](#erc20_basic)
        
    *   [ERC20Mintable](#erc20mintable)
        
    *   [ERC20Pausable](#erc20pausable)
        
    *   [ERC20Upgradeable](#erc20upgradeable)
        
    
*   [API Specification](#api_specification)
    
    *   [Methods](#methods)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`decimals`](#decimals)
            
        *   [`totalSupply`](#totalsupply)
            
        *   [`balanceOf`](#balanceof)
            
        *   [`allowance`](#allowance)
            
        *   [`transfer`](#transfer)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        
    *   [Events](#events)
        
        *   [`Transfer (event)`](#transfer_event)
            
        *   [`Approval (event)`](#approval_event)
            
        
    

[](#interface)
Interface
------------------------

    @contract_interface
    namespace IERC20 {
        func name() -> (name: felt) {
        }
    
        func symbol() -> (symbol: felt) {
        }
    
        func decimals() -> (decimals: felt) {
        }
    
        func totalSupply() -> (totalSupply: Uint256) {
        }
    
        func balanceOf(account: felt) -> (balance: Uint256) {
        }
    
        func allowance(owner: felt, spender: felt) -> (remaining: Uint256) {
        }
    
        func transfer(recipient: felt, amount: Uint256) -> (success: felt) {
        }
    
        func transferFrom(sender: felt, recipient: felt, amount: Uint256) -> (success: felt) {
        }
    
        func approve(spender: felt, amount: Uint256) -> (success: felt) {
        }
    }

### [](#erc20_compatibility)
ERC20 compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard, in the following ways:

*   It uses Cairo’s `uint256` instead of `felt`.
    
*   It returns `TRUE` as success.
    
*   It accepts a `felt` argument for `decimals` in the constructor calldata with a max value of 2^8 (imitating `uint8` type).
    
*   It makes use of Cairo’s short strings to simulate `name` and `symbol`.
    

But some differences can still be found, such as:

*   `transfer`, `transferFrom` and `approve` will never return anything different from `TRUE` because they will revert on any error.
    
*   Function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo-lang/blob/7712b21fc3b1cb02321a58d0c0579f5370147a8b/src/starkware/starknet/public/abi.py#L25)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    .
    

[](#usage)
Usage
----------------

Use cases go from medium of exchange currency to voting rights, staking, and more.

Considering that the constructor method looks like this:

    func constructor(
        name: felt,               // Token name as Cairo short string
        symbol: felt,             // Token symbol as Cairo short string
        decimals: felt            // Token decimals (usually 18)
        initial_supply: Uint256,  // Amount to be minted
        recipient: felt           // Address where to send initial supply to
    ) {
    }

To create a token you need to deploy it like this:

    erc20 = await starknet.deploy(
        "openzeppelin/token/erc20/presets/ERC20.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),     # name\
            str_to_felt("TKN"),       # symbol\
            18,                       # decimals\
            (1000, 0),                # initial supply\
            account.contract_address  # recipient\
        ]
    )

As most StarkNet contracts, it expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it. For example:

    signer = MockSigner(PRIVATE_KEY)
    amount = uint(100)
    
    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    await signer.send_transaction(account, erc20.contract_address, 'transfer', [recipient_address, *amount])

[](#extensibility)
Extensibility
--------------------------------

ERC20 contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
. The basic idea behind integrating the pattern is to import the requisite ERC20 methods from the ERC20 library and incorporate the extended logic thereafter. For example, let’s say you wanted to implement a pausing mechanism. The contract should first import the ERC20 methods and the extended logic from the [Pausable library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/security/pausable/library.cairo)
 i.e. `Pausable.pause`, `Pausable.unpause`. Next, the contract should expose the methods with the extended logic therein like this:

    @external
    func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        recipient: felt, amount: Uint256
    ) -> (success: felt) {
        Pausable.assert_not_paused();                 // imported extended logic
        return ERC20.transfer(recipient, amount);     // imported library method
    }

Note that extensibility does not have to be only library-based like in the above example. For instance, an ERC20 contract with a pausing mechanism can define the pausing methods directly in the contract or even import the `pausable` methods from the library and tailor them further.

Some other ways to extend ERC20 contracts may include:

*   Implementing a minting mechanism.
    
*   Creating a timelock.
    
*   Adding roles such as owner or minter.
    

For full examples of the extensibility pattern being used in ERC20 contracts, see [Presets](#presets)
.

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset mints an initial supply which is especially necessary for presets that do not expose a `mint` method.

### [](#erc20_basic)
ERC20 (basic)

The [`ERC20`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 preset offers a quick and easy setup for deploying a basic ERC20 token.

### [](#erc20mintable)
ERC20Mintable

The [`ERC20Mintable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
 preset allows the contract owner to mint new tokens.

### [](#erc20pausable)
ERC20Pausable

The [`ERC20Pausable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
 preset allows the contract owner to pause/unpause all state-modifying methods i.e. `transfer`, `approve`, etc. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug.

### [](#erc20upgradeable)
ERC20Upgradeable

The [`ERC20Upgradeable`](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
 preset allows the contract owner to upgrade a contract by deploying a new ERC20 implementation contract while also maintaining the contract’s state. This preset proves useful for scenarios such as eliminating bugs and adding new features. For more on upgradeability, see [Contract upgrades](proxies#contract_upgrades)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#methods)
Methods

    func name() -> (name: felt) {
    }
    
    func symbol() -> (symbol: felt) {
    }
    
    func decimals() -> (decimals: felt) {
    }
    
    func totalSupply() -> (totalSupply: Uint256) {
    }
    
    func balanceOf(account: felt) -> (balance: Uint256) {
    }
    
    func allowance(owner: felt, spender: felt) -> (remaining: Uint256) {
    }
    
    func transfer(recipient: felt, amount: Uint256) -> (success: felt) {
    }
    
    func transferFrom(sender: felt, recipient: felt, amount: Uint256) -> (success: felt) {
    }
    
    func approve(spender: felt, amount: Uint256) -> (success: felt) {
    }

#### [](#name)
`name`

Returns the name of the token.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the ticker symbol of the token.

Parameters: None.

Returns:

    symbol: felt

#### [](#decimals)
`decimals`

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user representation.

Parameters: None.

Returns:

    decimals: felt

#### [](#totalsupply)
`totalSupply`

Returns the amount of tokens in existence.

Parameters: None.

Returns:

    totalSupply: Uint256

#### [](#balanceof)
`balanceOf`

Returns the amount of tokens owned by `account`.

Parameters:

    account: felt

Returns:

    balance: Uint256

#### [](#allowance)
`allowance`

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through `transferFrom`. This is zero by default.

This value changes when `approve` or `transferFrom` are called.

Parameters:

    owner: felt
    spender: felt

Returns:

    remaining: Uint256

#### [](#transfer)
`transfer`

Moves `amount` tokens from the caller’s account to `recipient`. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#transferfrom)
`transferFrom`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    sender: felt
    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#approve)
`approve`

Sets `amount` as the allowance of `spender` over the caller’s tokens. It returns `1` representing a bool if it succeeds.

Emits an [Approval](#approval_event)
 event.

Parameters:

    spender: felt
    amount: Uint256

Returns:

    success: felt

### [](#events)
Events

    func Transfer(from_: felt, to: felt, value: Uint256) {
    }
    
    func Approval(owner: felt, spender: felt, value: Uint256) {
    }

#### [](#transfer_event)
`Transfer (event)`

Emitted when `value` tokens are moved from one account (`from_`) to another (`to`).

Note that `value` may be zero.

Parameters:

    from_: felt
    to: felt
    value: Uint256

#### [](#approval_event)
`Approval (event)`

Emitted when the allowance of a `spender` for an `owner` is set by a call to [approve](#approve)
. `value` is the new allowance.

Parameters:

    owner: felt
    spender: felt
    value: Uint256

[← Access Control](/contracts-cairo/0.6.0/access)

[ERC721 →](/contracts-cairo/0.6.0/erc721)




 Wizard for Cairo - OpenZeppelin Docs       

Wizard for Cairo
================

Not sure where to start? Use the interactive generator below to bootstrap your contract and learn about the components offered in OpenZeppelin Contracts for Cairo.

|     |     |
| --- | --- |
|     | We strongly recommend checking the [Components](components)<br> section to understand how to extend from our library. |

[← Overview](/contracts-cairo/0.10.0/)

[Components →](/contracts-cairo/0.10.0/components)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `ERC20.cairo` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for StarkNet.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Interface](#interface)
    
    *   [ERC20 compatibility](#erc20_compatibility)
        
    
*   [Usage](#usage)
    
*   [Extensibility](#extensibility)
    
*   [Presets](#presets)
    
    *   [ERC20 (basic)](#erc20_basic)
        
    *   [ERC20Mintable](#erc20mintable)
        
    *   [ERC20Pausable](#erc20pausable)
        
    *   [ERC20Upgradeable](#erc20upgradeable)
        
    
*   [API Specification](#api_specification)
    
    *   [Methods](#methods)
        
        *   [`name`](#name)
            
        *   [`symbol`](#symbol)
            
        *   [`decimals`](#decimals)
            
        *   [`totalSupply`](#totalsupply)
            
        *   [`balanceOf`](#balanceof)
            
        *   [`allowance`](#allowance)
            
        *   [`transfer`](#transfer)
            
        *   [`transferFrom`](#transferfrom)
            
        *   [`approve`](#approve)
            
        
    *   [Events](#events)
        
        *   [`Transfer (event)`](#transfer_event)
            
        *   [`Approval (event)`](#approval_event)
            
        
    

[](#interface)
Interface
------------------------

    @contract_interface
    namespace IERC20:
        func name() -> (name: felt):
        end
    
        func symbol() -> (symbol: felt):
        end
    
        func decimals() -> (decimals: felt):
        end
    
        func totalSupply() -> (totalSupply: Uint256):
        end
    
        func balanceOf(account: felt) -> (balance: Uint256):
        end
    
        func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
        end
    
        func transfer(recipient: felt, amount: Uint256) -> (success: felt):
        end
    
        func transferFrom(
                sender: felt,
                recipient: felt,
                amount: Uint256
            ) -> (success: felt):
        end
    
        func approve(spender: felt, amount: Uint256) -> (success: felt):
        end
    end

### [](#erc20_compatibility)
ERC20 compatibility

Although StarkNet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard, in the following ways:

*   it uses Cairo’s `uint256` instead of `felt`
    
*   it returns `TRUE` as success
    
*   it accepts a `felt` argument for `decimals` in the constructor calldata with a max value of 2^8 (imitating `uint8` type)
    
*   it makes use of Cairo’s short strings to simulate `name` and `symbol`
    

But some differences can still be found, such as:

*   `transfer`, `transferFrom` and `approve` will never return anything different from `TRUE` because they will revert on any error
    
*   function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo-lang/blob/7712b21fc3b1cb02321a58d0c0579f5370147a8b/src/starkware/starknet/public/abi.py#L25)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    

[](#usage)
Usage
----------------

Use cases go from medium of exchange currency to voting rights, staking, and more.

Considering that the constructor method looks like this:

    func constructor(
        name: felt,               # Token name as Cairo short string
        symbol: felt,             # Token symbol as Cairo short string
        decimals: felt            # Token decimals (usually 18)
        initial_supply: Uint256,  # Amount to be minted
        recipient: felt           # Address where to send initial supply to
    ):

To create a token you need to deploy it like this:

    erc20 = await starknet.deploy(
        "openzeppelin/token/erc20/presets/ERC20.cairo",
        constructor_calldata=[\
            str_to_felt("Token"),     # name\
            str_to_felt("TKN"),       # symbol\
            18,                       # decimals\
            (1000, 0),                # initial supply\
            account.contract_address  # recipient\
        ]
    )

As most StarkNet contracts, it expects to be called by another contract and it identifies it through `get_caller_address` (analogous to Solidity’s `this.address`). This is why we need an Account contract to interact with it. For example:

    signer = MockSigner(PRIVATE_KEY)
    amount = uint(100)
    
    account = await starknet.deploy(
        "contracts/Account.cairo",
        constructor_calldata=[signer.public_key]
    )
    
    await signer.send_transaction(account, erc20.contract_address, 'transfer', [recipient_address, *amount])

[](#extensibility)
Extensibility
--------------------------------

ERC20 contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
. The basic idea behind integrating the pattern is to import the requisite ERC20 methods from the ERC20 library and incorporate the extended logic thereafter. For example, let’s say you wanted to implement a pausing mechanism. The contract should first import the ERC20 methods and the extended logic from the [Pausable library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/security/pausable/library.cairo)
 i.e. `Pausable.pause`, `Pausable.unpause`. Next, the contract should expose the methods with the extended logic therein like this:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()          # imported extended logic
        ERC20.transfer(recipient, amount)     # imported library method
        return (TRUE)
    end

Note that extensibility does not have to be only library-based like in the above example. For instance, an ERC20 contract with a pausing mechanism can define the pausing methods directly in the contract or even import the `pausable` methods from the library and tailor them further.

Some other ways to extend ERC20 contracts may include:

*   Implementing a minting mechanism
    
*   Creating a timelock
    
*   Adding roles such as owner or minter
    

For full examples of the extensibility pattern being used in ERC20 contracts, see [Presets](#presets)
.

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset mints an initial supply which is especially necessary for presets that do not expose a `mint` method.

### [](#erc20_basic)
ERC20 (basic)

The [`ERC20`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 preset offers a quick and easy setup for deploying a basic ERC20 token.

### [](#erc20mintable)
ERC20Mintable

The [`ERC20Mintable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
 preset allows the contract owner to mint new tokens.

### [](#erc20pausable)
ERC20Pausable

The [`ERC20Pausable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
 preset allows the contract owner to pause/unpause all state-modifying methods i.e. `transfer`, `approve`, etc. This preset proves useful for scenarios such as preventing trades until the end of an evaluation period and having an emergency switch for freezing all token transfers in the event of a large bug.

### [](#erc20upgradeable)
ERC20Upgradeable

The [`ERC20Upgradeable`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
 preset allows the contract owner to upgrade a contract by deploying a new ERC20 implementation contract while also maintaing the contract’s state. This preset proves useful for scenarios such as eliminating bugs and adding new features. For more on upgradeability, see [Contract upgrades](proxies#contract_upgrades)
.

[](#api_specification)
API Specification
----------------------------------------

### [](#methods)
Methods

    func name() -> (name: felt):
    end
    
    func symbol() -> (symbol: felt):
    end
    
    func decimals() -> (decimals: felt):
    end
    
    func totalSupply() -> (totalSupply: Uint256):
    end
    
    func balanceOf(account: felt) -> (balance: Uint256):
    end
    
    func allowance(owner: felt, spender: felt) -> (remaining: Uint256):
    end
    
    func transfer(recipient: felt, amount: Uint256) -> (success: felt):
    end
    
    func transferFrom(
            sender: felt,
            recipient: felt,
            amount: Uint256
        ) -> (success: felt):
    end
    
    func approve(spender: felt, amount: Uint256) -> (success: felt):
    end

#### [](#name)
`name`

Returns the name of the token.

Parameters: None.

Returns:

    name: felt

#### [](#symbol)
`symbol`

Returns the ticker symbol of the token.

Parameters: None.

Returns:

    symbol: felt

#### [](#decimals)
`decimals`

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user representation.

Parameters: None.

Returns:

    decimals: felt

#### [](#totalsupply)
`totalSupply`

Returns the amount of tokens in existence.

Parameters: None.

Returns:

    totalSupply: Uint256

#### [](#balanceof)
`balanceOf`

Returns the amount of tokens owned by `account`.

Parameters:

    account: felt

Returns:

    balance: Uint256

#### [](#allowance)
`allowance`

Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through `transferFrom`. This is zero by default.

This value changes when `approve` or `transferFrom` are called.

Parameters:

    owner: felt
    spender: felt

Returns:

    remaining: Uint256

#### [](#transfer)
`transfer`

Moves `amount` tokens from the caller’s account to `recipient`. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#transferfrom)
`transferFrom`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. It returns `1` representing a bool if it succeeds.

Emits a [Transfer](#transfer_event)
 event.

Parameters:

    sender: felt
    recipient: felt
    amount: Uint256

Returns:

    success: felt

#### [](#approve)
`approve`

Sets `amount` as the allowance of `spender` over the caller’s tokens. It returns `1` representing a bool if it succeeds.

Emits an [Approval](#approval_event)
 event.

Parameters:

    spender: felt
    amount: Uint256

Returns:

    success: felt

### [](#events)
Events

    func Transfer(from_: felt, to: felt, value: Uint256):
    end
    
    func Approval(owner: felt, spender: felt, value: Uint256):
    end

#### [](#transfer_event)
`Transfer (event)`

Emitted when `value` tokens are moved from one account (`from_`) to another (`to`).

Note that `value` may be zero.

Parameters:

    from_: felt
    to: felt
    value: Uint256

#### [](#approval_event)
`Approval (event)`

Emitted when the allowance of a `spender` for an `owner` is set by a call to [approve](#approve)
. `value` is the new allowance.

Parameters:

    owner: felt
    spender: felt
    value: Uint256

[← Access Control](/contracts-cairo/0.3.2/access)

[ERC721 →](/contracts-cairo/0.3.2/erc721)




 Presets - OpenZeppelin Docs       

Presets
=======

Presets are ready-to-deploy contracts provided by the library. Since presets are intended to be very simple and as generic as possible, there’s no support for custom or complex contracts such as `ERC20Pausable` or `ERC721Mintable`.

|     |     |
| --- | --- |
|     | For contract customization and combination of modules you can use [Wizard for Cairo](https://wizard.openzeppelin.com)<br>, our code-generation tool. |

[](#available_presets)
Available presets
----------------------------------------

List of available presets and their corresponding [Sierra class hashes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash)
.

|     |     |
| --- | --- |
|     | Class hashes were computed using [cairo 2.7.0](https://crates.io/crates/cairo-lang-compiler/2.7.0)<br>. |

 
| Name | Sierra Class Hash |
| --- | --- |
| `[AccountUpgradeable](api/account#AccountUpgradeable) ` | `0x005b8b908d16497cd347642c1ab43015b5956e2085aa4c8bb21f0b073015a1c9` |
| `[ERC20Upgradeable](api/erc20#ERC20Upgradeable) ` | `0x05ea7bb131bc998b4ce1c0da6170bc8d224c9da558f10cf8a1e2bef193c1074e` |
| `[ERC721Upgradeable](api/erc721#ERC721Upgradeable) ` | `0x022e2c5b978e1decf9d03a34e3985d340664a15a2acd6f116c684d4055e6911d` |
| `[ERC1155Upgradeable](api/erc1155#ERC1155Upgradeable) ` | `0x03f994c0b1a88825c67270b7e82e681c839e95e3bc40d4d8144771f8860166a2` |
| `[EthAccountUpgradeable](api/account#EthAccountUpgradeable) ` | `0x041534fff05642ddbb5778be304be14dd36da40a02feadb6e489f9f749f5c983` |
| `[UniversalDeployer](api/udc#UniversalDeployer) ` | `0x03edeadb23f0c66167da93651affc6acc6f3b7256ef651b2fddfd6a63288a742` |

|     |     |
| --- | --- |
|     | [starkli](https://book.starkli.rs/introduction)<br> class-hash command can be used to compute the class hash from a Sierra artifact. |

[](#usage)
Usage
----------------

These preset contracts are ready-to-deploy which means they should already be declared on the Sepolia network. Simply deploy the preset class hash and add the appropriate constructor arguments. Deploying the ERC20Upgradeable preset with [starkli](https://book.starkli.rs/introduction)
, for example, will look like this:

    starkli deploy 0x05ea7bb131bc998b4ce1c0da6170bc8d224c9da558f10cf8a1e2bef193c1074e \
      <CONSTRUCTOR_ARGS> \
      --network="sepolia"

If a class hash has yet to be declared, copy/paste the preset contract code and declare it locally. Start by [setting up a project](./#set_up_your_project)
 and [installing the Contracts for Cairo library](./#install the_library)
. Copy the target preset contract from the [presets directory](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/presets)
 and paste it in the new project’s `src/lib.cairo` like this:

    // src/lib.cairo
    
    #[starknet::contract]
    mod ERC20Upgradeable {
        use openzeppelin::access::ownable::OwnableComponent;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use openzeppelin::upgrades::UpgradeableComponent;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::{ContractAddress, ClassHash};
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
        component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
    
        // Ownable Mixin
        #[abi(embed_v0)]
        impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
        impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        // ERC20 Mixin
        #[abi(embed_v0)]
        impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        // Upgradeable
        impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage,
            #[substorage(v0)]
            upgradeable: UpgradeableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event,
            #[flat]
            ERC20Event: ERC20Component::Event,
            #[flat]
            UpgradeableEvent: UpgradeableComponent::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            fixed_supply: u256,
            recipient: ContractAddress,
            owner: ContractAddress
        ) {
            self.ownable.initializer(owner);
            self.erc20.initializer(name, symbol);
            self.erc20.mint(recipient, fixed_supply);
        }
    
        #[abi(embed_v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                self.ownable.assert_only_owner();
                self.upgradeable.upgrade(new_class_hash);
            }
        }
    }

Next, compile the contract.

    scarb build

Finally, declare the preset.

    starkli declare target/dev/my_project_ERC20Upgradeable.contract_class.json \
      --network="sepolia"

[← Components](/contracts-cairo/0.15.0/components)

[Interfaces and Dispatchers →](/contracts-cairo/0.15.0/interfaces)




 Components - OpenZeppelin Docs       

Components
==========

The following documentation provides reasoning and examples on how to use Contracts for Cairo components.

Starknet components are separate modules that contain storage, events, and implementations that can be integrated into a contract. Components themselves cannot be declared or deployed. Another way to think of components is that they are abstract modules that must be instantiated.

|     |     |
| --- | --- |
|     | For more information on the construction and design of Starknet components, see the [Starknet Shamans post](https://community.starknet.io/t/cairo-components/101136#components-1)<br> and the [Cairo book](https://book.cairo-lang.org/ch99-01-05-00-components.html)<br>. |

[](#building_a_contract)
Building a contract
--------------------------------------------

### [](#setup)
Setup

The contract should first import the component and declare it with the `component!` macro:

    #[starknet::contract]
    mod MyContract {
        // Import the component
        use openzeppelin::security::InitializableComponent;
    
        // Declare the component
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    }

The `path` argument should be the imported component itself (in this case, [InitializableComponent](security#initializable)
). The `storage` and `event` arguments are the variable names that will be set in the `Storage` struct and `Event` enum, respectively. Note that even if the component doesn’t define any events, the compiler will still create an empty event enum inside the component module.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

The `#[substorage(v0)]` attribute must be included for each component in the `Storage` trait. This allows the contract to have indirect access to the component’s storage. See [Accessing component storage](#accessing_component_storage)
 for more on this.

The `#[flat]` attribute for events in the `Event` enum, however, is not required. For component events, the first key in the event log is the component ID. Flattening the component event removes it, leaving the event ID as the first key.

### [](#implementations)
Implementations

Components come with granular implementations of different interfaces. This allows contracts to integrate only the implementations that they’ll use and avoid unnecessary bloat. Integrating an implementation looks like this:

    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        // Gives the contract access to the implementation methods
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

Defining an `impl` gives the contract access to the methods within the implementation from the component. For example, `is_initialized` is defined in the `InitializableImpl`. A function on the contract level can expose it like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    
        #[external(v0)]
        fn is_initialized(ref self: ContractState) -> bool {
            self.initializable.is_initialized()
        }
    }

While there’s nothing wrong with manually exposing methods like in the previous example, this process can be tedious for implementations with many methods. Fortunately, a contract can embed implementations which will expose all of the methods of the implementation. To embed an implementation, add the `#[abi(embed_v0)]` attribute above the `impl`:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        // This attribute exposes the methods of the `impl`
        #[abi(embed_v0)]
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

`InitializableImpl` defines the `is_initialized` method in the component. By adding the embed attribute, `is_initialized` becomes a contract entrypoint for `MyContract`.

|     |     |
| --- | --- |
|     | Embeddable implementations, when available in this library’s components, are segregated from the internal component implementation which makes it easier to safely expose. Components also separate granular implementations from [mixin](#mixins)<br> implementations. The API documentation design reflects these groupings. See [ERC20Component](api/erc20#ERC20Component)<br> as an example which includes:<br><br>*   **Embeddable Mixin Implementation**<br>    <br>*   **Embeddable Implementations**<br>    <br>*   **Internal Implementations**<br>    <br>*   **Events** |

### [](#mixins)
Mixins

Mixins are impls made of a combination of smaller, more specific impls. While separating components into granular implementations offers flexibility, integrating components with many implementations can appear crowded especially if the contract uses all of them. Mixins simplify this by allowing contracts to embed groups of implementations with a single directive.

Compare the following code blocks to see the benefit of using a mixin when creating an account contract.

#### [](#account_without_mixin)
Account without mixin

    component!(path: AccountComponent, storage: account, event: AccountEvent);
    component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
    #[abi(embed_v0)]
    impl SRC6Impl = AccountComponent::SRC6Impl<ContractState>;
    #[abi(embed_v0)]
    impl DeclarerImpl = AccountComponent::DeclarerImpl<ContractState>;
    #[abi(embed_v0)]
    impl DeployableImpl = AccountComponent::DeployableImpl<ContractState>;
    #[abi(embed_v0)]
    impl PublicKeyImpl = AccountComponent::PublicKeyImpl<ContractState>;
    #[abi(embed_v0)]
    impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl<ContractState>;
    #[abi(embed_v0)]
    impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl<ContractState>;
    impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
    #[abi(embed_v0)]
    impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;

#### [](#account_with_mixin)
Account with mixin

    component!(path: AccountComponent, storage: account, event: AccountEvent);
    component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
    #[abi(embed_v0)]
    impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
    impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;

The rest of the setup for the contract, however, does not change. This means that component dependencies must still be included in the `Storage` struct and `Event` enum. Here’s a full example of an account contract that embeds the `AccountMixinImpl`:

    #[starknet::contract]
    mod Account {
        use openzeppelin::account::AccountComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccountComponent, storage: account, event: AccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // This embeds all of the methods from the many AccountComponent implementations
        // and also includes `supports_interface` from `SRC5Impl`
        #[abi(embed_v0)]
        impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
        impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            account: AccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccountEvent: AccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: felt252) {
            self.account.initializer(public_key);
        }
    }

### [](#initializers)
Initializers

|     |     |
| --- | --- |
|     | Failing to use a component’s `initializer` can result in irreparable contract deployments. Always read the API documentation for each integrated component. |

Some components require some sort of setup upon construction. Usually, this would be a job for a constructor; however, components themselves cannot implement constructors. Components instead offer `initializer`s within their `InternalImpl` to call from the contract’s constructor. Let’s look at how a contract would integrate [OwnableComponent](api/access#OwnableComponent)
:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        // Instantiate `InternalImpl` to give the contract access to the `initializer`
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Invoke ownable's `initializer`
            self.ownable.initializer(owner);
        }
    }

### [](#dependencies)
Dependencies

Some components include dependencies of other components. Contracts that integrate components with dependencies must also include the component dependency. For instance, [AccessControlComponent](api/access#AccessControlComponent)
 depends on [SRC5Component](api/introspection#SRC5Component)
. Creating a contract with `AccessControlComponent` should look like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl AccessControlCamelImpl =
            AccessControlComponent::AccessControlCamelImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        (...)
    }

[](#customization)
Customization
--------------------------------

|     |     |
| --- | --- |
|     | Customizing implementations and accessing component storage can potentially corrupt the state, bypass security checks, and undermine the component logic. **Exercise extreme caution**. See [Security](#security)<br>. |

### [](#custom_implementations)
Custom implementations

There are instances where a contract requires different or amended behaviors from a component implementation. In these scenarios, a contract must create a custom implementation of the interface. Let’s break down a pausable ERC20 contract to see what that looks like. Here’s the setup:

    #[starknet::contract]
    mod ERC20Pausable {
        use openzeppelin::security::pausable::PausableComponent;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        // Import the ERC20 interfaces to create custom implementations
        use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly};
        use starknet::ContractAddress;
    
        component!(path: PausableComponent, storage: pausable, event: PausableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
        impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    
        // `ERC20MetadataImpl` can keep the embed directive because the implementation
        // will not change
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        // Do not add the embed directive to these implementations because
        // these will be customized
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
    
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    }

The first thing to notice is that the contract imports the interfaces of the implementations that will be customized. These will be used in the next code example.

Next, the contract includes the [ERC20Component](api/erc20#ERC20Component)
 implementations; however, `ERC20Impl` and `ERC20CamelOnlyImplt` are **not** embedded. Instead, we want to expose our custom implementation of an interface. The following example shows the pausable logic integrated into the ERC20 implementations:

    #[starknet::contract]
    mod ERC20Pausable {
        (...)
    
        // Custom ERC20 implementation
        #[external(v0)]
        impl CustomERC20Impl of IERC20<ContractState> {
            fn transfer(
                ref self: ContractState, recipient: ContractAddress, amount: u256
            ) -> bool {
                // Add the custom logic
                self.pausable.assert_not_paused();
                // Add the original implementation method from `IERC20Impl`
                self.erc20.transfer(recipient, amount)
            }
    
            fn total_supply(self: @ContractState) -> u256 {
                // This method's behavior does not change from the component
                // implementation, but this method must still be defined.
                // Simply add the original implementation method from `IERC20Impl`
                self.erc20.total_supply()
            }
    
            (...)
        }
    
        // Custom ERC20CamelOnly implementation
        #[external(v0)]
        impl CustomERC20CamelOnlyImpl of IERC20CamelOnly<ContractState> {
            fn totalSupply(self: @ContractState) -> u256 {
                self.erc20.total_supply()
            }
    
            fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {
                self.erc20.balance_of(account)
            }
    
            fn transferFrom(
                ref self: ContractState,
                sender: ContractAddress,
                recipient: ContractAddress,
                amount: u256
            ) -> bool {
                self.pausable.assert_not_paused();
                self.erc20.transfer_from(sender, recipient, amount)
            }
        }
    }

Notice that in the `CustomERC20Impl`, the `transfer` method integrates `pausable.assert_not_paused` as well as `erc20.transfer` from `PausableImpl` and `ERC20Impl` respectively. This is why the contract defined the `ERC20Impl` from the component in the previous example.

Creating a custom implementation of an interface must define **all** methods from that interface. This is true even if the behavior of a method does not change from the component implementation (as `total_supply` exemplifies in this example).

|     |     |
| --- | --- |
|     | The ERC20 documentation provides another custom implementation guide for [Customizing decimals](erc20#customizing_decimals)<br>. |

### [](#accessing_component_storage)
Accessing component storage

There may be cases where the contract must read or write to an integrated component’s storage. To do so, use the same syntax as calling an implementation method except replace the name of the method with the storage variable like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        (...)
    
        fn write_to_comp_storage(ref self: ContractState) {
            self.initializable.Initializable_initialized.write(true);
        }
    
        fn read_from_comp_storage(self: @ContractState) -> bool {
            self.initializable.Initializable_initialized.read()
        }
    }

[](#security)
Security
----------------------

The maintainers of OpenZeppelin Contracts for Cairo are mainly concerned with the correctness and security of the code as published in the library.

Customizing implementations and manipulating the component state may break some important assumptions and introduce vulnerabilities. While we try to ensure the components remain secure in the face of a wide range of potential customizations, this is done in a best-effort manner. Any and all customizations to the component logic should be carefully reviewed and checked against the source code of the component they are customizing so as to fully understand their impact and guarantee their security.

[← Wizard](/contracts-cairo/0.13.0/wizard)

[Presets →](/contracts-cairo/0.13.0/presets)




 Interfaces and Dispatchers - OpenZeppelin Docs       

Interfaces and Dispatchers
==========================

This section describes the interfaces OpenZeppelin Contracts for Cairo offer, and explains the design choices behind them.

Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example:

    use openzeppelin::token::erc20::interface::IERC20;

or

    use openzeppelin::token::erc20::dual20::DualCaseERC20;

|     |     |
| --- | --- |
|     | For simplicity, we’ll use ERC20 as example but the same concepts apply to other modules. |

[](#interface_traits)
Interface traits
--------------------------------------

The library offers three types of traits to implement or interact with contracts:

### [](#standard_traits)
Standard traits

These are associated with a predefined interface such as a standard. This includes only the functions defined in the interface, and is the standard way to interact with a compliant contract.

    #[starknet::interface]
    trait IERC20<TState> {
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#abi_traits)
ABI traits

They describe a contract’s complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes functions from different traits such as `IERC20` and `IERC20Camel`.

    #[starknet::interface]
    trait ERC20ABI<TState> {
        // IERC20
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    
        // IERC20Metadata
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
    
        // IERC20CamelOnly
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
    }

### [](#dispatcher_traits)
Dispatcher traits

This is a utility trait to interface with contracts whose interface is unknown. Read more in the [DualCase Dispatchers](#dualcase_dispatchers)
 section.

    #[derive(Copy, Drop)]
    struct DualCaseERC20 {
        contract_address: ContractAddress
    }
    
    trait DualCaseERC20Trait {
        fn name(self: @DualCaseERC20) -> ByteArray;
        fn symbol(self: @DualCaseERC20) -> ByteArray;
        fn decimals(self: @DualCaseERC20) -> u8;
        fn total_supply(self: @DualCaseERC20) -> u256;
        fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
        fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dual_interfaces)
Dual interfaces
------------------------------------

Following the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
 plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.

In short, we offer two types of interfaces and utilities to handle them:

1.  `camelCase` interfaces, which are the ones we’ve been using so far.
    
2.  `snake_case` interfaces, which are the ones we’re migrating to.
    

This means that currently most of our contracts implement _dual interfaces_. For example, the ERC20 preset contract exposes `transferFrom`, `transfer_from`, `balanceOf`, `balance_of`, etc.

|     |     |
| --- | --- |
|     | Dual interfaces are available for all external functions present in previous versions of OpenZeppelin Contracts for Cairo ([v0.6.1](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.6.1)<br> and below). |

### [](#ierc20)
`IERC20`

The default version of the ERC20 interface trait exposes `snake_case` functions:

    #[starknet::interface]
    trait IERC20<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn total_supply(self: @TState) -> u256;
        fn balance_of(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

### [](#ierc20camel)
`IERC20Camel`

On top of that, we also offer a `camelCase` version of the same interface:

    #[starknet::interface]
    trait IERC20Camel<TState> {
        fn name(self: @TState) -> ByteArray;
        fn symbol(self: @TState) -> ByteArray;
        fn decimals(self: @TState) -> u8;
        fn totalSupply(self: @TState) -> u256;
        fn balanceOf(self: @TState, account: ContractAddress) -> u256;
        fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
        fn transferFrom(
            ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
    }

[](#dualcase_dispatchers)
`DualCase` dispatchers
------------------------------------------------

|     |     |
| --- | --- |
|     | `DualCase` dispatchers won’t work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments. |

In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.

These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses. This way, an AMM wouldn’t have problems integrating tokens independently of their interface.

For example:

    let token = DualCaseERC20 { contract_address: target };
    token.transfer_from(OWNER(), RECIPIENT(), VALUE);

This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:

    fn try_selector_with_fallback(
        target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
    ) -> SyscallResult<Span<felt252>> {
        match call_contract_syscall(target, selector, args) {
            Result::Ok(ret) => Result::Ok(ret),
            Result::Err(errors) => {
                if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
                    return call_contract_syscall(target, fallback, args);
                } else {
                    Result::Err(errors)
                }
            }
        }
    }

Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the [Great Interface Migration](https://community.starknet.io/t/the-great-interface-migration/92107)
.

[← Presets](/contracts-cairo/0.13.0/presets)

[Counterfactual Deployments →](/contracts-cairo/0.13.0/guides/deployment)




 Proxies - OpenZeppelin Docs       

Proxies
=======

|     |     |
| --- | --- |
|     | Expect rapid iteration as this pattern matures and more patterns potentially emerge. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Solidity/Cairo upgrades comparison](#soliditycairo_upgrades_comparison)
    
    *   [Constructors](#constructors)
        
    *   [Storage](#storage)
        
    
*   [Proxies](#proxies2)
    
    *   [Proxy contract](#proxy_contract)
        
    *   [Implementation contract](#implementation_contract)
        
    
*   [Upgrades library API](#upgrades_library_api)
    
    *   [Methods](#methods)
        
    *   [Events](#events)
        
    
*   [Using proxies](#using_proxies)
    
    *   [Contract upgrades](#contract_upgrades)
        
    *   [Declaring contracts](#declaring_contracts)
        
    *   [Testing method calls](#testing_method_calls)
        
    
*   [Presets](#presets)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Declare an implementation [contract class](https://starknet.io/docs/hello_starknet/intro.html#declare-the-contract-on-the-starknet-testnet)
    .
    
2.  Deploy proxy contract with the implementation contract’s class hash, and the inputs describing the call to initialize the proxy from the implementation (if required). This will redirect the call as a library\_call to the implementation (similar to Solidity delegatecall).
    

In Python, this would look as follows:

    # declare implementation contract
    IMPLEMENTATION = await starknet.declare(
        "path/to/implementation.cairo",
    )
    
    # deploy proxy
    selector = get_selector_from_name('initializer')
    params = [\
        proxy_admin   # admin account\
    ]
    PROXY = await starknet.deploy(
        "path/to/proxy.cairo",
        constructor_calldata=[\
            IMPLEMENTATION.class_hash,  # set implementation contract class hash\
            selector,                   # initializer function selector\
            len(params),                # calldata length in felt\
            *params                     # actual calldata\
        ]
    )

[](#soliditycairo_upgrades_comparison)
Solidity/Cairo upgrades comparison
-------------------------------------------------------------------------

### [](#constructors)
Constructors

OpenZeppelin Contracts for Solidity requires the use of an alternative library for upgradeable contracts. Consider that in Solidity constructors are not part of the deployed contract’s runtime bytecode; rather, a constructor’s logic is executed only once when the contract instance is deployed and then discarded. This is why proxies can’t imitate the construction of its implementation, therefore requiring a different initialization mechanism.

The constructor problem in upgradeable contracts is resolved by the use of initializer methods. Initializer methods are essentially regular methods that execute the logic that would have been in the constructor. Care needs to be exercised with initializers to ensure they can only be called once. Thus, OpenZeppelin offers an [upgradeable contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
 where much of this process is abstracted away. See OpenZeppelin’s [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)
 for more info.

The Cairo programming language does not support inheritance. Instead, Cairo contracts follow the [Extensibility Pattern](extensibility)
 which already uses initializer methods to mimic constructors. Upgradeable contracts do not, therefore, require a separate library with refactored constructor logic.

### [](#storage)
Storage

OpenZeppelin’s alternative Upgrades library also implements [unstructured storage](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies)
 for its upgradeable contracts. The basic idea behind unstructured storage is to pseudo-randomize the storage structure of the upgradeable contract so it’s based on variable names instead of declaration order, which makes the chances of storage collision during an upgrade extremely unlikely.

The StarkNet compiler, meanwhile, already creates pseudo-random storage addresses by hashing the storage variable names (and keys in mappings) by default. In other words, StarkNet already uses unstructured storage and does not need a second library to modify how storage is set. See StarkNet’s [Contracts Storage documentation](https://starknet.io/documentation/contracts/#contracts_storage)
 for more information.

[](#proxies2)
Proxies
---------------------

A proxy contract is a contract that delegates function calls to another contract. This type of pattern decouples state and logic. Proxy contracts store the state and redirect function calls to an implementation contract that handles the logic. This allows for different patterns such as upgrades, where implementation contracts can change but the proxy contract (and thus the state) does not; as well as deploying multiple proxy instances pointing to the same implementation. This can be useful to deploy many contracts with identical logic but unique initialization data.

In the case of contract upgrades, it is achieved by simply changing the proxy’s reference to the class hash of the declared implementation. This allows developers to add features, update logic, and fix bugs without touching the state or the contract address to interact with the application.

### [](#proxy_contract)
Proxy contract

The [Proxy contract](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/upgrades/presets/Proxy.cairo)
 includes two core methods:

1.  The `__default__` method is a fallback method that redirects a function call and associated calldata to the implementation contract.
    
2.  The `__l1_default__` method is also a fallback method; however, it redirects the function call and associated calldata to a layer one contract. In order to invoke `__l1_default__`, the original function call must include the library function `send_message_to_l1`. See Cairo’s [Interacting with L1 contracts](https://www.cairo-lang.org/docs/hello_starknet/l1l2.html)
     for more information.
    

Since this proxy is designed to work both as an [UUPS-flavored upgrade proxy](https://eips.ethereum.org/EIPS/eip-1822)
 as well as a non-upgradeable proxy, it does not know how to handle its own state. Therefore it requires the implementation contract class to be declared beforehand, so its class hash can be passed to the Proxy on construction time.

When interacting with the contract, function calls should be sent by the user to the proxy. The proxy’s fallback function redirects the function call to the implementation contract to execute.

### [](#implementation_contract)
Implementation contract

The implementation contract, also known as the logic contract, receives the redirected function calls from the proxy contract. The implementation contract should follow the [Extensibility pattern](extensibility#the_pattern)
 and import directly from the [Proxy library](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/upgrades/library.cairo)
.

The implementation contract should:

*   Import `Proxy` namespace.
    
*   Provide an external initializer function (calling `Proxy.initializer`) to intialize the proxy immediately after deployment.
    

If the implementation is upgradeable, it should:

*   Include a method to upgrade the implementation (i.e. `upgrade`).
    
*   Use access control to protect the contract’s upgradeability.
    

The implementation contract should NOT:

*   Be deployed like a regular contract. Instead, the implementation contract should be declared (which creates a `DeclaredClass` containing its hash and abi).
    
*   Set its initial state with a traditional constructor (decorated with `@constructor`). Instead, use an initializer method that invokes the Proxy `constructor`.
    

|     |     |
| --- | --- |
|     | The Proxy `constructor` includes a check that ensures the initializer can only be called once; however, `_set_implementation` does not include this check. It’s up to the developers to protect their implementation contract’s upgradeability with access controls such as [`assert_only_admin`](#assert_only_admin)<br>. |

For a full implementation contract example, please see:

*   [Proxiable implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ProxiableImplementation.cairo)
    

[](#upgrades_library_api)
Upgrades library API
----------------------------------------------

### [](#methods)
Methods

    func initializer(proxy_admin: felt) {
    }
    
    func assert_only_admin() {
    }
    
    func get_implementation_hash() -> (implementation: felt) {
    }
    
    func get_admin() -> (admin: felt) {
    }
    
    func _set_admin(new_admin: felt) {
    }
    
    func _set_implementation_hash(new_implementation: felt) {
    }

#### [](#initializer)
`initializer`

Initializes the proxy contract with an initial implementation.

Parameters:

    proxy_admin: felt

Returns: None.

#### [](#assert_only_admin)
`assert_only_admin`

Reverts if called by any account other than the admin.

Parameters: None.

Returns: None.

#### [](#get_implementation)
`get_implementation`

Returns the current implementation hash.

Parameters: None.

Returns:

    implementation: felt

#### [](#get_admin)
`get_admin`

Returns the current admin.

Parameters: None.

Returns:

    admin: felt

#### [](#set_admin)
`_set_admin`

Sets `new_admin` as the admin of the proxy contract.

Parameters:

    new_admin: felt

Returns: None.

#### [](#set_implementation_hash)
`_set_implementation_hash`

Sets `new_implementation` as the implementation’s contract class. This method is included in the proxy contract’s constructor and can be used to upgrade contracts.

Parameters:

    new_implementation: felt

Returns: None.

### [](#events)
Events

    func Upgraded(implementation: felt) {
    }
    
    func AdminChanged(previousAdmin: felt, newAdmin: felt) {
    }

#### [](#upgraded)
`Upgraded`

Emitted when a proxy contract sets a new implementation class hash.

Parameters:

    implementation: felt

#### [](#adminchanged)
`AdminChanged`

Emitted when the `admin` changes from `previousAdmin` to `newAdmin`.

Parameters:

    previousAdmin: felt
    newAdmin: felt

[](#using_proxies)
Using proxies
--------------------------------

### [](#contract_upgrades)
Contract upgrades

To upgrade a contract, the implementation contract should include an `upgrade` method that, when called, changes the reference to a new deployed contract like this:

    # declare first implementation
    IMPLEMENTATION = await starknet.declare(
        "path/to/implementation.cairo",
    )
    
    # deploy proxy
    PROXY = await starknet.deploy(
        "path/to/proxy.cairo",
        constructor_calldata=[\
            IMPLEMENTATION.class_hash,  # set implementation hash\
            0,                          # selector set to 0 ignores initialization\
            0,                          # calldata length in felt\
            *[]                         # empty calldata\
        ]
    )
    
    # declare implementation v2
    IMPLEMENTATION_V2 = await starknet.declare(
        "path/to/implementation_v2.cairo",
    )
    
    # call upgrade with the new implementation contract class hash
    await signer.send_transaction(
        account, PROXY.contract_address, 'upgrade', [\
            IMPLEMENTATION_V2.class_hash\
        ]
    )

For a full deployment and upgrade implementation, please see:

*   [Upgrades V1](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/tests/mocks/UpgradesMockV1.cairo)
    
*   [Upgrades V2](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/tests/mocks/UpgradesMockV2.cairo)
    

### [](#declaring_contracts)
Declaring contracts

StarkNet contracts come in two forms: contract classes and contract instances. Contract classes represent the uninstantiated, stateless code; whereas, contract instances are instantiated and include the state. Since the Proxy contract references the implementation contract by its class hash, declaring an implementation contract proves sufficient (as opposed to a full deployment). For more information on declaring classes, see [StarkNet’s documentation](https://starknet.io/docs/hello_starknet/intro.html#declare-contract)
.

### [](#testing_method_calls)
Testing method calls

As with most StarkNet contracts, interacting with a proxy contract requires an [account abstraction](accounts#quickstart)
. Due to limitations in the StarkNet testing framework, however, `@view` methods also require an account abstraction. This is only a requirement when testing. The differences in getter methods written in Python, for example, are as follows:

    # standard ERC20 call
    result = await erc20.totalSupply().call()
    
    # upgradeable ERC20 call
    result = await signer.send_transaction(
        account, PROXY.contract_address, 'totalSupply', []
    )

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets include:

*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   More to come! Have an idea? [Open an issue](https://github.com/OpenZeppelin/cairo-contracts/issues/new/choose)
    !
    

[← Extensibility](/contracts-cairo/0.6.0/extensibility)

[Accounts →](/contracts-cairo/0.6.0/accounts)




 Presets - OpenZeppelin Docs       

Presets
=======

Presets are ready-to-deploy contracts provided by the library. Since presets are intended to be very simple and as generic as possible, there’s no support for custom or complex contracts such as `ERC20Pausable` or `ERC721Mintable`.

|     |     |
| --- | --- |
|     | For contract customization and combination of modules you can use [Wizard for Cairo](https://wizard.openzeppelin.com)<br>, our code-generation tool. |

[](#available_presets)
Available presets
----------------------------------------

List of available presets and their corresponding [Sierra class hashes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash)
.

|     |     |
| --- | --- |
|     | Class hashes were computed using [cairo 2.6.3](https://crates.io/crates/cairo-lang-compiler/2.6.3)<br>. |

 
| Name | Sierra Class Hash |
| --- | --- |
| `[AccountUpgradeable](api/account#AccountUpgradeable) ` | `0x00e2eb8f5672af4e6a4e8a8f1b44989685e668489b0a25437733756c5a34a1d6` |
| `[ERC20Upgradeable](api/erc20#ERC20Upgradeable) ` | `0x040b9e69e14ddc34a98ec8133c80807c144b818bc6cbf5a119d8f62535258142` |
| `[ERC721Upgradeable](api/erc721#ERC721Upgradeable) ` | `0x00f56255bf8db96498c71884407f3b623f20a5d507cbb7c41deeeb65a1bf8725` |
| `[ERC1155Upgradeable](api/erc1155#ERC1155Upgradeable) ` | `0x017baa69866decbb1ac5e6d5ef2e69b7d5dd7113111a8cc51a48f01854df571f` |
| `[EthAccountUpgradeable](api/account#EthAccountUpgradeable) ` | `0x0169e64bc8a60422da86e6cc821c498d2f8cba60888399ce4be86690aaa51e4a` |
| `[UniversalDeployer](api/udc#UniversalDeployer) ` | `0x0536e18e3e9820b48e0477e83e0a4d6d923ccddc06deb61585dfd7402dd40733` |

|     |     |
| --- | --- |
|     | [starkli](https://book.starkli.rs/introduction)<br> class-hash command can be used to compute the class hash from a Sierra artifact. |

[](#usage)
Usage
----------------

These preset contracts are ready-to-deploy which means they should already be declared on the Sepolia network. Simply deploy the preset class hash and add the appropriate constructor arguments. Deploying the ERC20Upgradeable preset with [starkli](https://book.starkli.rs/introduction)
, for example, will look like this:

    starkli deploy 0x040b9e69e14ddc34a98ec8133c80807c144b818bc6cbf5a119d8f62535258142 \
      <CONSTRUCTOR_ARGS> \
      --network="sepolia"

If a class hash has yet to be declared, copy/paste the preset contract code and declare it locally. Start by [setting up a project](./#set_up_your_project)
 and [installing the Contracts for Cairo library](./#install the_library)
. Copy the target preset contract from the [presets directory](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/presets)
 and paste it in the new project’s `src/lib.cairo` like this:

    // src/lib.cairo
    
    #[starknet::contract]
    mod ERC20Upgradeable {
        use openzeppelin::access::ownable::OwnableComponent;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        use openzeppelin::upgrades::UpgradeableComponent;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::{ContractAddress, ClassHash};
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
        component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
    
        // Ownable Mixin
        #[abi(embed_v0)]
        impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
        impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        // ERC20 Mixin
        #[abi(embed_v0)]
        impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        // Upgradeable
        impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage,
            #[substorage(v0)]
            erc20: ERC20Component::Storage,
            #[substorage(v0)]
            upgradeable: UpgradeableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event,
            #[flat]
            ERC20Event: ERC20Component::Event,
            #[flat]
            UpgradeableEvent: UpgradeableComponent::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            name: ByteArray,
            symbol: ByteArray,
            fixed_supply: u256,
            recipient: ContractAddress,
            owner: ContractAddress
        ) {
            self.ownable.initializer(owner);
            self.erc20.initializer(name, symbol);
            self.erc20._mint(recipient, fixed_supply);
        }
    
        #[abi(embed_v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                self.ownable.assert_only_owner();
                self.upgradeable._upgrade(new_class_hash);
            }
        }
    }

Next, compile the contract.

    scarb build

Finally, declare the preset.

    starkli declare target/dev/my_project_ERC20Upgradeable.contract_class.json \
      --network="sepolia"

[← Components](/contracts-cairo/0.13.0/components)

[Interfaces and Dispatchers →](/contracts-cairo/0.13.0/interfaces)




 Wizard for Cairo - OpenZeppelin Docs       

Wizard for Cairo
================

Not sure where to start? Use the interactive generator below to bootstrap your contract and learn about the components offered in OpenZeppelin Contracts for Cairo.

|     |     |
| --- | --- |
|     | We strongly recommend checking the [Components](components)<br> section to understand how to extend from our library. |

[← Overview](/contracts-cairo/0.15.0/)

[Components →](/contracts-cairo/0.15.0/components)




 Components - OpenZeppelin Docs       

Components
==========

The following documentation provides reasoning and examples on how to use Contracts for Cairo components.

Starknet components are separate modules that contain storage, events, and implementations that can be integrated into a contract. Components themselves cannot be declared or deployed. Another way to think of components is that they are abstract modules that must be instantiated.

|     |     |
| --- | --- |
|     | For more information on the construction and design of Starknet components, see the [Starknet Shamans post](https://community.starknet.io/t/cairo-components/101136#components-1)<br> and the [Cairo book](https://book.cairo-lang.org/ch99-01-05-00-components.html)<br>. |

[](#building_a_contract)
Building a contract
--------------------------------------------

### [](#setup)
Setup

The contract should first import the component and declare it with the `component!` macro:

    #[starknet::contract]
    mod MyContract {
        // Import the component
        use openzeppelin::security::InitializableComponent;
    
        // Declare the component
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    }

The `path` argument should be the imported component itself (in this case, [InitializableComponent](security#initializable)
). The `storage` and `event` arguments are the variable names that will be set in the `Storage` struct and `Event` enum, respectively. Note that even if the component doesn’t define any events, the compiler will still create an empty event enum inside the component module.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

The `#[substorage(v0)]` attribute must be included for each component in the `Storage` trait. This allows the contract to have indirect access to the component’s storage. See [Accessing component storage](#accessing_component_storage)
 for more on this.

The `#[flat]` attribute for events in the `Event` enum, however, is not required. For component events, the first key in the event log is the component ID. Flattening the component event removes it, leaving the event ID as the first key.

### [](#implementations)
Implementations

Components come with granular implementations of different interfaces. This allows contracts to integrate only the implementations that they’ll use and avoid unnecessary bloat. Integrating an implementation looks like this:

    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        // Gives the contract access to the implementation methods
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

Defining an `impl` gives the contract access to the methods within the implementation from the component. For example, `is_initialized` is defined in the `InitializableImpl`. A function on the contract level can expose it like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        (...)
    
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    
        #[external(v0)]
        fn is_initialized(ref self: ContractState) -> bool {
            self.initializable.is_initialized()
        }
    }

While there’s nothing wrong with manually exposing methods like in the previous example, this process can be tedious for implementations with many methods. Fortunately, a contract can embed implementations which will expose all of the methods of the implementation. To embed an implementation, add the `#[abi(embed_v0)]` attribute above the `impl`:

    #[starknet::contract]
    mod MyContract {
        (...)
    
        // This attribute exposes the methods of the `impl`
        #[abi(embed_v0)]
        impl InitializableImpl =
            InitializableComponent::InitializableImpl<ContractState>;
    }

`InitializableImpl` defines the `is_initialized` method in the component. By adding the embed attribute, `is_initialized` becomes a contract entrypoint for `MyContract`.

|     |     |
| --- | --- |
|     | Embeddable implementations, when available in this library’s components, are segregated from the internal component implementation which makes it easier to safely expose. Components also separate granular implementations from [mixin](#mixins)<br> implementations. The API documentation design reflects these groupings. See [ERC20Component](api/erc20#ERC20Component)<br> as an example which includes:<br><br>*   **Embeddable Mixin Implementation**<br>    <br>*   **Embeddable Implementations**<br>    <br>*   **Internal Implementations**<br>    <br>*   **Events** |

### [](#mixins)
Mixins

Mixins are impls made of a combination of smaller, more specific impls. While separating components into granular implementations offers flexibility, integrating components with many implementations can appear crowded especially if the contract uses all of them. Mixins simplify this by allowing contracts to embed groups of implementations with a single directive.

Compare the following code blocks to see the benefit of using a mixin when creating an account contract.

#### [](#account_without_mixin)
Account without mixin

    component!(path: AccountComponent, storage: account, event: AccountEvent);
    component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
    #[abi(embed_v0)]
    impl SRC6Impl = AccountComponent::SRC6Impl<ContractState>;
    #[abi(embed_v0)]
    impl DeclarerImpl = AccountComponent::DeclarerImpl<ContractState>;
    #[abi(embed_v0)]
    impl DeployableImpl = AccountComponent::DeployableImpl<ContractState>;
    #[abi(embed_v0)]
    impl PublicKeyImpl = AccountComponent::PublicKeyImpl<ContractState>;
    #[abi(embed_v0)]
    impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl<ContractState>;
    #[abi(embed_v0)]
    impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl<ContractState>;
    impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
    #[abi(embed_v0)]
    impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;

#### [](#account_with_mixin)
Account with mixin

    component!(path: AccountComponent, storage: account, event: AccountEvent);
    component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
    #[abi(embed_v0)]
    impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
    impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;

The rest of the setup for the contract, however, does not change. This means that component dependencies must still be included in the `Storage` struct and `Event` enum. Here’s a full example of an account contract that embeds the `AccountMixinImpl`:

    #[starknet::contract]
    mod Account {
        use openzeppelin::account::AccountComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccountComponent, storage: account, event: AccountEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // This embeds all of the methods from the many AccountComponent implementations
        // and also includes `supports_interface` from `SRC5Impl`
        #[abi(embed_v0)]
        impl AccountMixinImpl = AccountComponent::AccountMixinImpl<ContractState>;
        impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            account: AccountComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccountEvent: AccountComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, public_key: felt252) {
            self.account.initializer(public_key);
        }
    }

### [](#initializers)
Initializers

|     |     |
| --- | --- |
|     | Failing to use a component’s `initializer` can result in irreparable contract deployments. Always read the API documentation for each integrated component. |

Some components require some sort of setup upon construction. Usually, this would be a job for a constructor; however, components themselves cannot implement constructors. Components instead offer `initializer`s within their `InternalImpl` to call from the contract’s constructor. Let’s look at how a contract would integrate [OwnableComponent](api/access#OwnableComponent)
:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    
        // Instantiate `InternalImpl` to give the contract access to the `initializer`
        impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            // Invoke ownable's `initializer`
            self.ownable.initializer(owner);
        }
    }

### [](#dependencies)
Dependencies

Some components include dependencies of other components. Contracts that integrate components with dependencies must also include the component dependency. For instance, [AccessControlComponent](api/access#AccessControlComponent)
 depends on [SRC5Component](api/introspection#SRC5Component)
. Creating a contract with `AccessControlComponent` should look like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::access::accesscontrol::AccessControlComponent;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // AccessControl
        #[abi(embed_v0)]
        impl AccessControlImpl =
            AccessControlComponent::AccessControlImpl<ContractState>;
        #[abi(embed_v0)]
        impl AccessControlCamelImpl =
            AccessControlComponent::AccessControlCamelImpl<ContractState>;
        impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            accesscontrol: AccessControlComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            AccessControlEvent: AccessControlComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        (...)
    }

[](#customization)
Customization
--------------------------------

|     |     |
| --- | --- |
|     | Customizing implementations and accessing component storage can potentially corrupt the state, bypass security checks, and undermine the component logic. **Exercise extreme caution**. See [Security](#security)<br>. |

### [](#custom_implementations)
Custom implementations

There are instances where a contract requires different or amended behaviors from a component implementation. In these scenarios, a contract must create a custom implementation of the interface. Let’s break down a pausable ERC20 contract to see what that looks like. Here’s the setup:

    #[starknet::contract]
    mod ERC20Pausable {
        use openzeppelin::security::pausable::PausableComponent;
        use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
        // Import the ERC20 interfaces to create custom implementations
        use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly};
        use starknet::ContractAddress;
    
        component!(path: PausableComponent, storage: pausable, event: PausableEvent);
        component!(path: ERC20Component, storage: erc20, event: ERC20Event);
    
        #[abi(embed_v0)]
        impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
        impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    
        // `ERC20MetadataImpl` can keep the embed directive because the implementation
        // will not change
        #[abi(embed_v0)]
        impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
        // Do not add the embed directive to these implementations because
        // these will be customized
        impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
        impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
    
        impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
    
        (...)
    }

The first thing to notice is that the contract imports the interfaces of the implementations that will be customized. These will be used in the next code example.

Next, the contract includes the [ERC20Component](api/erc20#ERC20Component)
 implementations; however, `ERC20Impl` and `ERC20CamelOnlyImplt` are **not** embedded. Instead, we want to expose our custom implementation of an interface. The following example shows the pausable logic integrated into the ERC20 implementations:

    #[starknet::contract]
    mod ERC20Pausable {
        (...)
    
        // Custom ERC20 implementation
        #[abi(embed_v0)]
        impl CustomERC20Impl of IERC20<ContractState> {
            fn transfer(
                ref self: ContractState, recipient: ContractAddress, amount: u256
            ) -> bool {
                // Add the custom logic
                self.pausable.assert_not_paused();
                // Add the original implementation method from `IERC20Impl`
                self.erc20.transfer(recipient, amount)
            }
    
            fn total_supply(self: @ContractState) -> u256 {
                // This method's behavior does not change from the component
                // implementation, but this method must still be defined.
                // Simply add the original implementation method from `IERC20Impl`
                self.erc20.total_supply()
            }
    
            (...)
        }
    
        // Custom ERC20CamelOnly implementation
        #[abi(embed_v0)]
        impl CustomERC20CamelOnlyImpl of IERC20CamelOnly<ContractState> {
            fn totalSupply(self: @ContractState) -> u256 {
                self.erc20.total_supply()
            }
    
            fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 {
                self.erc20.balance_of(account)
            }
    
            fn transferFrom(
                ref self: ContractState,
                sender: ContractAddress,
                recipient: ContractAddress,
                amount: u256
            ) -> bool {
                self.pausable.assert_not_paused();
                self.erc20.transfer_from(sender, recipient, amount)
            }
        }
    }

Notice that in the `CustomERC20Impl`, the `transfer` method integrates `pausable.assert_not_paused` as well as `erc20.transfer` from `PausableImpl` and `ERC20Impl` respectively. This is why the contract defined the `ERC20Impl` from the component in the previous example.

Creating a custom implementation of an interface must define **all** methods from that interface. This is true even if the behavior of a method does not change from the component implementation (as `total_supply` exemplifies in this example).

|     |     |
| --- | --- |
|     | The ERC20 documentation provides another custom implementation guide for [Customizing decimals](erc20#customizing_decimals)<br>. |

### [](#accessing_component_storage)
Accessing component storage

There may be cases where the contract must read or write to an integrated component’s storage. To do so, use the same syntax as calling an implementation method except replace the name of the method with the storage variable like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        (...)
    
        fn write_to_comp_storage(ref self: ContractState) {
            self.initializable.Initializable_initialized.write(true);
        }
    
        fn read_from_comp_storage(self: @ContractState) -> bool {
            self.initializable.Initializable_initialized.read()
        }
    }

[](#security)
Security
----------------------

The maintainers of OpenZeppelin Contracts for Cairo are mainly concerned with the correctness and security of the code as published in the library.

Customizing implementations and manipulating the component state may break some important assumptions and introduce vulnerabilities. While we try to ensure the components remain secure in the face of a wide range of potential customizations, this is done in a best-effort manner. Any and all customizations to the component logic should be carefully reviewed and checked against the source code of the component they are customizing so as to fully understand their impact and guarantee their security.

[← Wizard](/contracts-cairo/0.15.0/wizard)

[Presets →](/contracts-cairo/0.15.0/presets)




 Access - OpenZeppelin Docs       

Access
======

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

Access control—​that is, "who is allowed to do this thing"--is incredibly important in the world of smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things. It is therefore critical to understand how you implement it, lest someone else [steals your whole system](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Ownable](#ownable)
    
    *   [Quickstart](#quickstart)
        
    *   [Ownable library API](#ownable_library_api)
        
    *   [Ownable events](#ownable_events)
        
    
*   [AccessControl](#accesscontrol)
    
    *   [Usage](#usage)
        
    *   [Granting and revoking roles](#granting_and_revoking_roles)
        
    *   [Creating role identifiers](#creating_role_identifiers)
        
    *   [AccessControl library API](#accesscontrol_library_api)
        
    *   [AccessControl events](#accesscontrol_events)
        
    

[](#ownable)
Ownable
--------------------

The most common and basic form of access control is the concept of ownership: there’s an account that is the `owner` of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 for implementing ownership in your contracts.

### [](#quickstart)
Quickstart

Integrating [Ownable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/access/ownable/library.cairo)
 into a contract first requires assigning an owner. The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s [initializer](#initializer)
 like this:

    from openzeppelin.access.ownable.library import Ownable
    
    @constructor
    func constructor{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(owner: felt):
        Ownable.initializer(owner)
        return ()
    end

To restrict a function’s access to the owner only, add in the `assert_only_owner` method:

    from openzeppelin.access.ownable.library import Ownable
    
    func protected_function{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }():
        Ownable.assert_only_owner()
        return ()
    end

### [](#ownable_library_api)
Ownable library API

    func initializer(owner: felt):
    end
    
    func assert_only_owner():
    end
    
    func owner() -> (owner: felt):
    end
    
    func transfer_ownership(new_owner: felt):
    end
    
    func renounce_ownership():
    end
    
    func _transfer_ownership(new_owner: felt):
    end

#### [](#initializer)
`initializer`

Initializes Ownable access control and should be called in the implementing contract’s constructor. Assigns `owner` as the initial owner address of the contract.

This must be called only once.

Parameters:

    owner: felt

Returns: None.

#### [](#assert_only_owner)
`assert_only_owner`

Reverts if called by any account other than the owner. In case of renounced ownership, any call from the default zero address will also be reverted.

Parameters: None.

Returns: None.

#### [](#owner)
`owner`

Returns the address of the current owner.

Parameters: None.

Returns:

    owner: felt

#### [](#transfer_ownership)
`transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

#### [](#renounce_ownership)
`renounce_ownership`

Leaves the contract without owner. It will not be possible to call functions with `assert_only_owner` anymore. Can only be called by the current owner.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters: None.

Returns: None.

#### [](#transfer-ownership-internal)
`_transfer_ownership`

Transfers ownership of the contract to a new account (`new_owner`). [`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [`OwnershipTransferred`](#ownershiptransferred)
 event.

Parameters:

    new_owner: felt

Returns: None.

### [](#ownable_events)
Ownable events

    func OwnershipTransferred(previousOwner: felt, newOwner: felt):
    end

#### [](#ownershiptransferred)
OwnershipTransferred

Emitted when ownership of a contract is transferred from `previousOwner` to `newOwner`.

Parameters:

    previousOwner: felt
    newOwner: felt

[](#accesscontrol)
AccessControl
--------------------------------

While the simplicity of ownership can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
 offers flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using [assert\_only\_owner](#assert_only_owner)
. This check can be enforced through [assert\_only\_role](#assert_only_role)
. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.

### [](#usage)
Usage

For each role that you want to define, you will create a new _role identifier_ that is used to grant, revoke, and check if an account has that role (see [Creating role identifiers](#creating_role_identifiers)
 for information on creating identifiers).

Here’s a simple example of implementing `AccessControl` on a portion of an [ERC20 token contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
 which defines and sets the 'minter' role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end

|     |     |
| --- | --- |
|     | Make sure you fully understand how [AccessControl](#accesscontrol)<br> works before using it on your system, or copy-pasting the examples from this guide. |

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with [Ownable](#ownable)
. Indeed, where `AccessControl` shines is in scenarios where granular permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens, and by using `assert_only_role`:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            minter: felt,
            burner: felt
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
        AccessControl._grant_role(MINTER_ROLE, minter)
        AccessControl._grant_role(BURNER_ROLE, burner)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

So clean! By splitting concerns this way, more granular levels of permission may be implemented than were possible with the simpler ownership approach to access control. Limiting what each component of a system is able to do is known as the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
, and is a good security practice. Note that each account may still have more than one role, if so desired.

### [](#granting_and_revoking_roles)
Granting and revoking roles

The ERC20 token example above uses `_grant_role`, an [`internal`](extensibility#the_pattern)
 function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `assert_only_role` check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the `grant_role` and `revoke_role` functions. A role can be granted or revoked by using these if the calling account has the corresponding admin role. Multiple roles may have the same admin role to make management easier. A role’s admin can even be the same role itself, which would cause accounts with that role to be able to also grant and revoke it.

This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_set_role_admin` is used to select a new admin role.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

    from openzeppelin.token.erc20.library import ERC20
    
    from openzeppelin.access.accesscontrol.library import AccessControl
    
    from openzeppelin.utils.constants import DEFAULT_ADMIN_ROLE
    
    
    const MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    const BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    @constructor
    func constructor{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(
            name: felt,
            symbol: felt,
            decimals: felt,
            admin: felt,
        ):
        ERC20.initializer(name, symbol, decimals)
        AccessControl.initializer()
    
        AccessControl._grant_role(DEFAULT_ADMIN_ROLE, admin)
        return ()
    end
    
    @external
    func mint{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(to: felt, amount: Uint256):
        AccessControl.assert_only_role(MINTER_ROLE)
        ERC20._mint(to, amount)
        return ()
    end
    
    @external
    func burn{
            syscall_ptr: felt*,
            pedersen_ptr: HashBuiltin*,
            range_check_ptr
        }(from_: felt, amount: Uint256):
        AccessControl.assert_only_role(BURNER_ROLE)
        ERC20._burn(from_, amount)
        return ()
    end

Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and that role was granted to the 'admin', that same account can call `grant_role` to give minting or burning permission, and `revoke_role` to remove it.

Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as [KYC](https://en.wikipedia.org/wiki/Know_your_customer)
, where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.

The following example uses the [AccessControl mock contract](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/AccessControl.cairo)
 which exposes the role management functions. To grant and revoke roles in Python, for example:

    MINTER_ROLE = 0x4f96f87f6963bb246f2c30526628466840c642dc5c50d5a67777c6cc0e44ab5
    BURNER_ROLE = 0x7823a2d975ffa03bed39c38809ec681dc0ae931ebe0048c321d4a8440aed509
    
    # grants MINTER_ROLE and BURNER_ROLE to account1 and account2 respectively
    await signer.send_transactions(
        admin, [\
            (accesscontrol.contract_address, 'grantRole', [MINTER_ROLE, account1.contract_address]),\
            (accesscontrol.contract_address, 'grantRole', [BURNER_ROLE, account2.contract_address])\
        ]
    )
    
    # revokes MINTER_ROLE from account1
    await signer.send_transaction(
        admin,
        accesscontrol.contract_address,
        'revokeRole',
        [MINTER_ROLE, account1.contract_address]
    )

### [](#creating_role_identifiers)
Creating role identifiers

In the Solidity implementation of AccessControl, contracts generally refer to the [keccak256 hash](https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=keccak256#mathematical-and-cryptographic-functions)
 of a role as the role identifier. For example:

    bytes32 public constant SOME_ROLE = keccak256("SOME_ROLE")

These identifiers take up 32 bytes (256 bits).

Cairo field elements store a maximum of 252 bits. Even further, a declared _constant_ field element in a StarkNet contract stores even less (see [cairo\_constants](https://github.com/starkware-libs/cairo-lang/blob/167b28bcd940fd25ea3816204fa882a0b0a49603/src/starkware/cairo/lang/cairo_constants.py#L1)
). With this discrepancy, this library maintains an agnostic stance on how contracts should create identifiers. Some ideas to consider:

*   using the first or last 251 bits of keccak256 hash digests
    
*   using Cairo’s [hash2](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash.cairo)
    

### [](#accesscontrol_library_api)
AccessControl library API

    func initializer():
    end
    
    func assert_only_role(role: felt):
    end
    
    func has_role(role: felt, user: felt) -> (has_role: felt):
    end
    
    func get_role_admin(role: felt) -> (admin: felt):
    end
    
    func grant_role(role: felt, user: felt):
    end
    
    func revoke_role(role: felt, user: felt):
    end
    
    func renounce_role(role: felt, user: felt):
    end
    
    func _grant_role(role: felt, user: felt):
    end
    
    func _revoke_role(role: felt, user: felt):
    end
    
    func _set_role_admin(role: felt, admin_role: felt):
    end

#### [](#initializer-accesscontrol)
`initializer`

Initializes AccessControl and should be called in the implementing contract’s constructor.

This must only be called once.

Parameters: None.

Returns: None.

#### [](#assert_only_role)
`assert_only_role`

Checks that an account has a specific role. Reverts with a message including the required role.

Parameters:

    role: felt

Returns: None.

#### [](#has_role)
has\_role

Returns `TRUE` if `user` has been granted `role`, `FALSE` otherwise.

Parameters:

    role: felt
    user: felt

Returns:

    has_role: felt

#### [](#get_role_admin)
`get_role_admin`

Returns the admin role that controls `role`. See [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
.

To change a role’s admin, use [`_set_role_admin`](#set_role_admin)
.

Parameters:

    role: felt

Returns:

    admin: felt

#### [](#grant_role)
`grant_role`

Grants `role` to `user`.

If `user` had not been already granted `role`, emits a [RoleGranted](#rolegranted)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revoke_role)
`revoke_role`

Revokes `role` from `user`.

If `user` had been granted `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must have `role`'s admin role.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#renounce_role)
`renounce_role`

Revokes `role` from the calling `user`.

Roles are often managed via [grant\_role](#grant_role)
 and [revoke\_role](#revoke_role)
: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).

If the calling `user` had been revoked `role`, emits a [RoleRevoked](#rolerevoked)
 event.

Requirements:

*   the caller must be `user`.
    

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#grantrole-internal)
`_grant_role`

Grants `role` to `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleGranted](#rolegranted)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#revokerole-internal)
`_revoke_role`

Revokes `role` from `user`.

[`internal`](extensibility#the_pattern)
 function without access restriction.

Emits a [RoleRevoked](#rolerevoked)
 event.

Parameters:

    role: felt
    user: felt

Returns: None.

#### [](#setroleadmin)
`_set_role_admin`

[`internal`](extensibility#the_pattern)
 function that sets `admin_role` as `role`'s admin role.

Emits a [RoleAdminChanged](#roleadminchanged)
 event.

Parameters:

    role: felt
    admin_role: felt

Returns: None.

### [](#accesscontrol_events)
AccessControl events

    func RoleGranted(role: felt, account: felt, sender: felt):
    end
    
    func RoleRevoked(role: felt, account: felt, sender: felt):
    end
    
    func RoleAdminChanged(
        role: felt,
        previousAdminRole: felt,
        newAdminRole: felt
      ):
    end

#### [](#rolegranted)
`RoleGranted`

Emitted when `account` is granted `role`.

`sender` is the account that originated the contract call, an admin role bearer.

Parameters:

    role: felt
    account: felt
    sender: felt

#### [](#rolerevoked)
`RoleRevoked`

Emitted when account is revoked role.

`sender` is the account that originated the contract call:

*   if using [revoke\_role](#revoke_role)
    , it is the admin role bearer
    
*   if using [renounce\_role](#renounce_role)
    , it is the role bearer (i.e. `account`).
    

    role: felt
    account: felt
    sender: felt

#### [](#roleadminchanged)
`RoleAdminChanged`

Emitted when `newAdminRole` is set as `role`'s admin role, replacing `previousAdminRole`

`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite `RoleAdminChanged` not being emitted signaling this.

    role: felt
    previousAdminRole: felt
    newAdminRole: felt

[← Accounts](/contracts-cairo/0.3.2/accounts)

[ERC20 →](/contracts-cairo/0.3.2/erc20)




 Extensibility - OpenZeppelin Docs       

Extensibility
=============

|     |     |
| --- | --- |
|     | Expect this pattern to evolve (as it has already done) or even disappear if [proper extensibility features](https://community.starknet.io/t/contract-extensibility-pattern/210/11?u=martriay)<br> are implemented into Cairo. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [The extensibility problem](#the_extensibility_problem)
    
*   [The pattern ™️](#the_pattern)
    
    *   [Libraries](#libraries)
        
    *   [Contracts](#contracts)
        
    
*   [Presets](#presets)
    
*   [Function names and coding style](#function_names_and_coding_style)
    
*   [Emulating hooks](#emulating_hooks)
    

[](#the_extensibility_problem)
The extensibility problem
--------------------------------------------------------

Smart contract development is a critical task. As with all software development, it is error prone; but unlike most scenarios, a bug can result in major losses for organizations as well as individuals. Therefore writing complex smart contracts is a delicate task.

One of the best approaches to minimize introducing bugs is to reuse existing, battle-tested code, a.k.a. using libraries. But code reutilization in StarkNet’s smart contracts is not easy:

*   Cairo has no explicit smart contract extension mechanisms such as inheritance or composability.
    
*   Using imports for modularity can result in clashes (more so given that arguments are not part of the selector), and lack of overrides or aliasing leaves no way to resolve them.
    
*   Any `@external` function defined in an imported module will be automatically re-exposed by the importer (i.e. the smart contract).
    

To overcome these problems, this project builds on the following guidelines™.

[](#the_pattern)
The pattern
----------------------------

The idea is to have two types of Cairo modules: libraries and contracts. Libraries define reusable logic and storage variables which can then be extended and exposed by contracts. Contracts can be deployed, libraries cannot.

To minimize risk, boilerplate, and avoid function naming clashes, we follow these rules:

### [](#libraries)
Libraries

Considering the following types of functions:

*   `private`: private to a library, not meant to be used outside the module or imported.
    
*   `public`: part of the public API of a library.
    
*   `internal`: subset of `public` that is either discouraged or potentially unsafe (e.g. `_transfer` on ERC20).
    
*   `external`: subset of `public` that is ready to be exported as-is by contracts (e.g. `transfer` on ERC20).
    
*   `storage`: storage variable functions.
    

Then:

*   Must implement `public` and `external` functions under a namespace.
    
*   Must implement `private` functions outside the namespace to avoid exposing them.
    
*   Must prefix `internal` functions with an underscore (e.g. `ERC20._mint`).
    
*   Must not prefix `external` functions with an underscore (e.g. `ERC20.transfer`).
    
*   Must prefix `storage` functions with the name of the namespace to prevent clashing with other libraries (e.g. `ERC20balances`).
    
*   Must not implement any `@external`, `@view`, or `@constructor` functions.
    
*   Can implement initializers (never as `@constructor` or `@external`).
    
*   Must not call initializers on any function.
    

### [](#contracts)
Contracts

*   Can import from libraries.
    
*   Should implement `@external` functions if needed.
    
*   Should implement a `@constructor` function that calls initializers.
    
*   Must not call initializers in any function beside the constructor.
    

Note that since initializers will never be marked as `@external` and they won’t be called from anywhere but the constructor, there’s no risk of re-initialization after deployment. It’s up to the library developers not to make initializers interdependent to avoid weird dependency paths that may lead to double construction of libraries.

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets are:

*   [Account](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/account/presets/Account.cairo)
    
*   [ERC165](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/tests/mocks/ERC165.cairo)
    
*   [ERC20Mintable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
    
*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   [ERC20](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc20/presets/ERC20.cairo)
    
*   [ERC721MintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    
*   [ERC721EnumerableMintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.6.0/src/openzeppelin/token/erc721/enumerable/presets/ERC721EnumerableMintableBurnable.cairo)
    

In previous versions of Cairo importing any function from a module would automatically import all `@external` functions. We used to leverage this behavior to just import the constructor of the preset contract to load it. Since Cairo v0.10, however, contracts that utilize the preset contracts should import all of the exposed functions from it. For example:

    %lang starknet
    
    from openzeppelin.token.erc20.presets.ERC20 import constructor

should now look like:

    %lang starknet
    
    from openzeppelin.token.erc20.presets.ERC20 import (
        constructor,
        name,
        symbol,
        totalSupply,
        decimals,
        balanceOf,
        allowance,
        transfer,
        transferFrom,
        approve,
        increaseAllowance,
        decreaseAllowance
    )

[](#function_names_and_coding_style)
Function names and coding style
--------------------------------------------------------------------

*   Following Cairo’s programming style, we use `snake_case` for library APIs (e.g. `ERC20.transfer_from`, `ERC721.safe_transfer_from`).
    
*   But for standard EVM ecosystem compatibility, we implement external functions in contracts using `camelCase` (e.g. `transferFrom` in a ERC20 contract).
    
*   Guard functions such as the so-called "only owner" are prefixed with `assert_` (e.g. `Ownable.assert_only_owner`).
    

[](#emulating_hooks)
Emulating hooks
------------------------------------

Unlike the Solidity version of [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts)
, this library does not implement [hooks](https://docs.openzeppelin.com/contracts/4.x/extending-contracts#using-hooks)
. The main reason being that Cairo does not support overriding functions.

This is what a hook looks like in Solidity:

    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }

Instead, the extensibility pattern allows us to simply extend the library implementation of a function (namely `transfer`) by adding lines before or after calling it. This way, we can get away with:

    @external
    func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        recipient: felt, amount: Uint256
    ) -> (success: felt) {
        Pausable.assert_not_paused();
        return ERC20.transfer(recipient, amount);
    }

[← Overview](/contracts-cairo/0.6.0/)

[Proxies and Upgrades →](/contracts-cairo/0.6.0/proxies)




 Accounts - OpenZeppelin Docs       

Accounts
========

Unlike Ethereum where accounts are directly derived from a private key, there’s no native account concept on StarkNet.

Instead, signature validation has to be done at the contract level. To relieve smart contract applications such as ERC20 tokens or exchanges from this responsibility, we make use of Account contracts to deal with transaction authentication.

A more detailed writeup on the topic can be found on [Perama’s blogpost](https://perama-v.github.io/cairo/account-abstraction/)
.

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Standard Interface](#standard_interface)
    
*   [Keys, signatures and signers](#keys_signatures_and_signers)
    
    *   [Signer](#signer)
        
    *   [MockSigner utility](#mocksigner_utility)
        
    *   [MockEthSigner utility](#mockethsigner_utility)
        
    
*   [Account entrypoint](#account_entrypoint)
    
*   [Call and AccountCallArray format](#call_and_accountcallarray_format)
    
    *   [Call](#call)
        
    *   [AccountCallArray](#accountcallarray)
        
    
*   [Multicall transactions](#multicall_transactions)
    
*   [API Specification](#api_specification)
    
    *   [`get_public_key`](#get_public_key)
        
    *   [`get_nonce`](#get_nonce)
        
    *   [`set_public_key`](#set_public_key)
        
    *   [`is_valid_signature`](#is_valid_signature)
        
    *   [`__execute__`](#execute)
        
    *   [`is_valid_eth_signature`](#is_valid_eth_signature)
        
    *   [`eth_execute`](#eth_execute)
        
    *   [`_unsafe_execute`](#unsafe_execute)
        
    
*   [Presets](#presets)
    
    *   [Account](#account)
        
    *   [Eth Account](#eth_account)
        
    
*   [Account differentiation with ERC165](#account_differentiation_with_erc165)
    
*   [Extending the Account contract](#extending_the_account_contract)
    
*   [L1 escape hatch mechanism](#l1_escape_hatch_mechanism)
    
*   [Paying for gas](#paying_for_gas)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  Account contract is deployed to StarkNet
    
2.  Signed transactions can now be sent to the Account contract which validates and executes them
    

In Python, this would look as follows:

    from starkware.starknet.testing.starknet import Starknet
    from utils import get_contract_class
    from signers import MockSigner
    
    signer = MockSigner(123456789987654321)
    
    starknet = await Starknet.empty()
    
    # 1. Deploy Account
    account = await starknet.deploy(
        get_contract_class("Account"),
        constructor_calldata=[signer.public_key]
    )
    
    # 2. Send transaction through Account
    await signer.send_transaction(account, some_contract_address, 'some_function', [some_parameter])

[](#standard_interface)
Standard Interface
------------------------------------------

The [`IAccount.cairo`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/IAccount.cairo)
 contract interface contains the standard account interface proposed in [#41](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and adopted by OpenZeppelin and Argent. It implements [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and it is agnostic of signature validation and nonce management strategies.

    @contract_interface
    namespace IAccount:
        #
        # Getters
        #
    
        func get_nonce() -> (res : felt):
        end
    
        #
        # Business logic
        #
    
        func is_valid_signature(
                hash: felt,
                signature_len: felt,
                signature: felt*
            ) -> (is_valid: felt):
        end
    
        func __execute__(
                call_array_len: felt,
                call_array: AccountCallArray*,
                calldata_len: felt,
                calldata: felt*,
                nonce: felt
            ) -> (response_len: felt, response: felt*):
        end
    end

[](#keys_signatures_and_signers)
Keys, signatures and signers
-------------------------------------------------------------

While the interface is agnostic of signature validation schemes, this implementation assumes there’s a public-private key pair controlling the Account. That’s why the `constructor` function expects a `public_key` parameter to set it. Since there’s also a `set_public_key()` method, accounts can be effectively transferred.

### [](#signer)
Signer

The signer is responsible for creating a transaction signature with the user’s private key for a given transaction. This implementation utilizes [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 class to create transaction signatures through the `Signer` method `sign_transaction`.

`sign_transaction` expects the following parameters per transaction:

*   `sender` the contract address invoking the tx
    
*   `calls` a list containing a sublist of each call to be sent. Each sublist must consist of:
    
    1.  `to` the address of the target contract of the message
        
    2.  `selector` the function to be called on the target contract
        
    3.  `calldata` the parameters for the given `selector`
        
    
*   `nonce` an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    
*   `max_fee` the maximum fee a user will pay
    

Which returns:

*   `calls` a list of calls to be bundled in the transaction
    
*   `calldata` a list of arguments for each call
    
*   `sig_r` the transaction signature
    
*   `sig_s` the transaction signature
    

While the `Signer` class performs much of the work for a transaction to be sent, it neither manages nonces nor invokes the actual transaction on the Account contract. To simplify Account management, most of this is abstracted away with `MockSigner`.

### [](#mocksigner_utility)
MockSigner utility

The `MockSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account, crafting the transaction and managing nonces.

The flow of a transaction starts with checking the nonce and converting the `to` contract address of each call to hexadecimal format. The hexadecimal conversion is necessary because Nile’s `Signer` converts the address to a base-16 integer (which requires a string argument). Note that directly converting `to` to a string will ultimately result in an integer exceeding Cairo’s `FIELD_PRIME`.

The values included in the transaction are passed to the `sign_transaction` method of Nile’s `Signer` which creates and returns a signature. Finally, the `MockSigner` instance invokes the account contract’s `__execute__` with the transaction data.

Users only need to interact with the following exposed methods to perform a transaction:

*   `send_transaction(account, to, selector_name, calldata, nonce=None, max_fee=0)` returns a future of a signed transaction, ready to be sent.
    
*   `send_transactions(account, calls, nonce=None, max_fee=0)` returns a future of batched signed transactions, ready to be sent.
    

To use `MockSigner`, pass a private key when instantiating the class:

    from utils import MockSigner
    
    PRIVATE_KEY = 123456789987654321
    signer = MockSigner(PRIVATE_KEY)

Then send single transactions with the `send_transaction` method.

    await signer.send_transaction(account, contract_address, 'method_name', [])

If utilizing multicall, send multiple transactions with the `send_transactions` method.

        await signer.send_transactions(
            account,
            [\
                (contract_address, 'method_name', [param1, param2]),\
                (contract_address, 'another_method', [])\
            ]
        )

### [](#mockethsigner_utility)
MockEthSigner utility

The `MockEthSigner` class in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 is used to perform transactions on a given Account with a secp256k1 curve key pair, crafting the transaction and managing nonces. It differs from the `MockSigner` implementation by:

*   not using the public key but its derived address instead (the last 20 bytes of the keccak256 hash of the public key and adding `0x` to the beginning)
    
*   signing the message with a secp256k1 curve address
    

[](#account_entrypoint)
Account entrypoint
------------------------------------------

`__execute__` acts as a single entrypoint for all user interaction with any contract, including managing the account contract itself. That’s why if you want to change the public key controlling the Account, you would send a transaction targeting the very Account contract:

    await signer.send_transaction(account, account.contract_address, 'set_public_key', [NEW_KEY])

Or if you want to update the Account’s L1 address on the `AccountRegistry` contract, you would

    await signer.send_transaction(account, registry.contract_address, 'set_L1_address', [NEW_ADDRESS])

You can read more about how messages are structured and hashed in the [Account message scheme discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/24)
. For more information on the design choices and implementation of multicall, you can read the [How should Account multicall work discussion](https://github.com/OpenZeppelin/cairo-contracts/discussions/27)
.

The `__execute__` method has the following interface:

    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

Where:

*   `call_array_len` is the number of calls
    
*   `call_array` is an array representing each `Call`
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    
*   `nonce` is an unique identifier of this message to prevent transaction replays. Current implementation requires nonces to be incremental
    

|     |     |
| --- | --- |
|     | The scheme of building multicall transactions within the `__execute__` method will change once StarkNet allows for pointers in struct arrays. In which case, multiple transactions can be passed to (as opposed to built within) `__execute__`. |

[](#call_and_accountcallarray_format)
`Call` and `AccountCallArray` format
--------------------------------------------------------------------------

The idea is for all user intent to be encoded into a `Call` representing a smart contract call. Users can also pack multiple messages into a single transaction (creating a multicall transaction). Cairo currently does not support arrays of structs with pointers which means the `__execute__` function cannot properly iterate through mutiple `Call`s. Instead, this implementation utilizes a workaround with the `AccountCallArray` struct. See [Multicall transactions](#multicall_transactions)
.

### [](#call)
`Call`

A single `Call` is structured as follows:

    struct Call:
        member to: felt
        member selector: felt
        member calldata_len: felt
        member calldata: felt*
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `calldata_len` is the number of calldata parameters
    
*   `calldata` is an array representing the function parameters
    

### [](#accountcallarray)
`AccountCallArray`

`AccountCallArray` is structured as:

    struct AccountCallArray:
        member to: felt
        member selector: felt
        member data_offset: felt
        member data_len: felt
    end

Where:

*   `to` is the address of the target contract of the message
    
*   `selector` is the selector of the function to be called on the target contract
    
*   `data_offset` is the starting position of the calldata array that holds the `Call`'s calldata
    
*   `data_len` is the number of calldata elements in the `Call`
    

[](#multicall_transactions)
Multicall transactions
--------------------------------------------------

A multicall transaction packs the `to`, `selector`, `calldata_offset`, and `calldata_len` of each call into the `AccountCallArray` struct and keeps the cumulative calldata for every call in a separate array. The `__execute__` function rebuilds each message by combining the `AccountCallArray` with its calldata (demarcated by the offset and calldata length specified for that particular call). The rebuilding logic is set in the internal `_from_call_array_to_call`.

This is the basic flow:

First, the user sends the messages for the transaction through a Signer instantiation which looks like this:

     await signer.send_transaction(
             account, [\
                 (contract_address, 'contract_method', [arg_1]),\
                 (contract_address, 'another_method', [arg_1, arg_2])\
             ]
         )

Then the `_from_call_to_call_array` method in [utils.py](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/utils.py)
 converts each call into the `AccountCallArray` format and cumulatively stores the calldata of every call into a single array. Next, both arrays (as well as the `sender`, `nonce`, and `max_fee`) are used to create the transaction hash. The Signer then invokes `__execute__` with the signature and passes `AccountCallArray`, calldata, and nonce as arguments.

Finally, the `__execute__` method takes the `AccountCallArray` and calldata and builds an array of `Call`s (MultiCall).

|     |     |
| --- | --- |
|     | Every transaction utilizes `AccountCallArray`. A single `Call` is treated as a bundle with one message. |

[](#api_specification)
API Specification
----------------------------------------

This in a nutshell is the Account contract public API:

    func get_public_key() -> (res: felt):
    end
    
    func get_nonce() -> (res: felt):
    end
    
    func set_public_key(new_public_key: felt):
    end
    
    func is_valid_signature(hash: felt,
            signature_len: felt,
            signature: felt*
        ) -> (is_valid: felt):
    end
    
    func __execute__(
            call_array_len: felt,
            call_array: AccountCallArray*,
            calldata_len: felt,
            calldata: felt*,
            nonce: felt
        ) -> (response_len: felt, response: felt*):
    end

### [](#get_public_key)
`get_public_key`

Returns the public key associated with the Account contract.

Parameters: None.

Returns:

    public_key: felt

### [](#get_nonce)
`get_nonce`

Returns the current transaction nonce for the Account.

Parameters: None.

Returns:

    nonce: felt

### [](#set_public_key)
`set_public_key`

Sets the public key that will control this Account. It can be used to rotate keys for security, change them in case of compromised keys or even transferring ownership of the account.

Parameters:

    public_key: felt

Returns: None.

### [](#is_valid_signature)
`is_valid_signature`

This function is inspired by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)
 and returns `TRUE` if a given signature is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    hash: felt
    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#execute)
`__execute__`

This is the only external entrypoint to interact with the Account contract. It:

1.  Validates the transaction signature matches the message (including the nonce)
    
2.  Increments the nonce
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

|     |     |
| --- | --- |
|     | The current signature scheme expects a 2-element array like `[sig_r, sig_s]`. |

Returns:

    response_len: felt
    response: felt*

### [](#is_valid_eth_signature)
`is_valid_eth_signature`

Returns `TRUE` if a given signature in the secp256k1 curve is valid, otherwise it reverts. In the future it will return `FALSE` if a given signature is invalid (for more info please check [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)
).

Parameters:

    signature_len: felt
    signature: felt*

Returns:

    is_valid: felt

|     |     |
| --- | --- |
|     | It may return `FALSE` in the future if a given signature is invalid (follow the discussion on [this issue](https://github.com/OpenZeppelin/cairo-contracts/issues/327)<br>). |

### [](#eth_execute)
`eth_execute`

This follows the same idea as the vanilla version of `execute` with the sole difference that signature verification is on the secp256k1 curve.

Parameters:

    call_array_len: felt
    call_array: AccountCallArray*
    calldata_len: felt
    calldata: felt*
    nonce: felt

Returns:

    response_len: felt
    response: felt*

|     |     |
| --- | --- |
|     | The current signature scheme expects a 7-element array like `[sig_v, uint256_sig_r_low, uint256_sig_r_high, uint256_sig_s_low, uint256_sig_s_high, uint256_hash_low, uint256_hash_high]` given that the parameters of the verification are bigger than a felt. |

### [](#unsafe_execute)
`_unsafe_execute`

It’s an [internal](extensibility#the_pattern)
 method that performs the following tasks:

1.  Increments the nonce.
    
2.  Takes the input and builds a `Call` for each iterated message. See [Multicall transactions](#multicall_transactions)
     for more information.
    
3.  Calls the target contract with the intended function selector and calldata parameters
    
4.  Forwards the contract call response data as return value
    

[](#presets)
Presets
--------------------

The following contract presets are ready to deploy and can be used as-is for quick prototyping and testing. Each preset differs on the signature type being used by the Account.

### [](#account)
Account

The [`Account`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
 preset uses StarkNet keys to validate transactions.

### [](#eth_account)
Eth Account

The [`EthAccount`](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/EthAccount.cairo)
 preset supports Ethereum addresses, validating transactions with secp256k1 keys.

[](#account_differentiation_with_erc165)
Account differentiation with ERC165
----------------------------------------------------------------------------

Certain contracts like ERC721 require a means to differentiate between account contracts and non-account contracts. For a contract to declare itself as an account, it should implement [ERC165](https://eips.ethereum.org/EIPS/eip-165)
 as proposed in [#100](https://github.com/OpenZeppelin/cairo-contracts/discussions/100)
. To be in compliance with ERC165 specifications, the idea is to calculate the XOR of `IAccount`'s EVM selectors (not StarkNet selectors). The resulting magic value of `IAccount` is 0x50b70dcb.

Our ERC165 integration on StarkNet is inspired by OpenZeppelin’s Solidity implementation of [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
 which stores the interfaces that the implementing contract supports. In the case of account contracts, querying `supportsInterface` of an account’s address with the `IAccount` magic value should return `TRUE`.

[](#extending_the_account_contract)
Extending the Account contract
------------------------------------------------------------------

Account contracts can be extended by following the [extensibility pattern](extensibility#the_pattern)
.

To implement custom account contracts, a pair of `validate` and `execute` functions should be exposed. This is why the Account library comes with different flavors of such pairs, like the vanilla `is_valid_signature` and `execute`, or the Ethereum flavored `is_valid_eth_signature` and `eth_execute` pair.

Account contract developers are encouraged to implement the [standard Account interface](https://github.com/OpenZeppelin/cairo-contracts/discussions/41)
 and incorporate the custom logic thereafter.

To implement alternative `execute` functions, make sure to check their corresponding `validate` function before calling the `_unsafe_execute` building block, as each of the current presets is doing. Do not expose `_unsafe_execute` directly.

|     |     |
| --- | --- |
|     | The `ecdsa_ptr` implicit argument should be included in new methods that invoke `_unsafe_execute` (even if the `ecdsa_ptr` is not being used). Otherwise, it’s possible that an account’s functionality can work in both the testing and local devnet environments; however, it could fail on public networks on account of the [SignatureBuiltinRunner](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py)<br>. See [issue #386](https://github.com/OpenZeppelin/cairo-contracts/issues/386)<br> for more information. |

Some other validation schemes to look out for in the future:

*   multisig
    
*   guardian logic like in [Argent’s account](https://github.com/argentlabs/argent-contracts-starknet/blob/de5654555309fa76160ba3d7393d32d2b12e7349/contracts/ArgentAccount.cairo)
    

[](#l1_escape_hatch_mechanism)
L1 escape hatch mechanism
--------------------------------------------------------

[](#paying_for_gas)
Paying for gas
----------------------------------

[← Proxies and Upgrades](/contracts-cairo/0.3.2/proxies)

[Access Control →](/contracts-cairo/0.3.2/access)




 Proxies - OpenZeppelin Docs       

Proxies
=======

|     |     |
| --- | --- |
|     | Expect rapid iteration as this pattern matures and more patterns potentially emerge. |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Quickstart](#quickstart)
    
*   [Solidity/Cairo upgrades comparison](#soliditycairo_upgrades_comparison)
    
    *   [Constructors](#constructors)
        
    *   [Storage](#storage)
        
    
*   [Proxies](#proxies2)
    
    *   [Proxy contract](#proxy_contract)
        
    *   [Implementation contract](#implementation_contract)
        
    
*   [Upgrades library API](#upgrades_library_api)
    
    *   [Methods](#methods)
        
    *   [Events](#events)
        
    
*   [Using proxies](#using_proxies)
    
    *   [Contract upgrades](#contract_upgrades)
        
    *   [Declaring contracts](#declaring_contracts)
        
    *   [Testing method calls](#testing_method_calls)
        
    
*   [Presets](#presets)
    

[](#quickstart)
Quickstart
--------------------------

The general workflow is:

1.  declare an implementation [contract class](https://starknet.io/docs/hello_starknet/intro.html#declare-the-contract-on-the-starknet-testnet)
    
2.  deploy proxy contract with the implementation contract’s class hash set in the proxy’s constructor calldata
    
3.  initialize the implementation contract by sending a call to the proxy contract. This will redirect the call to the implementation contract class and behave like the implementation contract’s constructor
    

In Python, this would look as follows:

        # declare implementation contract
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation contract class hash\
            ]
        )
    
        # users should only interact with the proxy contract
        await signer.send_transaction(
            account, PROXY.contract_address, 'initializer', [\
                proxy_admin\
            ]
        )

[](#soliditycairo_upgrades_comparison)
Solidity/Cairo upgrades comparison
-------------------------------------------------------------------------

### [](#constructors)
Constructors

OpenZeppelin Contracts for Solidity requires the use of an alternative library for upgradeable contracts. Consider that in Solidity constructors are not part of the deployed contract’s runtime bytecode; rather, a constructor’s logic is executed only once when the contract instance is deployed and then discarded. This is why proxies can’t imitate the construction of its implementation, therefore requiring a different initialization mechanism.

The constructor problem in upgradeable contracts is resolved by the use of initializer methods. Initializer methods are essentially regular methods that execute the logic that would have been in the constructor. Care needs to be exercised with initializers to ensure they can only be called once. Thus, OpenZeppelin offers an [upgradeable contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable)
 where much of this process is abstracted away. See OpenZeppelin’s [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)
 for more info.

The Cairo programming language does not support inheritance. Instead, Cairo contracts follow the [Extensibility Pattern](extensibility)
 which already uses initializer methods to mimic constructors. Upgradeable contracts do not, therefore, require a separate library with refactored constructor logic.

### [](#storage)
Storage

OpenZeppelin’s alternative Upgrades library also implements [unstructured storage](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#unstructured-storage-proxies)
 for its upgradeable contracts. The basic idea behind unstructured storage is to pseudo-randomize the storage structure of the upgradeable contract so it’s based on variable names instead of declaration order, which makes the chances of storage collision during an upgrade extremely unlikely.

The StarkNet compiler, meanwhile, already creates pseudo-random storage addresses by hashing the storage variable names (and keys in mappings) by default. In other words, StarkNet already uses unstructured storage and does not need a second library to modify how storage is set. See StarkNet’s [Contracts Storage documentation](https://starknet.io/documentation/contracts/#contracts_storage)
 for more information.

[](#proxies2)
Proxies
---------------------

A proxy contract is a contract that delegates function calls to another contract. This type of pattern decouples state and logic. Proxy contracts store the state and redirect function calls to an implementation contract that handles the logic. This allows for different patterns such as upgrades, where implementation contracts can change but the proxy contract (and thus the state) does not; as well as deploying multiple proxy instances pointing to the same implementation. This can be useful to deploy many contracts with identical logic but unique initialization data.

In the case of contract upgrades, it is achieved by simply changing the proxy’s reference to the class hash of the declared implementation. This allows developers to add features, update logic, and fix bugs without touching the state or the contract address to interact with the application.

### [](#proxy_contract)
Proxy contract

The [Proxy contract](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/presets/Proxy.cairo)
 includes two core methods:

1.  The `__default__` method is a fallback method that redirects a function call and associated calldata to the implementation contract.
    
2.  The `__l1_default__` method is also a fallback method; however, it redirects the function call and associated calldata to a layer one contract. In order to invoke `__l1_default__`, the original function call must include the library function `send_message_to_l1`. See Cairo’s [Interacting with L1 contracts](https://www.cairo-lang.org/docs/hello_starknet/l1l2.html)
     for more information.
    

Since this proxy is designed to work both as an [UUPS-flavored upgrade proxy](https://eips.ethereum.org/EIPS/eip-1822)
 as well as a non-upgradeable proxy, it does not know how to handle its own state. Therefore it requires the implementation contract class to be declared beforehand, so its class hash can be passed to the Proxy on construction time.

When interacting with the contract, function calls should be sent by the user to the proxy. The proxy’s fallback function redirects the function call to the implementation contract to execute.

### [](#implementation_contract)
Implementation contract

The implementation contract, also known as the logic contract, receives the redirected function calls from the proxy contract. The implementation contract should follow the [Extensibility pattern](extensibility#the_pattern)
 and import directly from the [Proxy library](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/upgrades/library.cairo)
.

The implementation contract should:

*   import `Proxy` namespace
    
*   initialize the proxy immediately after contract deployment with `Proxy.initializer`.
    

If the implementation is upgradeable, it should:

*   include a method to upgrade the implementation (i.e. `upgrade`)
    
*   use access control to protect the contract’s upgradeability.
    

The implementation contract should NOT:

*   be deployed like a regular contract. Instead, the implementation contract should be declared (which creates a `DeclaredClass` containing its hash and abi)
    
*   set its initial state with a traditional constructor (decorated with `@constructor`). Instead, use an initializer method that invokes the Proxy `constructor`.
    

|     |     |
| --- | --- |
|     | The Proxy `constructor` includes a check the ensures the initializer can only be called once; however, `_set_implementation` does not include this check. It’s up to the developers to protect their implementation contract’s upgradeability with access controls such as [`assert_only_admin`](#assert_only_admin)<br>. |

For a full implementation contract example, please see:

*   [Proxiable implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/ProxiableImplementation.cairo)
    

[](#upgrades_library_api)
Upgrades library API
----------------------------------------------

### [](#methods)
Methods

    func initializer(proxy_admin: felt):
    end
    
    func assert_only_admin():
    end
    
    func get_implementation_hash() -> (implementation: felt):
    end
    
    func get_admin() -> (admin: felt):
    end
    
    func _set_admin(new_admin: felt):
    end
    
    func _set_implementation_hash(new_implementation: felt):
    end

#### [](#initializer)
`initializer`

Initializes the proxy contract with an initial implementation.

Parameters:

    proxy_admin: felt

Returns: None.

#### [](#assert_only_admin)
`assert_only_admin`

Reverts if called by any account other than the admin.

Parameters: None.

Returns: None.

#### [](#get_implementation)
`get_implementation`

Returns the current implementation hash.

Parameters: None.

Returns:

    implementation: felt

#### [](#get_admin)
`get_admin`

Returns the current admin.

Parameters: None.

Returns:

    admin: felt

#### [](#set_admin)
`_set_admin`

Sets `new_admin` as the admin of the proxy contract.

Parameters:

    new_admin: felt

Returns: None.

#### [](#set_implementation_hash)
`_set_implementation_hash`

Sets `new_implementation` as the implementation’s contract class. This method is included in the proxy contract’s constructor and can be used to upgrade contracts.

Parameters:

    new_implementation: felt

Returns: None.

### [](#events)
Events

    func Upgraded(implementation: felt):
    end
    
    func AdminChanged(previousAdmin: felt, newAdmin: felt):
    end

#### [](#upgraded)
`Upgraded`

Emitted when a proxy contract sets a new implementation class hash.

Parameters:

    implementation: felt

#### [](#adminchanged)
`AdminChanged`

Emitted when the `admin` changes from `previousAdmin` to `newAdmin`.

Parameters:

    previousAdmin: felt
    newAdmin: felt

[](#using_proxies)
Using proxies
--------------------------------

### [](#contract_upgrades)
Contract upgrades

To upgrade a contract, the implementation contract should include an `upgrade` method that, when called, changes the reference to a new deployed contract like this:

        # declare first implementation
        IMPLEMENTATION = await starknet.declare(
            "path/to/implementation.cairo",
        )
    
        # deploy proxy
        PROXY = await starknet.deploy(
            "path/to/proxy.cairo",
            constructor_calldata=[\
                IMPLEMENTATION.class_hash,  # set implementation hash\
            ]
        )
    
        # declare implementation v2
        IMPLEMENTATION_V2 = await starknet.declare(
            "path/to/implementation_v2.cairo",
        )
    
        # call upgrade with the new implementation contract class hash
        await signer.send_transaction(
            account, PROXY.contract_address, 'upgrade', [\
                IMPLEMENTATION_V2.class_hash\
            ]
        )

For a full deployment and upgrade implementation, please see:

*   [Upgrades V1](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV1.cairo)
    
*   [Upgrades V2](https://github.com/OpenZeppelin/cairo-contracts/blob/main/tests/mocks/UpgradesMockV2.cairo)
    

### [](#declaring_contracts)
Declaring contracts

StarkNet contracts come in two forms: contract classes and contract instances. Contract classes represent the uninstantiated, stateless code; whereas, contract instances are instantiated and include the state. Since the Proxy contract references the implementation contract by its class hash, declaring an implementation contract proves sufficient (as opposed to a full deployment). For more information on declaring classes, see [StarkNet’s documentation](https://starknet.io/docs/hello_starknet/intro.html#declare-contract)
.

### [](#testing_method_calls)
Testing method calls

As with most StarkNet contracts, interacting with a proxy contract requires an [account abstraction](accounts#quickstart)
. Due to limitations in the StarkNet testing framework, however, `@view` methods also require an account abstraction. This is only a requirement when testing. The differences in getter methods written in Python, for example, are as follows:

    # standard ERC20 call
    result = await erc20.totalSupply().call()
    
    # upgradeable ERC20 call
    result = await signer.send_transaction(
            account, PROXY.contract_address, 'totalSupply', []
        )

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets include:

*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   more to come! have an idea? [open an issue](https://github.com/OpenZeppelin/cairo-contracts/issues/new/choose)
    !
    

[← Extensibility](/contracts-cairo/0.3.2/extensibility)

[Accounts →](/contracts-cairo/0.3.2/accounts)




 Security - OpenZeppelin Docs       

Security
========

The following documentation provides context, reasoning, and examples of modules found under `openzeppelin::security`.

|     |     |
| --- | --- |
|     | Expect these modules to evolve. |

[](#initializable)
Initializable
--------------------------------

The [Initializable](api/security#InitializableComponent)
 component provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to set up a contract’s initial state when a constructor cannot be used, for example when there are circular dependencies at construction time.

You can use the component in your contracts like this:

    #[starknet::contract]
    mod MyInitializableContract {
        use openzeppelin::security::InitializableComponent;
    
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        impl InternalImpl = InitializableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            initializable: InitializableComponent::Storage,
            param: felt252
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    
        fn initializer(ref self: ContractState, some_param: felt252) {
            // Makes the method callable only once
            self.initializable.initialize();
    
            // Initialization logic
            self.param.write(some_param);
        }
    }

|     |     |
| --- | --- |
|     | This Initializable pattern should only be used in one function. |

[](#pausable)
Pausable
----------------------

The [Pausable](api/security#PausableComponent)
 component allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.

To become pausable, the contract should include `pause` and `unpause` functions (which should be protected). For methods that should be available only when paused or not, insert calls to `[assert_paused](api/security#PausableComponent-assert_paused) ` and `[assert_not_paused](api/security#PausableComponent-assert_not_paused) ` respectively.

For example (using the [Ownable](api/access#OwnableComponent)
 component for access control):

    #[starknet::contract]
    mod MyPausableContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use openzeppelin::security::PausableComponent;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
        component!(path: PausableComponent, storage: pausable, event: PausableEvent);
    
        // Ownable
        #[abi(embed_v0)]
        impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
        impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        // Pausable
        #[abi(embed_v0)]
        impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
        impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage,
            #[substorage(v0)]
            pausable: PausableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event,
            #[flat]
            PausableEvent: PausableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            self.ownable.initializer(owner);
        }
    
        #[generate_trait]
        #[external(v0)]
        impl ExternalImpl of ExternalTrait {
            fn pause(ref self: ContractState) {
                self.ownable.assert_only_owner();
                self.pausable._pause();
            }
    
            fn unpause(ref self: ContractState) {
                self.ownable.assert_only_owner();
                self.pausable._unpause();
            }
    
            fn when_not_paused(ref self: ContractState) {
                self.pausable.assert_not_paused();
                // Do something
            }
    
            fn when_paused(ref self: ContractState) {
                self.pausable.assert_paused();
                // Do something
            }
        }
    }

[](#reentrancy_guard)
Reentrancy Guard
--------------------------------------

A [reentrancy attack](https://gus-tavo-guim.medium.com/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4)
 occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.

Since Cairo does not support modifiers like Solidity, the [ReentrancyGuard](api/security#ReentrancyGuardComponent)
 component exposes two methods `[start](api/security#ReentrancyGuardComponent-start) ` and `[end](api/security#ReentrancyGuardComponent-end) ` to protect functions against reentrancy attacks. The protected function must call `start` before the first function statement, and `end` before the return statement, as shown below:

    #[starknet::contract]
    mod MyReentrancyContract {
        use openzeppelin::security::ReentrancyGuardComponent;
    
        component!(
            path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent
        );
    
        impl InternalImpl = ReentrancyGuardComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            reentrancy_guard: ReentrancyGuardComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ReentrancyGuardEvent: ReentrancyGuardComponent::Event
        }
    
        #[generate_trait]
        #[external(v0)]
        impl ExternalImpl of ExternalTrait {
            fn protected_function(ref self: ContractState) {
                self.reentrancy_guard.start();
    
                // Do something
    
                self.reentrancy_guard.end();
            }
    
            fn another_protected_function(ref self: ContractState) {
                self.reentrancy_guard.start();
    
                // Do something
    
                self.reentrancy_guard.end();
            }
        }
    }

|     |     |
| --- | --- |
|     | The guard prevents the execution flow occurring inside `protected_function` to call itself or `another_protected_function`, and vice versa. |

[← API Reference](/contracts-cairo/0.8.1/api/introspection)

[API Reference →](/contracts-cairo/0.8.1/api/security)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

The ERC20 token standard is a specification for [fungible tokens](https://docs.openzeppelin.com/contracts/4.x/tokens#different-kinds-of-tokens)
, a type of token where all the units are exactly equal to each other. The `token::erc20::ERC20` contract implements an approximation of [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
 in Cairo for Starknet.

|     |     |
| --- | --- |
|     | Prior to [Contracts v0.7.0](https://github.com/OpenZeppelin/cairo-contracts/releases/tag/v0.7.0)<br>, ERC20 contracts store and read `decimals` from storage; however, this implementation returns a static `18`. If upgrading an older ERC20 contract that has a decimals value other than `18`, the upgraded contract **must** use a custom `decimals` implementation. See the [Customizing decimals](#customizing_decimals)<br> guide. |

[](#interface)
Interface
------------------------

The following interface represents the full ABI of the Contracts for Cairo `ERC20` preset. The interface includes the `IERC20` standard interface as well as non-standard functions like `increase_allowance`. To support older deployments of ERC20, as mentioned in [Dual interfaces](interfaces#dual_interfaces)
, `ERC20` also includes the previously defined functions written in camelCase.

    trait ERC20ABI {
        // IERC20
        fn name() -> felt252;
        fn symbol() -> felt252;
        fn decimals() -> u8;
        fn total_supply() -> u256;
        fn balance_of(account: ContractAddress) -> u256;
        fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256;
        fn transfer(recipient: ContractAddress, amount: u256) -> bool;
        fn transfer_from(
            sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn approve(spender: ContractAddress, amount: u256) -> bool;
    
        // Non-standard
        fn increase_allowance(spender: ContractAddress, added_value: u256) -> bool;
        fn decrease_allowance(spender: ContractAddress, subtracted_value: u256) -> bool;
    
        // Camel case compatibility
        fn totalSupply() -> u256;
        fn balanceOf(account: ContractAddress) -> u256;
        fn transferFrom(
            sender: ContractAddress, recipient: ContractAddress, amount: u256
        ) -> bool;
        fn increaseAllowance(spender: ContractAddress, addedValue: u256) -> bool;
        fn decreaseAllowance(spender: ContractAddress, subtractedValue: u256) -> bool;
    }

### [](#erc20_compatibility)
ERC20 compatibility

Although Starknet is not EVM compatible, this implementation aims to be as close as possible to the ERC20 standard. Some notable differences, however, can still be found, such as:

*   Cairo short strings are used to simulate `name` and `symbol` because Cairo does not yet include native string support.
    
*   The contract offers a [dual interface](interfaces#dual_interfaces)
     which supports both snake\_case and camelCase methods, as opposed to just camelCase in Solidity.
    
*   `transfer`, `transfer_from` and `approve` will never return anything different from `true` because they will revert on any error.
    
*   Function selectors are calculated differently between [Cairo](https://github.com/starkware-libs/cairo/blob/7dd34f6c57b7baf5cd5a30c15e00af39cb26f7e1/crates/cairo-lang-starknet/src/contract.rs#L39-L48)
     and [Solidity](https://solidity-by-example.org/function-selector/)
    .
    

[](#usage)
Usage
----------------

|     |     |
| --- | --- |
|     | The following example uses `unsafe_new_contract_state` to access another contract’s state. Although this is useful to use them as modules, it’s considered unsafe because storage members could clash among used contracts if not reviewed carefully. Extensibility will be revisited after [Components](https://community.starknet.io/t/cairo-1-contract-syntax-is-evolving/94794#extensibility-and-components-11)<br> are introduced. |

Using Contracts for Cairo, constructing an ERC20 contract requires setting up the constructor and exposing the ERC20 interface. Here’s what that looks like:

    #[starknet::contract]
    mod MyToken {
        use starknet::ContractAddress;
        use openzeppelin::token::erc20::ERC20;
    
        #[storage]
        struct Storage {}
    
        #[constructor]
        fn constructor(
            self: @ContractState,
            initial_supply: u256,
            recipient: ContractAddress
        ) {
            let name = 'MyToken';
            let symbol = 'MTK';
    
            let mut unsafe_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref unsafe_state, name, symbol);
            ERC20::InternalImpl::_mint(ref unsafe_state, recipient, initial_supply);
        }
    
        #[external(v0)]
        impl MyTokenImpl of IERC20<ContractState> {
            fn name(self: @ContractState) -> felt252 {
                let mut unsafe_state = ERC20::unsafe_new_contract_state();
                ERC20::ERC20Impl::name(@unsafe_state)
            }
    
            (...)
        }
    }

In order for the `MyToken` contract to extend the ERC20 contract, it utilizes the `unsafe_new_contract_state`. The unsafe contract state allows access to ERC20’s implementations. With this access, the constructor first calls the initializer to set the token name and symbol. The constructor then calls `_mint` to create a fixed supply of tokens.

|     |     |
| --- | --- |
|     | For a more complete guide on ERC20 token mechanisms, see [Creating ERC20 Supply](guides/erc20-supply)<br>. |

In the external implementation, notice that `MyTokenImpl` is an implementation of `IERC20`. This ensures that the external implementation will include all of the methods defined in the interface.

### [](#customizing_decimals)
Customizing decimals

Cairo, like Solidity, does not support [floating-point numbers](https://en.wikipedia.org//wiki/Floating-point_arithmetic)
. To get around this limitation, ERC20 offers a `decimals` field which communicates to outside interfaces (wallets, exchanges, etc.) how the token should be displayed. For instance, suppose a token had a `decimals` value of `3` and the total token supply was `1234`. An outside interface would display the token supply as `1.234`. In the actual contract, however, the supply would still be the integer `1234`. In other words, **the decimals field in no way changes the actual arithmetic** because all operations are still performed on integers.

Most contracts use `18` decimals and this was even proposed to be compulsory (see the [EIP discussion](https://github.com/ethereum/EIPs/issues/724)
). The Contracts for Cairo ERC20 implementation of `decimals` returns `18` by default to save on gas fees. For those who want an ERC20 token with a configurable number of decimals, the following guide shows two ways to achieve this.

#### [](#the_static_approach)
The static approach

The simplest way to customize `decimals` consists of returning the target value when exposing the `decimals` method. For example:

    #[external(v0)]
    impl MyTokenImpl of IERC20<ContractState> {
        fn decimals(self: @ContractState) -> u8 {
            // Change the `3` below to the desired number of decimals
            3
        }
    
        (...)
    }

#### [](#the_storage_approach)
The storage approach

For more complex scenarios, such as a factory deploying multiple tokens with differing values for decimals, a flexible solution might be appropriate.

    #[starknet::contract]
    mod MyToken {
        use starknet::ContractAddress;
        use openzeppelin::token::erc20::ERC20;
    
        #[storage]
        struct Storage {
            // The decimals value is stored locally
            _decimals: u8,
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            decimals: u8
        ) {
            // Call the internal function that writes decimals to storage
            self._set_decimals(decimals);
    
            // Initialize ERC20
            let name = 'MyToken';
            let symbol = 'MTK';
    
            let mut unsafe_state = ERC20::unsafe_new_contract_state();
            ERC20::InternalImpl::initializer(ref unsafe_state, name, symbol);
        }
    
        /// This is a standalone function for brevity.
        /// It's recommended to create an implementation of IERC20
        /// to ensure that the contract exposes the entire ERC20 interface.
        /// See the previous example.
        #[external(v0)]
        fn decimals(self: @ContractState) -> u8 {
            self._decimals.read()
        }
    
        #[generate_trait]
        impl InternalImpl of InternalTrait {
            fn _set_decimals(ref self: ContractState, decimals: u8) {
                self._decimals.write(decimals);
            }
        }
    }

This contract expects a `decimals` argument in the constructor and uses an internal function to write the decimals to storage. Note that the `_decimals` state variable must be stored in the local contract’s storage because this variable does not exist in the Contracts for Cairo library. It’s important to include the correct logic in the exposed `decimals` method and to NOT use the Contracts for Cairo `decimals` implementation in this specific case. The library’s `decimals` implementation does not read from storage and will return `18`.

[← API Reference](/contracts-cairo/0.8.0-beta.0/api/access)

[Creating Supply →](/contracts-cairo/0.8.0-beta.0/guides/erc20-supply)




 Wizard for Cairo - OpenZeppelin Docs       

Wizard for Cairo
================

Not sure where to start? Use the interactive generator below to bootstrap your contract and learn about the components offered in OpenZeppelin Contracts for Cairo.

|     |     |
| --- | --- |
|     | We strongly recommend checking the [Components](components)<br> section to understand how to extend from our library. |

[← Overview](/contracts-cairo/0.13.0/)

[Components →](/contracts-cairo/0.13.0/components)




 Backwards Compatibility - OpenZeppelin Docs       

Backwards Compatibility
=======================

OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. Patch and minor updates will generally be backwards compatible, with rare exceptions as detailed below. Major updates should be assumed incompatible with previous releases. On this page, we provide details about these guarantees.

Bear in mind that while releasing versions under `v1.0.0`, we treat minors as majors and patches as minors, in accordance with semantic versioning. This means that `v0.7.1` could be adding features to `v0.7.0`, while `v0.8.0` would be considered a breaking release.

[](#api)
API
------------

In backwards compatible releases, all changes should be either additions or modifications to internal implementation details. Most code should continue to compile and behave as expected. The exceptions to this rule are listed below.

### [](#security)
Security

Infrequently, a patch or minor update will remove or change an API in a breaking way but only if the previous API is considered insecure. These breaking changes will be noted in the changelog and release notes, and published along with a security advisory.

### [](#errors)
Errors

The specific error format and data that is included with reverts should not be assumed stable unless otherwise specified.

### [](#major_releases)
Major releases

Major releases should be assumed incompatible. Nevertheless, the external interfaces of contracts will remain compatible if they are standardized, or if the maintainers judge that changing them would cause significant strain on the ecosystem.

An important aspect that major releases may break is "upgrade compatibility", in particular storage layout compatibility. It will never be safe for a live contract to upgrade from one major release to another.

[](#storage_layout)
Storage layout
----------------------------------

Patch updates will always preserve storage layout compatibility, and after `v1.0.0` minors will too. This means that a live contract can be upgraded from one minor to another without corrupting the storage layout. In some cases it may be necessary to initialize new state variables when upgrading, although we expect this to be infrequent.

[](#cairo_version)
Cairo version
--------------------------------

The minimum Cairo version required to compile the contracts will remain unchanged for patch updates, but it may change for minors.

[← Utilities](/contracts-cairo/0.10.0/utilities)

[Contracts for Solidity →](/contracts/5.x/)




 Extensibility - OpenZeppelin Docs       

Extensibility
=============

|     |     |
| --- | --- |
|     | Expect this pattern to evolve (as it has already done) or even disappear if [proper extensibility features](https://community.starknet.io/t/contract-extensibility-pattern/210/11?u=martriay)<br> are implemented into Cairo. |

*   [The extensibility problem](#the_extensibility_problem)
    
*   [The pattern ™️](#the_pattern)
    
    *   [Libraries](#libraries)
        
    *   [Contracts](#contracts)
        
    
*   [Presets](#presets)
    
*   [Function names and coding style](#function_names_and_coding_style)
    
*   [Emulating hooks](#emulating_hooks)
    

[](#the_extensibility_problem)
The extensibility problem
--------------------------------------------------------

Smart contract development is a critical task. As with all software development, it is error prone; but unlike most scenarios, a bug can result in major losses for organizations as well as individuals. Therefore writing complex smart contracts is a delicate task.

One of the best approaches to minimize introducing bugs is to reuse existing, battle-tested code, a.k.a. using libraries. But code reutilization in StarkNet’s smart contracts is not easy:

*   Cairo has no explicit smart contract extension mechanisms such as inheritance or composability
    
*   Using imports for modularity can result in clashes (more so given that arguments are not part of the selector), and lack of overrides or aliasing leaves no way to resolve them
    
*   Any `@external` function defined in an imported module will be automatically re-exposed by the importer (i.e. the smart contract)
    

To overcome these problems, this project builds on the following guidelines™.

[](#the_pattern)
The pattern
----------------------------

The idea is to have two types of Cairo modules: libraries and contracts. Libraries define reusable logic and storage variables which can then be extended and exposed by contracts. Contracts can be deployed, libraries cannot.

To minimize risk, boilerplate, and avoid function naming clashes, we follow these rules:

### [](#libraries)
Libraries

Considering the following types of functions:

*   `private`: private to a library, not meant to be used outside the module or imported
    
*   `public`: part of the public API of a library
    
*   `internal`: subset of `public` that is either discouraged or potentially unsafe (e.g. `_transfer` on ERC20)
    
*   `external`: subset of `public` that is ready to be exported as-is by contracts (e.g. `transfer` on ERC20)
    
*   `storage`: storage variable functions
    

Then:

*   Must implement `public` and `external` functions under a namespace
    
*   Must implement `private` functions outside the namespace to avoid exposing them
    
*   Must prefix `internal` functions with an underscore (e.g. `ERC20._mint`)
    
*   Must not prefix `external` functions with an underscore (e.g. `ERC20.transfer`)
    
*   Must prefix `storage` functions with the name of the namespace to prevent clashing with other libraries (e.g. `ERC20balances`)
    
*   Must not implement any `@external`, `@view`, or `@constructor` functions
    
*   Can implement initializers (never as `@constructor` or `@external`)
    
*   Must not call initializers on any function
    

### [](#contracts)
Contracts

*   Can import from libraries
    
*   Should implement `@external` functions if needed
    
*   Should implement a `@constructor` function that calls initializers
    
*   Must not call initializers in any function beside the constructor
    

Note that since initializers will never be marked as `@external` and they won’t be called from anywhere but the constructor, there’s no risk of re-initialization after deployment. It’s up to the library developers not to make initializers interdependent to avoid weird dependency paths that may lead to double construction of libraries.

[](#presets)
Presets
--------------------

Presets are pre-written contracts that extend from our library of contracts. They can be deployed as-is or used as templates for customization.

Some presets are:

*   [Account](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/account/presets/Account.cairo)
    
*   [ERC165](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/tests/mocks/ERC165.cairo)
    
*   [ERC20Mintable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Mintable.cairo)
    
*   [ERC20Pausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Pausable.cairo)
    
*   [ERC20Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20Upgradeable.cairo)
    
*   [ERC20](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc20/presets/ERC20.cairo)
    
*   [ERC721MintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo)
    
*   [ERC721MintablePausable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/presets/ERC721MintablePausable.cairo)
    
*   [ERC721EnumerableMintableBurnable](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/token/erc721/enumerable/presets/ERC721EnumerableMintableBurnable.cairo)
    

[](#function_names_and_coding_style)
Function names and coding style
--------------------------------------------------------------------

*   Following Cairo’s programming style, we use `snake_case` for library APIs (e.g. `ERC20.transfer_from`, `ERC721.safe_transfer_from`).
    
*   But for standard EVM ecosystem compatibility, we implement external functions in contracts using `camelCase` (e.g. `transferFrom` in a ERC20 contract).
    
*   Guard functions such as the so-called "only owner" are prefixed with `assert_` (e.g. `Ownable.assert_only_owner`).
    

[](#emulating_hooks)
Emulating hooks
------------------------------------

Unlike the Solidity version of [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts)
, this library does not implement [hooks](https://docs.openzeppelin.com/contracts/4.x/extending-contracts#using-hooks)
. The main reason being that Cairo does not support overriding functions.

This is what a hook looks like in Solidity:

    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }

Instead, the extensibility pattern allows us to simply extend the library implementation of a function (namely `transfer`) by adding lines before or after calling it. This way, we can get away with:

    @external
    func transfer{
            syscall_ptr : felt*,
            pedersen_ptr : HashBuiltin*,
            range_check_ptr
        }(recipient: felt, amount: Uint256) -> (success: felt):
        Pausable.assert_not_paused()
        ERC20.transfer(recipient, amount)
        return (TRUE)
    end

[← Overview](/contracts-cairo/0.3.2/)

[Proxies and Upgrades →](/contracts-cairo/0.3.2/proxies)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides context, reasoning, and examples for methods and constants found in `tests/utils.py`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#table_of_contents)
Table of Contents
----------------------------------------

*   [Constants](#constants)
    
*   [Strings](#strings)
    
    *   [`str_to_felt`](#str_to_felt)
        
    *   [`felt_to_str`](#felt_to_str)
        
    
*   [Uint256](#uint256)
    
    *   [`uint`](#uint)
        
    *   [`to_uint`](#to_uint)
        
    *   [`from_uint`](#from_uint)
        
    *   [`add_uint`](#add_uint)
        
    *   [`sub_uint`](#sub_uint)
        
    
*   [Assertions](#assertions)
    
    *   [`assert_revert`](#assert_revert)
        
    *   [`assert_revert_entry_point`](#assert_revert_entry_point)
        
    *   [`assert_events_emitted`](#assert_event_emitted)
        
    
*   [Memoization](#memoization)
    
    *   [`get_contract_class`](#get_contract_class)
        
    *   [`cached_contract`](#cached_contract)
        
    
*   [State](#state)
    
*   [Account](#account)
    
*   [MockSigner](#mocksigner)
    

[](#constants)
Constants
------------------------

To ease the readability of Cairo contracts, this project includes reusable [constant variables](https://github.com/OpenZeppelin/cairo-contracts/blob/ad399728e6fcd5956a4ed347fb5e8ee731d37ec4/src/openzeppelin/utils/constants/library.cairo)
 like `UINT8_MAX`, or EIP165 interface IDs such as `IERC165_ID` or `IERC721_ID`. For more information on how interface ids are calculated, see the [ERC165 documentation](introspection#interface_calculations)
.

[](#strings)
Strings
--------------------

Cairo currently only provides support for short string literals (less than 32 characters). Note that short strings aren’t really strings, rather, they’re representations of Cairo field elements. The following methods provide a simple conversion to/from field elements.

### [](#str_to_felt)
`str_to_felt`

Takes an ASCII string and converts it to a field element via big endian representation.

### [](#felt_to_str)
`felt_to_str`

Takes an integer and converts it to an ASCII string by trimming the null bytes and decoding the remaining bits.

[](#uint256)
Uint256
--------------------

Cairo’s native data type is a field element (felt). Felts equate to 252 bits which poses a problem regarding 256-bit integer integration. To resolve the bit discrepancy, Cairo represents 256-bit integers as a struct of two 128-bit integers. Further, the low bits precede the high bits e.g.

    1 = (1, 0)
    1 << 128 = (0, 1)
    (1 << 128) - 1 = (340282366920938463463374607431768211455, 0)

### [](#uint)
`uint`

Converts a simple integer into a uint256-ish tuple.

> Note `to_uint` should be used in favor of `uint`, as `uint` only returns the low bits of the tuple.

### [](#to_uint)
`to_uint`

Converts an integer into a uint256-ish tuple.

    x = to_uint(340282366920938463463374607431768211456)
    print(x)
    # prints (0, 1)

### [](#from_uint)
`from_uint`

Converts a uint256-ish tuple into an integer.

    x = (0, 1)
    y = from_uint(x)
    print(y)
    # prints 340282366920938463463374607431768211456

### [](#add_uint)
`add_uint`

Performs addition between two uint256-ish tuples and returns the sum as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = add_uint(x, y)
    print(z)
    # prints (1, 1)

### [](#sub_uint)
`sub_uint`

Performs subtraction between two uint256-ish tuples and returns the difference as a uint256-ish tuple.

    x = (0, 1)
    y = (1, 0)
    z = sub_uint(x, y)
    print(z)
    # prints (340282366920938463463374607431768211455, 0)

### [](#mul_uint)
`mul_uint`

Performs multiplication between two uint256-ish tuples and returns the product as a uint256-ish tuple.

    x = (0, 10)
    y = (2, 0)
    z = mul_uint(x, y)
    print(z)
    # prints (0, 20)

### [](#div_rem_uint)
`div_rem_uint`

Performs division between two uint256-ish tuples and returns both the quotient and remainder as uint256-ish tuples respectively.

    x = (1, 100)
    y = (0, 25)
    z = div_rem_uint(x, y)
    print(z)
    # prints ((4, 0), (1, 0))

[](#assertions)
Assertions
--------------------------

In order to abstract away some of the verbosity regarding test assertions on StarkNet transactions, this project includes the following helper methods:

### [](#assert_revert)
`assert_revert`

An asynchronous wrapper method that executes a try-except pattern for transactions that should fail. Note that this wrapper does not check for a StarkNet error code. This allows for more flexibility in checking that a transaction simply failed. If you wanted to check for an exact error code, you could use StarkNet’s [error\_codes module](https://github.com/starkware-libs/cairo-lang/blob/ed6cf8d6cec50a6ad95fa36d1eb4a7f48538019e/src/starkware/starknet/definitions/error_codes.py)
 and implement additional logic to the `assert_revert` method.

To successfully use this wrapper, the transaction method should be wrapped with `assert_revert`; however, `await` should precede the wrapper itself like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    )

This wrapper also includes the option to check that an error message was included in the reversion. To check that the reversion sends the correct error message, add the `reverted_with` keyword argument outside of the actual transaction (but still inside the wrapper) like this:

    await assert_revert(signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ]),
        reverted_with="insert error message here"
    )

### [](#assert_revert_entry_point)
`assert_revert_entry_point`

An extension of `assert_revert` that asserts an entry point error occurs with the given `invalid_selector` parameter. This assertion is especially useful in checking proxy/implementation contracts. To use `assert_revert_entry_point`:

    await assert_revert_entry_point(
        signer.send_transaction(
            account, contract.contract_address, 'nonexistent_selector', []
        ),
        invalid_selector='nonexistent_selector'
    )

### [](#assert_event_emitted)
`assert_event_emitted`

A helper method that checks a transaction receipt for the contract emitting the event (`from_address`), the emitted event itself (`name`), and the arguments emitted (`data`). To use `assert_event_emitted`:

    # capture the tx receipt
    tx_exec_info = await signer.send_transaction(
        account, contract.contract_address, 'foo', [\
            recipient,\
            *token\
        ])
    
    # insert arguments to assert
    assert_event_emitted(
        tx_exec_info,
        from_address=contract.contract_address,
        name='Foo_emitted',
        data=[\
            account.contract_address,\
            recipient,\
            *token\
        ]
    )

[](#memoization)
Memoization
----------------------------

Memoizing functions allow for quicker and computationally cheaper calculations which is immensely beneficial while testing smart contracts.

### [](#get_contract_class)
`get_contract_class`

A helper method that returns the contract class from the contract’s name. To capture the contract class, simply add the contract’s name as an argument like this:

    contract_class = get_contract_class('ContractName')

If multiple contracts exist with the same name, then the contract’s path must be passed along with the `is_path` flag instead of the name. To pass the contract’s path:

    contract_class = get_contract_class('path/to/Contract.cairo', is_path=True)

### [](#cached_contract)
`cached_contract`

A helper method that returns the cached state of a given contract. It’s recommended to first deploy all the relevant contracts before caching the state. The requisite contracts in the testing module should each be instantiated with `cached_contract` in a fixture after the state has been copied. The memoization pattern with `cached_contract` should look something like this:

    # get contract classes
    @pytest.fixture(scope='module')
    def contract_classes():
      foo_cls = get_contract_class('Foo')
      return foo_cls
    
    # deploy contracts
    @pytest.fixture(scope='module')
    async def foo_init(contract_classes):
        foo_cls = contract_classes
        starknet = await Starknet.empty()
        foo = await starknet.deploy(
            contract_class=foo_cls,
            constructor_calldata=[]
        )
        return starknet.state, foo  # return state and all deployed contracts
    
    # memoization
    @pytest.fixture(scope='module')
    def foo_factory(contract_classes, foo_init):
        foo_cls = contract_classes                          # contract classes
        state, foo = foo_init                               # state and deployed contracts
        _state = state.copy()                               # copy the state
        cached_foo = cached_contract(_state, foo_cls, foo)  # cache contracts
        return cached_foo                                   # return cached contracts

[](#state)
State
----------------

The `State` class provides a wrapper for initializing the StarkNet state which acts as a helper for the `Account` class. This wrapper allows `Account` deployments to share the same initialized state without explicitly passing the instantiated StarkNet state to `Account`. Initializing the state should look like this:

    from utils import State
    
    starknet = await State.init()

[](#account)
Account
--------------------

The `Account` class abstracts away most of the boilerplate for deploying accounts. Instantiating accounts with this class requires the StarkNet state to be instantiated first with the `State.init()` method like this:

    from utils import State, Account
    
    starknet = await State.init()
    account1 = await Account.deploy(public_key)
    account2 = await Account.deploy(public_key)

The Account class also provides access to the account contract class which is useful for following the [Memoization](#memoization)
 pattern. To fetch the account contract class:

    fetch_class = Account.get_class

[](#mocksigner)
MockSigner
--------------------------

`MockSigner` is used to perform transactions with an instance of [Nile’s Signer](https://github.com/OpenZeppelin/nile/blob/main/src/nile/signer.py)
 on a given Account, crafting the transaction and managing nonces. The `Signer` instance manages signatures and is leveraged by `MockSigner` to operate with the Account contract’s `__execute__` method. See [MockSigner utility](accounts#mocksigner_utility)
 for more information.

[← Introspection](/contracts-cairo/0.3.1/introspection)

[Contracts for Solidity →](/contracts/5.x/)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides reasoning and examples for functions and constants found in `openzeppelin::utils`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#core_utilities)
Core utilities
----------------------------------

### [](#utils)
`utils`

    use openzeppelin::utils;

Module containing core utilities of the library.

Members

Functions

*   [`try_selector_with_fallback(target, selector, fallback, args)`](#utils-try_selector_with_fallback)
    

Traits

*   [`UnwrapAndCast`](#utils-UnwrapAndCast)
    

Inner modules

*   [`cryptography`](#utils-cryptography)
    
*   [`deployments`](#utils-deployments)
    
*   [`math`](#utils-math)
    
*   [`selectors`](#utils-selectors)
    
*   [`serde`](#utils-serde)
    

#### [](#utils-Functions)
Functions

#### [](#utils-try_selector_with_fallback)
`try_selector_with_fallback(target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>) → SyscallResult<Span<felt252>>` function

Tries to call a given selector on a given contract, and if it fails, tries to call a fallback selector.

It was designed for falling back to the `camelCase` selector for backward compatibility in the case of a failure of the `snake_case` selector.

Returns a `SyscallResult` with the result of the successful call.

Note that:

*   If the first call succeeds, the second call is not attempted.
    
*   If the first call fails with an error different than `ENTRYPOINT_NOT_FOUND`, the error is returned without falling back to the second selector.
    
*   If the first call fails with `ENTRYPOINT_NOT_FOUND`, the second call is attempted, and if it fails its error is returned.
    

|     |     |
| --- | --- |
|     | The fallback mechanism won’t work on live chains (mainnet or testnets) until they implement panic handling in their runtime. |

#### [](#utils-Traits)
Traits

#### [](#utils-UnwrapAndCast)
`UnwrapAndCast` trait

Trait for exposing an `unwrap_and_cast` function to `SyscallResult` objects. This may be useful when unwrapping a syscall result to a type implementing the `Serde` trait, and you want to avoid the boilerplate of casting and unwrapping the result multiple times.

Usage example:

    use openzeppelin::utils::selectors;
    use openzeppelin::utils::UnwrapAndCast;
    
    fn call_and_cast_to_bool(target: ContractAddress, args: Span<felt252>) -> bool {
        try_selector_with_fallback(
            target, selectors::has_role, selectors::hasRole, args
        ).unwrap_and_cast()
    }
    
    fn call_and_cast_to_felt252(target: ContractAddress, args: Span<felt252>) -> felt252 {
        try_selector_with_fallback(
            target, selectors::get_role_admin, selectors::getRoleAdmin, args
        ).unwrap_and_cast()
    }

Note that it can be automatically casted to any type implementing the `Serde` trait.

#### [](#utils-Inner-Modules)
Inner modules

#### [](#utils-cryptography)
`cryptography` module

See [`openzeppelin::utils::cryptography`](#cryptography)
.

#### [](#utils-deployments)
`deployments` module

See [`openzeppelin::utils::deployments`](#deployments)
.

#### [](#utils-math)
`math` module

See [`openzeppelin::utils::math`](#math)
.

#### [](#utils-selectors)
`selectors` module

See [`openzeppelin::utils::selectors`](#selectors)
.

#### [](#utils-serde)
`serde` module

See [`openzeppelin::utils::serde`](#serde)
.

### [](#cryptography)
`cryptography`

    use openzeppelin::utils::cryptography;

Module containing utilities related to cryptography.

Members

Inner modules

*   [`nonces`](#cryptography-nonces)
    
*   [`snip12`](#cryptography-snip12)
    

#### [](#inner_modules)
Inner modules

#### [](#cryptography-nonces)
`nonces` module

See [`openzeppelin::utils::cryptography::nonces::NoncesComponent`](#NoncesComponent)
.

#### [](#cryptography-snip12)
`snip12` module

See [`openzeppelin::utils::cryptography::snip12`](#snip12)
.

### [](#deployments)
`deployments`

    use openzeppelin::utils::deployments;

Module containing utility functions for calculating contract addresses through [deploy\_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
 and the [Universal Deployer Contract](../udc)
 (UDC).

Members

Structs

*   [`DeployerInfo(caller_address, udc_address)`](#deployments-DeployerInfo)
    

Functions

*   [`calculate_contract_address_from_deploy_syscall(salt, class_hash, constructor_calldata, deployer_address)`](#deployments-calculate_contract_address_from_deploy_syscall)
    
*   [`compute_hash_on_elements(data)`](#deployments-compute_hash_on_elements)
    
*   [`calculate_contract_address_from_udc(salt, class_hash, constructor_calldata, deployer_info)`](#deployments-calculate_contract_address_from_udc)
    

#### [](#deployments-Structs)
Structs

#### [](#deployments-DeployerInfo)
`DeployerInfo(caller_address: ContractAddress, udc_address: ContractAddress)` struct

Struct containing arguments necessary in [utils::calculate\_contract\_address\_from\_udc](#deployments-calculate_contract_address_from_udc)
 for origin-dependent deployment calculations.

#### [](#deployments-Functions)
Functions

#### [](#deployments-calculate_contract_address_from_deploy_syscall)
`calculate_contract_address_from_deploy_syscall(salt: felt252, class_hash: ClassHash, constructor_calldata: Span<felt252>, deployer_address: ContractAddress) → ContractAddress` function

Returns the contract address when passing the given arguments to [deploy\_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
.

#### [](#deployments-compute_hash_on_elements)
`compute_hash_on_elements(mut data: Span<felt252>) → felt252` function

Creates a Pedersen hash chain with the elements of `data` and returns the finalized hash.

#### [](#deployments-calculate_contract_address_from_udc)
`calculate_contract_address_from_udc(salt: felt252, class_hash: ClassHash, constructor_calldata: Span<felt252>, deployer_info: Option<DeployerInfo>) → ContractAddress` function

Returns the calculated contract address for UDC deployments.

Origin-independent deployments (deployed from zero) should pass `Option::None` as `deployer_info`.

Origin-dependent deployments hash `salt` with `caller_address` (member of [DeployerInfo](#deployments-DeployerInfo)
) and pass the hashed salt to the inner [deploy\_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
 as the `contract_address_salt` argument.

### [](#math)
`math`

    use openzeppelin::utils::math;

Module containing math utilities.

Members

Functions

*   [`average(a, b)`](#math-average)
    

#### [](#math-Functions)
Functions

#### [](#math-average)
`average(a: T, b: T) → T` function

Returns the average of two values. The result is rounded down.

|     |     |
| --- | --- |
|     | `T` is a generic value matching different numeric implementations. |

### [](#selectors)
`selectors`

    use openzeppelin::utils::selectors;

Module containing constants matching multiple selectors used through the library. To see the full list of selectors, see [selectors.cairo](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/utils/selectors.cairo)
.

### [](#serde)
`serde`

    use openzeppelin::utils::serde;

Module containing utilities related to serialization and deserialization of Cairo data structures.

Members

Traits

*   [`SerializedAppend`](#serde-SerializedAppend)
    

#### [](#serde-Traits)
Traits

#### [](#serde-SerializedAppend)
`SerializedAppend` trait

Importing this trait allows the ability to append a serialized representation of a Cairo data structure already implementing the `Serde` trait to a `felt252` buffer.

Usage example:

    use openzeppelin::utils::serde::SerializedAppend;
    use starknet::ContractAddress;
    
    fn to_calldata(recipient: ContractAddress, amount: u256) -> Array<felt252> {
        let mut calldata = array![];
        calldata.append_serde(recipient);
        calldata.append_serde(amount);
        calldata
    }

Note that the `append_serde` method is automatically available for arrays of felts, and it accepts any data structure that implements the `Serde` trait.

[](#cryptography_2)
Cryptography
--------------------------------

### [](#NoncesComponent)
`NoncesComponent`

    use openzeppelin::utils::cryptography::nonces::NoncesComponent;

Simple component for managing nonces.

Embeddable Implementations

NoncesImpl

*   [`nonces(self, owner)`](#NoncesComponent-nonces)
    

Internal Implementations

InternalImpl

*   [`use_nonce(self, owner)`](#NoncesComponent-use_nonce)
    
*   [`use_checked_nonce(self, owner, nonce)`](#NoncesComponent-use_checked_nonce)
    

#### [](#NoncesComponent-Embeddable-Functions)
Embeddable functions

#### [](#NoncesComponent-nonces)
`nonces(self: @ContractState, owner: ContractAddress) → felt252` external

Returns the next unused nonce for an `owner`.

#### [](#NoncesComponent-Internal-Functions)
Internal functions

#### [](#NoncesComponent-use_nonce)
`use_nonce(ref self: ComponentState, owner: ContractAddress) → felt252` internal

Consumes a nonce, returns the current value, and increments nonce.

For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be decremented or reset. This guarantees that the nonce never overflows.

#### [](#NoncesComponent-use_checked_nonce)
`use_checked_nonce(ref self: ComponentState, owner: ContractAddress, nonce: felt252) → felt252` internal

Same as `use_nonce` but checking that `nonce` is the next valid one for `owner`.

### [](#snip12)
`snip12`

    use openzeppelin::utils::snip12;

Supports on-chain generation of message hashes compliant with [SNIP12](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md)
.

|     |     |
| --- | --- |
|     | For a full walkthrough on how to use this module, see the [SNIP12 and Typed Messages](../guides/snip12)<br> guide. |

[← API Reference](/contracts-cairo/0.15.0/api/upgrades)

[Test Utilities →](/contracts-cairo/0.15.0/api/testing)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides reasoning and examples for functions and constants found in `openzeppelin::utils` and `openzeppelin::tests::utils`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#core_utilities)
Core utilities
----------------------------------

### [](#utils)
`utils`

    use openzeppelin::utils;

Module containing core utilities of the library.

Members

Functions

*   [`try_selector_with_fallback(target, selector, fallback, args)`](#utils-try_selector_with_fallback)
    

Traits

*   [`UnwrapAndCast`](#utils-UnwrapAndCast)
    

Inner modules

*   [`cryptography`](#utils-cryptography)
    
*   [`deployments`](#utils-deployments)
    
*   [`math`](#utils-math)
    
*   [`selectors`](#utils-selectors)
    
*   [`serde`](#utils-serde)
    

#### [](#utils-Functions)
Functions

#### [](#utils-try_selector_with_fallback)
`try_selector_with_fallback(target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>) → SyscallResult<Span<felt252>>` function

Tries to call a given selector on a given contract, and if it fails, tries to call a fallback selector.

It was designed for falling back to the `camelCase` selector for backward compatibility in the case of a failure of the `snake_case` selector.

Returns a `SyscallResult` with the result of the successful call.

Note that:

*   If the first call succeeds, the second call is not attempted.
    
*   If the first call fails with an error different than `ENTRYPOINT_NOT_FOUND`, the error is returned without falling back to the second selector.
    
*   If the first call fails with `ENTRYPOINT_NOT_FOUND`, the second call is attempted, and if it fails its error is returned.
    

|     |     |
| --- | --- |
|     | The fallback mechanism won’t work on live chains (mainnet or testnets) until they implement panic handling in their runtime. |

#### [](#utils-Traits)
Traits

#### [](#utils-UnwrapAndCast)
`UnwrapAndCast` trait

Trait for exposing an `unwrap_and_cast` function to `SyscallResult` objects. This may be useful when unwrapping a syscall result to a type implementing the `Serde` trait, and you want to avoid the boilerplate of casting and unwrapping the result multiple times.

Usage example:

    use openzeppelin::utils::selectors;
    use openzeppelin::utils::UnwrapAndCast;
    
    fn call_and_cast_to_bool(target: ContractAddress, args: Span<felt252>) -> bool {
        try_selector_with_fallback(
            target, selectors::has_role, selectors::hasRole, args
        ).unwrap_and_cast()
    }
    
    fn call_and_cast_to_felt252(target: ContractAddress, args: Span<felt252>) -> felt252 {
        try_selector_with_fallback(
            target, selectors::get_role_admin, selectors::getRoleAdmin, args
        ).unwrap_and_cast()
    }

Note that it can be automatically casted to any type implementing the `Serde` trait.

#### [](#utils-Inner-Modules)
Inner modules

#### [](#utils-cryptography)
`cryptography` module

See [`openzeppelin::utils::cryptography`](#cryptography)
.

#### [](#utils-deployments)
`deployments` module

See [`openzeppelin::utils::deployments`](#deployments)
.

#### [](#utils-math)
`math` module

See [`openzeppelin::utils::math`](#math)
.

#### [](#utils-selectors)
`selectors` module

See [`openzeppelin::utils::selectors`](#selectors)
.

#### [](#utils-serde)
`serde` module

See [`openzeppelin::utils::serde`](#serde)
.

### [](#cryptography)
`cryptography`

    use openzeppelin::utils::cryptography;

Module containing utilities related to cryptography.

Members

Inner modules

*   [`nonces`](#cryptography-nonces)
    
*   [`snip12`](#cryptography-snip12)
    

#### [](#inner_modules)
Inner modules

#### [](#cryptography-nonces)
`nonces` module

See [`openzeppelin::utils::cryptography::nonces::NoncesComponent`](#NoncesComponent)
.

#### [](#cryptography-snip12)
`snip12` module

See [`openzeppelin::utils::cryptography::snip12`](#snip12)
.

### [](#deployments)
`deployments`

    use openzeppelin::utils::deployments;

Module containing utility functions for calculating contract addresses through [deploy\_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
 and the [Universal Deployer Contract](../udc)
 (UDC).

Members

Structs

*   [`DeployerInfo(caller_address, udc_address)`](#deployments-DeployerInfo)
    

Functions

*   [`calculate_contract_address_from_deploy_syscall(salt, class_hash, constructor_calldata, deployer_address)`](#deployments-calculate_contract_address_from_deploy_syscall)
    
*   [`compute_hash_on_elements(data)`](#deployments-compute_hash_on_elements)
    
*   [`calculate_contract_address_from_udc(salt, class_hash, constructor_calldata, deployer_info)`](#deployments-calculate_contract_address_from_udc)
    

#### [](#deployments-Structs)
Structs

#### [](#deployments-DeployerInfo)
`DeployerInfo(caller_address: ContractAddress, udc_address: ContractAddress)` struct

Struct containing arguments necessary in [utils::calculate\_contract\_address\_from\_udc](#deployments-calculate_contract_address_from_udc)
 for origin-dependent deployment calculations.

#### [](#deployments-Functions)
Functions

#### [](#deployments-calculate_contract_address_from_deploy_syscall)
`calculate_contract_address_from_deploy_syscall(salt: felt252, class_hash: ClassHash, constructor_calldata: Span<felt252>, deployer_address: ContractAddress) → ContractAddress` function

Returns the contract address when passing the given arguments to [deploy\_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
.

#### [](#deployments-compute_hash_on_elements)
`compute_hash_on_elements(mut data: Span<felt252>) → felt252` function

Creates a Pedersen hash chain with the elements of `data` and returns the finalized hash.

#### [](#deployments-calculate_contract_address_from_udc)
`calculate_contract_address_from_udc(salt: felt252, class_hash: ClassHash, constructor_calldata: Span<felt252>, deployer_info: Option<DeployerInfo>) → ContractAddress` function

Returns the calculated contract address for UDC deployments.

Origin-independent deployments (deployed from zero) should pass `Option::None` as `deployer_info`.

Origin-dependent deployments hash `salt` with `caller_address` (member of [DeployerInfo](#deployments-DeployerInfo)
) and pass the hashed salt to the inner [deploy\_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
 as the `contract_address_salt` argument.

### [](#math)
`math`

    use openzeppelin::utils::math;

Module containing math utilities.

Members

Functions

*   [`average(a, b)`](#math-average)
    

#### [](#math-Functions)
Functions

#### [](#math-average)
`average(a: T, b: T) → T` function

Returns the average of two values. The result is rounded down.

|     |     |
| --- | --- |
|     | `T` is a generic value matching different numeric implementations. |

### [](#selectors)
`selectors`

    use openzeppelin::utils::selectors;

Module containing constants matching multiple selectors used through the library. To see the full list of selectors, see [selectors.cairo](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/utils/selectors.cairo)
.

### [](#serde)
`serde`

    use openzeppelin::utils::serde;

Module containing utilities related to serialization and deserialization of Cairo data structures.

Members

Traits

*   [`SerializedAppend`](#serde-SerializedAppend)
    

#### [](#serde-Traits)
Traits

#### [](#serde-SerializedAppend)
`SerializedAppend` trait

Importing this trait allows the ability to append a serialized representation of a Cairo data structure already implementing the `Serde` trait to a `felt252` buffer.

Usage example:

    use openzeppelin::utils::serde::SerializedAppend;
    use starknet::ContractAddress;
    
    fn to_calldata(recipient: ContractAddress, amount: u256) -> Array<felt252> {
        let mut calldata = array![];
        calldata.append_serde(recipient);
        calldata.append_serde(amount);
        calldata
    }

Note that the `append_serde` method is automatically available for arrays of felts, and it accepts any data structure that implements the `Serde` trait.

[](#cryptography_2)
Cryptography
--------------------------------

### [](#NoncesComponent)
`NoncesComponent`

    use openzeppelin::utils::cryptography::nonces::NoncesComponent;

Simple component for managing nonces.

Embeddable Implementations

NoncesImpl

*   [`nonces(self, owner)`](#NoncesComponent-nonces)
    

Internal Implementations

InternalImpl

*   [`use_nonce(self, owner)`](#NoncesComponent-use_nonce)
    
*   [`use_checked_nonce(self, owner, nonce)`](#NoncesComponent-use_checked_nonce)
    

#### [](#NoncesComponent-Embeddable-Functions)
Embeddable functions

#### [](#NoncesComponent-nonces)
`nonces(self: @ContractState, owner: ContractAddress) → felt252` external

Returns the next unused nonce for an `owner`.

#### [](#NoncesComponent-Internal-Functions)
Internal functions

#### [](#NoncesComponent-use_nonce)
`use_nonce(ref self: ComponentState, owner: ContractAddress) → felt252` internal

Consumes a nonce, returns the current value, and increments nonce.

For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be decremented or reset. This guarantees that the nonce never overflows.

#### [](#NoncesComponent-use_checked_nonce)
`use_checked_nonce(ref self: ComponentState, owner: ContractAddress, nonce: felt252) → felt252` internal

Same as `use_nonce` but checking that `nonce` is the next valid one for `owner`.

### [](#snip12)
`snip12`

    use openzeppelin::utils::snip12;

Supports on-chain generation of message hashes compliant with [SNIP12](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md)
.

|     |     |
| --- | --- |
|     | For a full walkthrough on how to use this module, see the [SNIP12 and Typed Messages](../guides/snip12)<br> guide. |

[](#test_utilities)
Test utilities
----------------------------------

### [](#testutils)
`utils`

    use openzeppelin::tests::utils;

Module containing utilities for testing the library.

Members

Functions

*   [`deploy(contract_class_hash, calldata)`](#testutils-deploy)
    
*   [`deploy_with_salt(contract_class_hash, calldata, salt)`](#testutils-deploy_with_salt)
    
*   [`pop_log<T>(address)`](#testutils-pop_log)
    
*   [`assert_indexed_keys<T>(event, expected_keys)`](#testutils-assert_indexed_keys)
    
*   [`assert_no_events_left(address)`](#testutils-assert_no_events_left)
    
*   [`drop_event(address)`](#testutils-drop_event)
    
*   [`drop_events(address, n_events)`](#testutils-drop_events)
    

Inner modules

*   [`constants`](#testutils-constants)
    

#### [](#testutils-Functions)
Functions

#### [](#testutils-deploy)
`deploy(contract_class_hash: felt252, calldata: Array<felt252>) → ContractAddress` function

Uses the `[deploy_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy) ` to deploy an instance of the contract given the class hash and the calldata.

The `contract_address_salt` is always set to zero, and `deploy_from_zero` is set to false.

Usage example:

    use openzeppelin::presets::AccountUpgradeable;
    use openzeppelin::tests::utils;
    use starknet::ContractAddress;
    
    const PUBKEY: felt252 = 'PUBKEY';
    
    fn deploy_test_contract() -> ContractAddress {
        let calldata = array![PUBKEY];
        utils::deploy(AccountUpgradeable::TEST_CLASS_HASH, calldata)
    }

#### [](#testutils-deploy_with_salt)
`deploy_with_salt(contract_class_hash: felt252, calldata: Array<felt252>, salt: felt252) → ContractAddress` function

Same as [utils::deploy](#testutils-deploy)
 except this function accepts a `salt` argument. This utility is useful when tests require multiple deployed instances of the same contract.

#### [](#testutils-pop_log)
`pop_log<T>(address: ContractAddress) → Option<T>` function

Pops the earliest unpopped logged event for the contract as the requested type and checks that there’s no more keys or data left on the event, preventing unaccounted params.

Required traits for `T`:

*   `Drop`
    
*   `starknet::Event`
    

Requirements:

*   No extra data or keys are left on the raw event after deserialization.
    

Usage example:

    use openzeppelin::tests::utils;
    use openzeppelin::token::erc20::ERC20Component;
    use openzeppelin::token::erc20::ERC20Component::Transfer;
    use starknet::ContractAddress;
    
    fn assert_emitted_event(
        target: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256
    ) {
        let event = utils::pop_log::<ERC20Component::Event>(target).unwrap();
        let expected = ERC20Component::Event::Transfer(Transfer { from, to, value });
        assert!(event == expected);
    }

#### [](#testutils-assert_indexed_keys)
`assert_indexed_keys<T>(event: T, expected_keys: Span<felt252>)` function

Asserts that `expected_keys` exactly matches the indexed keys from `event`.

`expected_keys` must include all indexed event keys for `event` in the order that they’re defined.

|     |     |
| --- | --- |
|     | If the event is not flattened, the first key will be the event member name e.g. `selector!("EnumMemberName")`. |

Required traits for `T`:

*   `Drop`
    
*   `starknet::Event`
    

#### [](#testutils-assert_no_events_left)
`assert_no_events_left(address: ContractAddress)` function

Asserts that there are no more events left in the queue for the given address.

#### [](#testutils-drop_event)
`drop_event(address: ContractAddress)` function

Removes an event from the queue for the given address.

If the queue is empty, this function won’t do anything.

#### [](#testutils-drop_events)
`drop_events(address: ContractAddress, n_events: felt252)` function

Removes `n_events` from the queue for the given address.

If the queue is empty, this function won’t do anything.

#### [](#testutils-Inner-Modules)
Inner modules

#### [](#testutils-constants)
`constants` module

See [`openzeppelin::tests::utils::constants`](#constants)
.

### [](#constants)
`constants`

    use openzeppelin::tests::utils::constants;

Module containing constants that are repeatedly used among tests. To see the full list, see [constants.cairo](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/tests/utils/constants.cairo)
.

[← API Reference](/contracts-cairo/0.13.0/api/upgrades)

[Backwards Compatibility →](/contracts-cairo/0.13.0/backwards-compatibility)




 Testing - OpenZeppelin Docs       

Testing
=======

This module provides various helper functions for declaring, deploying, and testing Smart Contracts using `snforge` toolchain from Starknet Foundry.

    use openzeppelin_testing;

The module isn’t part of the `openzeppelin` package and to be accessible has to be added as a separate dependency in `Scarb.toml`:

    [dev-dependencies]
    openzeppelin_testing = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.15.0" }

[](#test_utilities)
Test Utilities
----------------------------------

### [](#testing-common)
`common`

A module providing common test helpers.

    use openzeppelin_testing::common;

Members

Functions

*   [`panic_data_to_byte_array(panic_data)`](#testing-common-panic_data_to_byte_array)
    
*   [`to_base_16_string(value)`](#testing-common-to_base_16_string)
    
*   [`assert_entrypoint_not_found_error(result, selector, contract_address)`](#testing-common-assert_entrypoint_not_found_error)
    

Traits

*   [`IntoBase16StringTrait`](#testing-common-IntoBase16StringTrait)
    

#### [](#testing-common-Functions)
Functions

#### [](#testing-common-panic_data_to_byte_array)
`panic_data_to_byte_array(panic_data: Array<felt252>) → ByteArray` function

Converts panic data into a string (`ByteArray`).

`panic_data` is expected to be a valid serialized `ByteArray` with an extra `felt252` at the beginning, which is the BYTE\_ARRAY\_MAGIC.

#### [](#testing-common-to_base_16_string)
`to_base_16_string(value: felt252) → ByteArray` function

Converts a `felt252` to a `base16` string padded to 66 characters (including the `0x` prefix).

#### [](#testing-common-assert_entrypoint_not_found_error)
`assert_entrypoint_not_found_error<T, +Drop<T>>(result: SyscallResult<T>, selector: felt252, contract_address: ContractAddress)` function

Asserts that the syscall result of a call failed with an "Entrypoint not found" error, following the Starknet Foundry emitted error format.

#### [](#testing-common-Traits)
Traits

#### [](#testing-common-IntoBase16StringTrait)
`IntoBase16StringTrait` trait

A helper trait that enables a value to be represented as a `base16` string padded to 66 characters (including the `0x` prefix). The type of the value must implement `Into<T, felt252>` to be convertible to `felt252`.

Usage example:

    use openzeppelin_testing::common::IntoBase16String;
    
    let expected_panic_message = format!(
        "Entry point selector {} not found in contract {}",
        selector.into_base_16_string(),
        contract_address.into_base_16_string()
    );

### [](#testing-deployment)
`deployment`

    use openzeppelin_testing::deployment;

A module containing utilities that simplify declaring and deploying contracts using the `snforge` toolchain.

Members

Functions

*   [`declare_class(contract_name)`](#testing-deployment-declare_class)
    
*   [`deploy(contract_class, calldata)`](#testing-deployment-deploy)
    
*   [`deploy_at(contract_class, contract_address, calldata)`](#testing-deployment-deploy_at)
    
*   [`deploy_another_at(existing, target_address, calldata)`](#testing-deployment-deploy_another_at)
    
*   [`declare_and_deploy(contract_name, calldata)`](#testing-deployment-declare_and_deploy)
    
*   [`declare_and_deploy_at(contract_name, target_address, calldata)`](#testing-deployment-declare_and_deploy_at)
    

#### [](#testing-deployment-Functions)
Functions

#### [](#testing-deployment-declare_class)
`declare_class(contract_name: ByteArray) → ContractClass` function

Declares a contract with a `snforge` `declare` call and unwraps the result.

#### [](#testing-deployment-deploy)
`deploy(contract_class: ContractClass, calldata: Array<felt252>) → ContractAddress` function

Deploys an instance of a contract and unwraps the result.

#### [](#testing-deployment-deploy_at)
`deploy_at(contract_class: ContractClass, target_address: ContractAddress, calldata: Array<felt252>)` function

Deploys an instance of a contract at a given address.

#### [](#testing-deployment-deploy_another_at)
`deploy_another_at(existing: ContractAddress, target_address: ContractAddress, calldata: Array<felt252>)` function

Deploys a contract using the class hash from another already-deployed contract.

Note that currently, `snforge` does not support redeclaring a contract class. Consequently, there is no direct method to deploy a second instance of a contract if neither its `ContractClass` nor its `class_hash` is available in the context. This helper function provides a solution by retrieving the class hash from an existing contract and using it to facilitate the deployment.

    use openzeppelin_testing::deploy_another_at;
    
    let alice_address = setup_account(array!['ALICE_PUBKEY']);
    let bob_address = contract_address_const::<'BOB'>();
    deploy_another_at(alice_address, bob_address, array!['BOB_PUBKEY']);

#### [](#testing-deployment-declare_and_deploy)
`declare_and_deploy(contract_name: ByteArray, calldata: Array<felt252>) → ContractAddress` function

Combines the declaration of a class and the deployment of a contract into one function call.

#### [](#testing-deployment-declare_and_deploy_at)
`declare_and_deploy_at(contract_name: ByteArray, target_address: ContractAddress, calldata: Array<felt252>)` function

Combines the declaration of a class and the deployment of a contract at the given address into one function call.

### [](#testing-events)
`events`

    use openzeppelin_testing::events;
    use openzeppelin_testing::events::EventSpyExt;

A module offering an extended set of functions for handling emitted events, enhancing the default event utilities provided by `snforge`. These functions are accessible via the `EventSpyExt` trait implemented on the `EventSpy` struct.

Members

Functions

*   [`assert_only_event(self, from_address, event)`](#testing-events-assert_only_event)
    
*   [`assert_emitted_single(self, from_address, expected_event)`](#testing-events-assert_emitted_single)
    
*   [`drop_event(self)`](#testing-events-drop_event)
    
*   [`drop_n_events(self, number_to_drop)`](#testing-events-drop_n_events)
    
*   [`drop_all_events(self)`](#testing-events-drop_all_events)
    
*   [`assert_no_events_left(self)`](#testing-events-assert_no_events_left)
    
*   [`assert_no_events_left_from(self, from_address)`](#testing-events-assert_no_events_left_from)
    
*   [`count_events_from(self, from_address)`](#testing-events-count_events_from)
    

#### [](#testing-events-Functions)
Functions

#### [](#testing-events-assert_only_event)
`assert_only_event<T, +starknet::Event<T>, +Drop<T>>(ref self: EventSpy, from_address: ContractAddress, expected_event: T)` function

Ensures that `from_address` has emitted only the `expected_event` and no additional events.

#### [](#testing-events-assert_emitted_single)
`assert_emitted_single<T, +starknet::Event<T>, +Drop<T>>(ref self: EventSpy, from_address: ContractAddress, expected_event: T)` function

Ensures that `from_address` has emitted the `expected_event`.

#### [](#testing-events-drop_event)
`drop_event(ref self: EventSpy)` function

Removes a single event from the queue. If the queue is empty, the function will panic.

#### [](#testing-events-drop_n_events)
`drop_n_events(ref self: EventSpy, number_to_drop: u32)` function

Removes `number_to_drop` events from the queue. If the queue is empty, the function will panic.

#### [](#testing-events-drop_all_events)
`drop_all_events(ref self: EventSpy)` function

Removes all events remaining on the queue. If the queue is empty already, the function will do nothing.

#### [](#testing-events-assert_no_events_left)
`assert_no_events_left(ref self: EventSpy)` function

Ensures that there are no events remaining on the queue.

#### [](#testing-events-assert_no_events_left_from)
`assert_no_events_left_from(ref self: EventSpy, from_address: ContractAddress)` function

Ensures that there are no events emitted from the given address remaining on the queue.

#### [](#testing-events-count_events_from)
`count_events_from(ref self: EventSpy, from_address: ContractAddress) → u32` function

Counts the number of remaining events emitted from the given address.

### [](#testing-signing)
`signing`

    use openzeppelin_testing::signing;

A module offering utility functions for easier management of key pairs and signatures.

Members

Functions

*   [`get_stark_keys_from(private_key)`](#testing-signing-get_stark_keys_from)
    
*   [`get_secp256k1_keys_from(private_key)`](#testing-signing-get_secp256k1_keys_from)
    

Traits

*   [`SerializedSigning`](#testing-signing-SerializedSigning)
    

#### [](#testing-signing-Functions)
Functions

#### [](#testing-signing-get_stark_keys_from)
`get_stark_keys_from(private_key: felt252) → StarkKeyPair` function

Builds a [Stark](https://docs.starknet.io/architecture-and-concepts/cryptography/stark-curve/)
 key pair from a private key represented by a `felt252` value.

#### [](#testing-signing-get_secp256k1_keys_from)
`get_secp256k1_keys_from(private_key: u256) → Secp256k1KeyPair` function

Builds a [Secp256k1](https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/secp256k1.cairo)
 key pair from a private key represented by a `u256` value.

#### [](#testing-signing-Traits)
Traits

#### [](#testing-signing-SerializedSigning)
`SerializedSigning` trait

A helper trait that facilitates signing and converting the result signature into a serialized format.

Usage example:

    use openzeppelin_testing::signing::{
        StarkKeyPair, get_stark_keys_from, StarkSerializedSigning
    };
    
    let key_pair = get_stark_keys_from('SECRET_KEY');
    let serialized_signature = key_pair.serialized_sign('TX_HASH');

[← Utilities](/contracts-cairo/0.15.0/api/utilities)

[Backwards Compatibility →](/contracts-cairo/0.15.0/backwards-compatibility)




 Backwards Compatibility - OpenZeppelin Docs       

Backwards Compatibility
=======================

OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. Patch and minor updates will generally be backwards compatible, with rare exceptions as detailed below. Major updates should be assumed incompatible with previous releases. On this page, we provide details about these guarantees.

Bear in mind that while releasing versions under `v1.0.0`, we treat minors as majors and patches as minors, in accordance with semantic versioning. This means that `v0.7.1` could be adding features to `v0.7.0`, while `v0.8.0` would be considered a breaking release.

[](#api)
API
------------

In backwards compatible releases, all changes should be either additions or modifications to internal implementation details. Most code should continue to compile and behave as expected. The exceptions to this rule are listed below.

### [](#security)
Security

Infrequently, a patch or minor update will remove or change an API in a breaking way but only if the previous API is considered insecure. These breaking changes will be noted in the changelog and release notes, and published along with a security advisory.

### [](#errors)
Errors

The specific error format and data that is included with reverts should not be assumed stable unless otherwise specified.

### [](#major_releases)
Major releases

Major releases should be assumed incompatible. Nevertheless, the external interfaces of contracts will remain compatible if they are standardized, or if the maintainers judge that changing them would cause significant strain on the ecosystem.

An important aspect that major releases may break is "upgrade compatibility", in particular storage layout compatibility. It will never be safe for a live contract to upgrade from one major release to another.

[](#storage_layout)
Storage layout
----------------------------------

Patch updates will always preserve storage layout compatibility, and after `v1.0.0` minors will too. This means that a live contract can be upgraded from one minor to another without corrupting the storage layout. In some cases it may be necessary to initialize new state variables when upgrading, although we expect this to be infrequent.

[](#cairo_version)
Cairo version
--------------------------------

The minimum Cairo version required to compile the contracts will remain unchanged for patch updates, but it may change for minors.

[← Utilities](/contracts-cairo/0.13.0/api/utilities)

[Contracts for Solidity →](/contracts/5.x/)




 Backwards Compatibility - OpenZeppelin Docs       

Backwards Compatibility
=======================

OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. Patch and minor updates will generally be backwards compatible, with rare exceptions as detailed below. Major updates should be assumed incompatible with previous releases. On this page, we provide details about these guarantees.

Bear in mind that while releasing versions under `v1.0.0`, we treat minors as majors and patches as minors, in accordance with semantic versioning. This means that `v0.7.1` could be adding features to `v0.7.0`, while `v0.8.0` would be considered a breaking release.

[](#api)
API
------------

In backwards compatible releases, all changes should be either additions or modifications to internal implementation details. Most code should continue to compile and behave as expected. The exceptions to this rule are listed below.

### [](#security)
Security

Infrequently, a patch or minor update will remove or change an API in a breaking way but only if the previous API is considered insecure. These breaking changes will be noted in the changelog and release notes, and published along with a security advisory.

### [](#errors)
Errors

The specific error format and data that is included with reverts should not be assumed stable unless otherwise specified.

### [](#major_releases)
Major releases

Major releases should be assumed incompatible. Nevertheless, the external interfaces of contracts will remain compatible if they are standardized, or if the maintainers judge that changing them would cause significant strain on the ecosystem.

An important aspect that major releases may break is "upgrade compatibility", in particular storage layout compatibility. It will never be safe for a live contract to upgrade from one major release to another.

[](#storage_layout)
Storage layout
----------------------------------

Patch updates will always preserve storage layout compatibility, and after `v1.0.0` minors will too. This means that a live contract can be upgraded from one minor to another without corrupting the storage layout. In some cases it may be necessary to initialize new state variables when upgrading, although we expect this to be infrequent.

[](#cairo_version)
Cairo version
--------------------------------

The minimum Cairo version required to compile the contracts will remain unchanged for patch updates, but it may change for minors.

[← Test Utilities](/contracts-cairo/0.15.0/api/testing)

[Contracts for Solidity →](/contracts/5.x/)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

In different blockchains, multiple patterns have been developed for making a contract upgradeable including the widely adopted proxy patterns.

Starknet has native upgradeability through a syscall that updates the contract source code, removing [the need for proxies](#proxies_in_starknet)
.

|     |     |
| --- | --- |
|     | Make sure you follow [our security recommendations](#security)<br> before upgrading. |

[](#replacing_contract_classes)
Replacing contract classes
----------------------------------------------------------

To better comprehend how upgradeability works in Starknet, it’s important to understand the difference between a contract and its contract class.

[Contract Classes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-classes/)
 represent the source code of a program. All contracts are associated to a class, and many contracts can be instances of the same one. Classes are usually represented by a [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
, and before a contract of a class can be deployed, the class hash needs to be declared.

### [](#replace_class_syscall)
`replace_class_syscall`

The `[replace_class](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#replace_class) ` syscall allows a contract to update its source code by replacing its class hash once deployed.

    /// Upgrades the contract source code to the new contract class.
    fn _upgrade(new_class_hash: ClassHash) {
        assert(!new_class_hash.is_zero(), 'Class hash cannot be zero');
        starknet::replace_class_syscall(new_class_hash).unwrap_syscall();
    }

|     |     |
| --- | --- |
|     | If a contract is deployed without this mechanism, its class hash can still be replaced through [library calls](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#library_call)<br>. |

[](#upgradeable_component)
`Upgradeable` component
--------------------------------------------------

OpenZeppelin Contracts for Cairo provides [Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/upgrades/upgradeable.cairo)
 to add upgradeability support to your contracts.

### [](#usage)
Usage

Upgrades are often very sensitive operations, and some form of access control is usually required to avoid unauthorized upgrades. The [Ownable](access#ownership_and_ownable)
 module is used in this example.

|     |     |
| --- | --- |
|     | We will be using the following module to implement the [IUpgradeable](api/upgrades#IUpgradeable)<br> interface described in the API Reference section. |

    #[starknet::contract]
    mod UpgradeableContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use openzeppelin::upgrades::UpgradeableComponent;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::ClassHash;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
        component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
    
        /// Ownable
        #[abi(embed_v0)]
        impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
        impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        /// Upgradeable
        impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage,
            #[substorage(v0)]
            upgradeable: UpgradeableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event,
            #[flat]
            UpgradeableEvent: UpgradeableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            self.ownable.initializer(owner);
        }
    
        #[external(v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                // This function can only be called by the owner
                self.ownable.assert_only_owner();
    
                // Replace the class hash upgrading the contract
                self.upgradeable._upgrade(new_class_hash);
            }
        }
    }

[](#security)
Security
----------------------

Upgrades can be very sensitive operations, and security should always be top of mind while performing one. Please make sure you thoroughly review the changes and their consequences before upgrading. Some aspects to consider are:

*   API changes that might affect integration. For example, changing an external function’s arguments might break existing contracts or offchain systems calling your contract.
    
*   Storage changes that might result in lost data (e.g. changing a storage slot name, making existing storage inaccessible).
    
*   Collisions (e.g. mistakenly reusing the same storage slot from another component) are also possible, although less likely if best practices are followed, for example prepending storage variables with the component’s name (e.g. `ERC20_balances`).
    
*   Always check for [backwards compatibility](backwards-compatibility)
     before upgrading between versions of OpenZeppelin Contracts.
    

[](#proxies_in_starknet)
Proxies in Starknet
--------------------------------------------

Proxies enable different patterns such as upgrades and clones. But since Starknet achieves the same in different ways is that there’s no support to implement them.

In the case of contract upgrades, it is achieved by simply changing the contract’s class hash. As of clones, contracts already are like clones of the class they implement.

Implementing a proxy pattern in Starknet has an important limitation: there is no fallback mechanism to be used for redirecting every potential function call to the implementation. This means that a generic proxy contract can’t be implemented. Instead, a limited proxy contract can implement specific functions that forward their execution to another contract class. This can still be useful for example to upgrade the logic of some functions.

[← API Reference](/contracts-cairo/0.10.0/api/erc1155)

[API Reference →](/contracts-cairo/0.10.0/api/upgrades)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

Reference of interfaces, presets, and utilities related to ERC1155 contracts.

|     |     |
| --- | --- |
|     | For an overview of ERC1155, read our [ERC1155 guide](../erc1155)<br>. |

[](#core)
Core
--------------

### [](#IERC1155)
`IERC1155`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc1155/interface.cairo)

    use openzeppelin::token::erc1155::interface::IERC1155;

Interface of the IERC1155 standard as defined in [EIP1155](https://eips.ethereum.org/EIPS/eip-1155)
.

[SRC5 ID](introspection#ISRC5)

0x6114a8f75559e1b39fcba08ce02961a1aa082d9256a158dd3e64964e4b1b52

Functions

*   [`balance_of(account, token_id)`](#IERC1155-balance_of)
    
*   [`balance_of_batch(accounts, token_ids)`](#IERC1155-balance_of_batch)
    
*   [`safe_transfer_from(from, to, token_id, value, data)`](#IERC1155-safe_transfer_from)
    
*   [`safe_batch_transfer_from(from, to, token_ids, values, data)`](#IERC1155-safe_batch_transfer_from)
    
*   [`set_approval_for_all(operator, approved)`](#IERC1155-set_approval_for_all)
    
*   [`is_approved_for_all(owner, operator)`](#IERC1155-is_approved_for_all)
    

Events

*   [`TransferSingle(operator, from, to, id, value)`](#IERC1155-TransferSingle)
    
*   [`TransferBatch(operator, from, to, ids, values)`](#IERC1155-TransferBatch)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC1155-ApprovalForAll)
    
*   [`URI(value, id)`](#IERC1155-URI)
    

#### [](#functions)
Functions

#### [](#IERC1155-balance_of)
`balance_of(account: ContractAddress, token_id: u256) → u256` external

Returns the amount of `token_id` tokens owned by `account`.

#### [](#IERC1155-balance_of_batch)
`balance_of_batch(accounts: Span<ContractAddress>, token_ids: Span<u256>) → Span<u256>` external

Returns a list of balances derived from the `accounts` and `token_ids` pairs.

#### [](#IERC1155-safe_transfer_from)
`safe_transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256, value: u256, data: Span<felt252>)` external

Transfers ownership of `value` amount of `token_id` from `from` if `to` is either `IERC1155Receiver` or an account.

`data` is additional data, it has no specified format and it is passed to `to`.

Emits a [TransferSingle](#IERC1155-TransferSingle)
 event.

#### [](#IERC1155-safe_batch_transfer_from)
`safe_batch_transfer_from(from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` external

Transfers ownership of `token_ids` and `values` pairs from `from` if `to` is either `IERC1155Receiver` or an account.

`data` is additional data, it has no specified format and it is passed to `to`.

Emits a [TransferBatch](#IERC1155-TransferBatch)
 event.

#### [](#IERC1155-set_approval_for_all)
`set_approval_for_all(operator: ContractAddress, approved: bool)` external

Enables or disables approval for `operator` to manage all of the caller’s assets.

Emits an [ApprovalForAll](#IERC1155-ApprovalForAll)
 event.

#### [](#IERC1155-is_approved_for_all)
`is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool` external

Queries if `operator` is an authorized operator for `owner`.

#### [](#events)
Events

#### [](#IERC1155-TransferSingle)
`TransferSingle(operator: ContractAddress, from: ContractAddress, to: ContractAddress, id: u256, value: u256)` event

Emitted when `value` amount of `id` token is transferred from `from` to `to` through `operator`.

#### [](#IERC1155-TransferBatch)
`TransferBatch(operator: ContractAddress, from: ContractAddress, to: ContractAddress, ids: Span<u256>, values: Span<u256>)` event

Emitted when a batch of `values` amount of `ids` tokens are transferred from `from` to `to` through `operator`.

#### [](#IERC1155-ApprovalForAll)
`ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)` event

Emitted when `owner` enables or disables `operator` to manage all of the owner’s assets.

#### [](#IERC1155-URI)
`URI(value: ByteArray, id: u256)` event

Emitted when the token URI is updated to `value` for the `id` token.

### [](#IERC1155MetadataURI)
`IERC1155MetadataURI`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc1155/interface.cairo)

    use openzeppelin::token::erc1155::interface::IERC1155MetadataURI;

Interface for the optional metadata function in [EIP1155](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

[SRC5 ID](introspection#ISRC5)

0xcabe2400d5fe509e1735ba9bad205ba5f3ca6e062da406f72f113feb889ef7

Functions

*   [`uri(token_id)`](#IERC1155MetadataURI-uri)
    

#### [](#functions_2)
Functions

#### [](#IERC1155MetadataURI-uri)
`uri(token_id: u256) -> ByteArray` external

Returns the Uniform Resource Identifier (URI) for the `token_id` token.

### [](#ERC1155Component)
`ERC1155Component`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc1155/erc1155.cairo)

    use openzeppelin::token::erc1155::ERC1155Component;

ERC1155 component implementing [IERC1155](#IERC1155)
 and [IERC1155MetadataURI](#IERC1155MetadataURI)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

|     |     |
| --- | --- |
|     | See [Hooks](#ERC1155Component-Hooks)<br> to understand how are hooks used. |

Hooks

ERC1155HooksTrait

*   [`before_update(self, from, to, token_ids, values)`](#ERC1155Component-before_update)
    
*   [`after_update(self, from, to, token_ids, values)`](#ERC1155Component-after_update)
    

[Embeddable Mixin Implementations](../components#mixins)

ERC1155MixinImpl

*   [`ERC1155Impl`](#ERC1155Component-Embeddable-Impls-ERC1155Impl)
    
*   [`ERC1155MetadataURIImpl`](#ERC1155Component-Embeddable-Impls-ERC1155MetadataURIImpl)
    
*   [`ER1155CamelImpl`](#ERC1155Component-Embeddable-Impls-ER1155CamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls-SRC5Impl)
    

Embeddable Implementations

ERC1155Impl

*   [`balance_of(self, account, token_id)`](#ERC1155Component-balance_of)
    
*   [`balance_of_batch(self, accounts, token_ids)`](#ERC1155Component-balance_of_batch)
    
*   [`safe_transfer_from(self, from, to, token_id, value, data)`](#ERC1155Component-safe_transfer_from)
    
*   [`safe_batch_transfer_from(self, from, to, token_ids, values, data)`](#ERC1155Component-safe_batch_transfer_from)
    
*   [`set_approval_for_all(self, operator, approved)`](#ERC1155Component-set_approval_for_all)
    
*   [`is_approved_for_all(self, owner, operator)`](#ERC1155Component-is_approved_for_all)
    

ERC1155MetadataURIImpl

*   [`uri(self, token_id)`](#ERC1155Component-uri)
    

ER1155CamelImpl

*   [`balanceOf(self, account, tokenId)`](#ERC1155Component-balanceOf)
    
*   [`balanceOfBatch(self, accounts, tokenIds)`](#ERC1155Component-balanceOfBatch)
    
*   [`safeTransferFrom(self, from, to, tokenId, value, data)`](#ERC1155Component-safeTransferFrom)
    
*   [`safeBatchTransferFrom(self, from, to, tokenIds, values, data)`](#ERC1155Component-safeBatchTransferFrom)
    
*   [`setApprovalForAll(self, operator, approved)`](#ERC1155Component-setApprovalForAll)
    
*   [`isApprovedForAll(self, owner, operator)`](#ERC1155Component-isApprovedForAll)
    

Internal Functions

InternalImpl

*   [`initializer(self, base_uri)`](#ERC1155Component-initializer)
    
*   [`mint_with_acceptance_check(self, to, token_id, value, data)`](#ERC1155Component-mint_with_acceptance_check)
    
*   [`batch_mint_with_acceptance_check(self, to, token_ids, values, data)`](#ERC1155Component-batch_mint_with_acceptance_check)
    
*   [`burn(self, from, token_id, value)`](#ERC1155Component-burn)
    
*   [`batch_burn(self, from, token_ids, values)`](#ERC1155Component-batch_burn)
    
*   [`update_with_acceptance_check(self, from, to, token_ids, values, data)`](#ERC1155Component-update_with_acceptance_check)
    
*   [`update(self, from, to, token_ids, values)`](#ERC1155Component-update)
    
*   [`_set_base_uri(self, base_uri)`](#ERC1155Component-_set_base_uri)
    

Events

IERC1155

*   [`TransferSingle(operator, from, to, id, value)`](#ERC1155Component-TransferSingle)
    
*   [`TransferBatch(operator, from, to, ids, values)`](#ERC1155Component-TransferBatch)
    
*   [`ApprovalForAll(owner, operator, approved)`](#ERC1155Component-ApprovalForAll)
    
*   [`URI(value, id)`](#ERC1155Component-URI)
    

#### [](#ERC1155Component-Hooks)
Hooks

Hooks are functions which implementations can extend the functionality of the component source code. Every contract using ERC1155Component is expected to provide an implementation of the ERC1155HooksTrait. For basic token contracts, an empty implementation with no logic must be provided.

|     |     |
| --- | --- |
|     | You can use `openzeppelin::token::erc1155::ERC1155HooksEmptyImpl` which is already available as part of the library for this purpose. |

#### [](#ERC1155Component-before_update)
`before_update(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` hook

Function executed at the beginning of the [update](#ERC1155Component-update)
 function prior to any other logic.

#### [](#ERC1155Component-after_update)
`after_update(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` hook

Function executed at the end of the [update](#ERC1155Component-update)
 function.

#### [](#embeddable_functions)
Embeddable functions

#### [](#ERC1155Component-balance_of)
`balance_of(self: @ContractState, account: ContractAddress, token_id: u256) → u256` external

Returns the amount of `token_id` tokens owned by `account`.

#### [](#ERC1155Component-balance_of_batch)
`balance_of_batch(self: @ContractState, accounts: Span<ContractAddress>, token_ids: Span<u256>) → Span<u256>` external

Returns a list of balances derived from the `accounts` and `token_ids` pairs.

Requirements:

*   `token_ids` and `accounts` must have the same length.
    

#### [](#ERC1155Component-safe_transfer_from)
`safe_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, value: u256, data: Span<felt252>)` external

Transfers ownership of `value` amount of `token_id` from `from` if `to` is either an account or `IERC1155Receiver`.

`data` is additional data, it has no specified format and it is passed to `to`.

|     |     |
| --- | --- |
|     | This function can potentially allow a reentrancy attack when transferring tokens to an untrusted contract, when invoking `on_ERC1155_received` on the receiver. Ensure to follow the checks-effects-interactions pattern and consider employing reentrancy guards when interacting with untrusted contracts. |

Requirements:

*   Caller is either approved or the `token_id` owner.
    
*   `from` is not the zero address.
    
*   `to` is not the zero address.
    
*   If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_received` and return the required magic value.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event.

#### [](#ERC1155Component-safe_batch_transfer_from)
`safe_batch_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` external

Transfers ownership of `values` and `token_ids` pairs from `from` if `to` is either an account or `IERC1155Receiver`.

`data` is additional data, it has no specified format and it is passed to `to`.

|     |     |
| --- | --- |
|     | This function can potentially allow a reentrancy attack when transferring tokens to an untrusted contract, when invoking `on_ERC1155_batch_received` on the receiver. Ensure to follow the checks-effects-interactions pattern and consider employing reentrancy guards when interacting with untrusted contracts. |

Requirements:

*   Caller is either approved or the `token_id` owner.
    
*   `from` is not the zero address.
    
*   `to` is not the zero address.
    
*   `token_ids` and `values` must have the same length.
    
*   If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` and return the acceptance magic value.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event if the arrays contain one element, and [TransferBatch](#ERC1155Component-TransferBatch)
 otherwise.

#### [](#ERC1155Component-set_approval_for_all)
`set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool)` external

Enables or disables approval for `operator` to manage all of the callers assets.

Requirements:

*   `operator` cannot be the caller.
    

Emits an [ApprovalForAll](#ERC1155Component-ApprovalForAll)
 event.

#### [](#ERC1155Component-is_approved_for_all)
`is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool` external

Queries if `operator` is an authorized operator for `owner`.

#### [](#ERC1155Component-uri)
`uri(self: @ContractState, token_id: u256) -> ByteArray` external

This implementation returns the same URI for **all** token types. It relies on the token type ID substitution mechanism [specified in the EIP](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

Clients calling this function must replace the `{id}` substring with the actual token type ID.

#### [](#ERC1155Component-balanceOf)
`balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) → u256` external

See [ERC1155Component::balance\_of](#ERC1155Component-balance_of)
.

#### [](#ERC1155Component-balanceOfBatch)
`balanceOfBatch(self: @ContractState, accounts: Span<ContractAddress>, tokenIds: Span<u256>) → Span<u256>` external

See [ERC1155Component::balance\_of\_batch](#ERC1155Component-balance_of_batch)
.

#### [](#ERC1155Component-safeTransferFrom)
`safeTransferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256, value: u256, data: Span<felt252>)` external

See [ERC1155Component::safe\_transfer\_from](#ERC1155Component-safe_transfer_from)
.

#### [](#ERC1155Component-safeBatchTransferFrom)
`safeBatchTransferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenIds: Span<u256>, values: Span<u256>, data: Span<felt252>)` external

See [ERC1155Component::safe\_batch\_transfer\_from](#ERC1155Component-safe_batch_transfer_from)
.

#### [](#ERC1155Component-setApprovalForAll)
`setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool)` external

See [ERC1155Component::set\_approval\_for\_all](#ERC1155Component-set_approval_for_all)
.

#### [](#ERC1155Component-isApprovedForAll)
`isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool` external

See [ERC1155Component::is\_approved\_for\_all](#ERC1155Component-is_approved_for_all)
.

#### [](#internal_functions)
Internal functions

#### [](#ERC1155Component-initializer)
`initializer(ref self: ContractState, base_uri: ByteArray)` internal

Initializes the contract by setting the token’s base URI as `base_uri`, and registering the supported interfaces. This should only be used inside the contract’s constructor.

#### [](#ERC1155Component-mint_with_acceptance_check)
`mint_with_acceptance_check(ref self: ContractState, to: ContractAddress, token_id: u256, value: u256, data: Span<felt252>)` internal

Creates a `value` amount of tokens of type `token_id`, and assigns them to `to`.

Requirements:

*   `to` cannot be the zero address.
    
*   If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_received` and return the acceptance magic value.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event.

#### [](#ERC1155Component-batch_mint_with_acceptance_check)
`batch_mint_with_acceptance_check(ref self: ContractState, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` internal

Batched version of [mint\_with\_acceptance\_check](#ERC1155Component-mint_with_acceptance_check)
.

Requirements:

*   `to` cannot be the zero address.
    
*   `token_ids` and `values` must have the same length.
    
*   If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` and return the acceptance magic value.
    

Emits a [TransferBatch](#ERC1155Component-TransferBatch)
 event.

#### [](#ERC1155Component-burn)
`burn(ref self: ContractState, from: ContractAddress, token_id: u256, value: u256)` internal

Destroys a `value` amount of tokens of type `token_id` from `from`.

Requirements:

*   `from` cannot be the zero address.
    
*   `from` must have at least `value` amount of tokens of type `token_id`.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event.

#### [](#ERC1155Component-batch_burn)
`batch_burn(ref self: ContractState, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` internal

Batched version of [burn](#ERC1155Component-burn)
.

Requirements:

*   `from` cannot be the zero address.
    
*   `from` must have at least `value` amount of tokens of type `token_id`.
    
*   `token_ids` and `values` must have the same length.
    

Emits a [TransferBatch](#ERC1155Component-TransferBatch)
 event.

#### [](#ERC1155Component-update_with_acceptance_check)
`update_with_acceptance_check(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` internal

Version of `update` that performs the token acceptance check by calling `onERC1155Received` or `onERC1155BatchReceived` in the receiver if it implements `IERC1155Receiver`, otherwise by checking if it is an account.

Requirements:

*   `to` is either an account contract or supports the `IERC1155Receiver` interface.
    
*   `token_ids` and `values` must have the same length.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event if the arrays contain one element, and [TransferBatch](#ERC1155Component-TransferBatch)
 otherwise.

#### [](#ERC1155Component-update)
`update(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` internal

Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` (or `to`) is the zero address.

Requirements:

*   `token_ids` and `values` must have the same length.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event if the arrays contain one element, and [TransferBatch](#ERC1155Component-TransferBatch)
 otherwise.

|     |     |
| --- | --- |
|     | This function can be extended using the [ERC1155HooksTrait](#ERC1155Component-ERC1155HooksTrait)<br>, to add functionality before and/or after the transfer, mint, or burn. |

|     |     |
| --- | --- |
|     | The ERC1155 acceptance check is not performed in this function. See [update\_with\_acceptance\_check](#ERC1155Component-update_with_acceptance_check)<br> instead. |

#### [](#ERC1155Component-_set_base_uri)
`_set_base_uri(ref self: ContractState, base_uri: ByteArray)` internal

Sets a new URI for all token types, by relying on the token type ID substitution mechanism [specified in the EIP](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

By this mechanism, any occurrence of the `{id}` substring in either the URI or any of the values in the JSON file at said URI will be replaced by clients with the token type ID.

For example, the `https://token-cdn-domain/\{id\}.json` URI would be interpreted by clients as `https://token-cdn-domain/000000000000...000000000000004cce0.json` for token type ID `0x4cce0`.

Because these URIs cannot be meaningfully represented by the `URI` event, this function emits no events.

#### [](#events_2)
Events

#### [](#ERC1155Component-TransferSingle)
`TransferSingle(operator: ContractAddress, from: ContractAddress, to: ContractAddress, id: u256, value: u256)` event

See [IERC1155::TransferSingle](#IERC1155-TransferSingle)
.

#### [](#ERC1155Component-TransferBatch)
`TransferBatch(operator: ContractAddress, from: ContractAddress, to: ContractAddress, ids: Span<u256>, values: Span<u256>)` event

See [IERC1155::TransferBatch](#IERC1155-TransferBatch)
.

#### [](#ERC1155Component-ApprovalForAll)
`ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)` event

See [IERC1155::ApprovalForAll](#IERC1155-ApprovalForAll)
.

#### [](#ERC1155Component-URI)
`URI(value: ByteArray, id: u256)` event

See [IERC1155::URI](#IERC1155-URI)
.

[](#receiver)
Receiver
----------------------

### [](#IERC1155Receiver)
`IERC1155Receiver`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc1155/interface.cairo)

    use openzeppelin::token::erc1155::interface::IERC1155Receiver;

Interface for contracts that support receiving token transfers from `ERC1155` contracts.

[SRC5 ID](introspection#ISRC5)

0x15e8665b5af20040c3af1670509df02eb916375cdf7d8cbaf7bd553a257515e

Functions

*   [`on_erc1155_received(operator, from, token_id, value, data)`](#IERC1155Receiver-on_erc1155_received)
    
*   [`on_erc1155_batch_received(operator, from, token_ids, values, data)`](#IERC1155Receiver-on_erc1155_batch_received)
    

#### [](#functions_3)
Functions

#### [](#IERC1155Receiver-on_erc1155_received)
`on_erc1155_received(operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span<felt252>) -> felt252` external

This function is called whenever an ERC1155 `token_id` token is transferred to this `IERC1155Receiver` implementer via [IERC1155::safe\_transfer\_from](#IERC1155-safe_transfer_from)
 by `operator` from `from`.

#### [](#IERC1155Receiver-on_erc1155_batch_received)
`on_erc1155_batch_received(operator: ContractAddress, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data Span<felt252>) -> felt252` external

This function is called whenever multiple ERC1155 `token_ids` tokens are transferred to this `IERC1155Receiver` implementer via [IERC1155::safe\_batch\_transfer\_from](#IERC1155-safe_batch_transfer_from)
 by `operator` from `from`.

### [](#ERC1155ReceiverComponent)
`ERC1155ReceiverComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc1155/erc1155_receiver.cairo)

    use openzeppelin::token::erc1155::ERC1155ReceiverComponent;

ERC1155Receiver component implementing [IERC1155Receiver](#IERC1155Receiver)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

[Embeddable Mixin Implementations](../components#mixins)

ERC1155MixinImpl

*   [`ERC1155ReceiverImpl`](#ERC1155ReceiverComponent-Embeddable-Impls-ERC1155ReceiverImpl)
    
*   [`ERC1155ReceiverCamelImpl`](#ERC1155ReceiverComponent-Embeddable-Impls-ERC1155ReceiverCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls-SRC5Impl)
    

Embeddable Implementations

ERC1155ReceiverImpl

*   [`on_erc1155_received(self, operator, from, token_id, value, data)`](#ERC1155ReceiverComponent-on_erc1155_received)
    
*   [`on_erc1155_batch_received(self, operator, from, token_ids, values, data)`](#ERC1155ReceiverComponent-on_erc1155_batch_received)
    

ERC1155ReceiverCamelImpl

*   [`onERC1155Received(self, operator, from, tokenId, value, data)`](#ERC1155ReceiverComponent-onERC1155Received)
    
*   [`onERC1155BatchReceived(self, operator, from, tokenIds, values, data)`](#ERC1155ReceiverComponent-onERC1155BatchReceived)
    

Internal Functions

InternalImpl

*   [`initializer(self)`](#ERC1155ReceiverComponent-initializer)
    

#### [](#embeddable_functions_2)
Embeddable functions

#### [](#ERC1155ReceiverComponent-on_erc1155_received)
`on_erc1155_received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span<felt252>) -> felt252` external

Returns the `IERC1155Receiver` interface ID.

#### [](#ERC1155ReceiverComponent-on_erc1155_batch_received)
`on_erc1155_batch_received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data Span<felt252>) -> felt252` external

Returns the `IERC1155Receiver` interface ID.

#### [](#ERC1155ReceiverComponent-onERC1155Received)
`onERC1155Received(self: @ContractState, operator: ContractAddress, from: ContractAddress, tokenId: u256, value: u256, data Span<felt252>) -> felt252` external

See [ERC1155ReceiverComponent::on\_erc1155\_received](#ERC1155ReceiverComponent-on_erc1155_received)
.

#### [](#ERC1155ReceiverComponent-onERC1155BatchReceived)
`onERC1155BatchReceived(self: @ContractState, operator: ContractAddress, from: ContractAddress, tokenIds: Span<u256>, values: Span<u256>, data Span<felt252>) -> felt252` external

See [ERC1155ReceiverComponent::on\_erc1155\_batch\_received](#ERC1155ReceiverComponent-on_erc1155_batch_received)
.

#### [](#internal_functions_2)
Internal functions

#### [](#ERC1155ReceiverComponent-initializer)
`initializer(ref self: ContractState)` internal

Registers the `IERC1155Receiver` interface ID as supported through introspection.

[](#presets)
Presets
--------------------

### [](#ERC1155Upgradeable)
`ERC1155Upgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/presets/erc1155.cairo)

    use openzeppelin::presets::ERC1155;

Upgradeable ERC1155 contract leveraging [ERC1155Component](#ERC1155Component)
.

[Sierra class hash](../presets)

0x03f994c0b1a88825c67270b7e82e681c839e95e3bc40d4d8144771f8860166a2

Constructor

*   [`constructor(self, base_uri, recipient, token_ids, values, owner)`](#ERC1155Upgradeable-constructor)
    

Embedded Implementations

ERC1155Component

*   [`ERC1155MixinImpl`](#ERC1155Component-Embeddable-Mixin-Impl)
    

OwnableMixinImpl

*   [`OwnableMixinImpl`](access#OwnableComponent-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#ERC1155Upgradeable-upgrade)
    

#### [](#ERC1155Upgradeable-constructor-section)
Constructor

#### [](#ERC1155Upgradeable-constructor)
`constructor(ref self: ContractState, base_uri: ByteArray, recipient: ContractAddress, token_ids: Span<u256>, values: Span<u256>, owner: ContractAddress)` constructor

Sets the `base_uri` for all tokens and registers the supported interfaces. Mints the `values` for `token_ids` tokens to `recipient`. Assigns `owner` as the contract owner with permissions to upgrade.

Requirements:

*   `to` is either an account contract (supporting ISRC6) or supports the `IERC1155Receiver` interface.
    
*   `token_ids` and `values` must have the same length.
    

#### [](#ERC1155Upgradeable-external-functions)
External Functions

#### [](#ERC1155Upgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the contract owner.
    
*   `new_class_hash` cannot be zero.
    

[← ERC1155](/contracts-cairo/0.15.0/erc1155)

[Universal Deployer Contract →](/contracts-cairo/0.15.0/udc)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

In different blockchains, multiple patterns have been developed for making a contract upgradeable including the widely adopted proxy patterns.

Starknet has native upgradeability through a syscall that updates the contract source code, removing [the need for proxies](#proxies_in_starknet)
.

|     |     |
| --- | --- |
|     | Make sure you follow [our security recommendations](#security)<br> before upgrading. |

[](#replacing_contract_classes)
Replacing contract classes
----------------------------------------------------------

To better comprehend how upgradeability works in Starknet, it’s important to understand the difference between a contract and its contract class.

[Contract Classes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-classes/)
 represent the source code of a program. All contracts are associated to a class, and many contracts can be instances of the same one. Classes are usually represented by a [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
, and before a contract of a class can be deployed, the class hash needs to be declared.

### [](#replace_class_syscall)
`replace_class_syscall`

The `[replace_class](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#replace_class) ` syscall allows a contract to update its source code by replacing its class hash once deployed.

    /// Upgrades the contract source code to the new contract class.
    fn upgrade(new_class_hash: ClassHash) {
        assert(!new_class_hash.is_zero(), 'Class hash cannot be zero');
        starknet::replace_class_syscall(new_class_hash).unwrap_syscall();
    }

|     |     |
| --- | --- |
|     | If a contract is deployed without this mechanism, its class hash can still be replaced through [library calls](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#library_call)<br>. |

[](#upgradeable_component)
`Upgradeable` component
--------------------------------------------------

OpenZeppelin Contracts for Cairo provides [Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/upgrades/upgradeable.cairo)
 to add upgradeability support to your contracts.

### [](#usage)
Usage

Upgrades are often very sensitive operations, and some form of access control is usually required to avoid unauthorized upgrades. The [Ownable](access#ownership_and_ownable)
 module is used in this example.

|     |     |
| --- | --- |
|     | We will be using the following module to implement the [IUpgradeable](api/upgrades#IUpgradeable)<br> interface described in the API Reference section. |

    #[starknet::contract]
    mod UpgradeableContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use openzeppelin::upgrades::UpgradeableComponent;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::ClassHash;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
        component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
    
        // Ownable Mixin
        #[abi(embed_v0)]
        impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
        impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        // Upgradeable
        impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage,
            #[substorage(v0)]
            upgradeable: UpgradeableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event,
            #[flat]
            UpgradeableEvent: UpgradeableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            self.ownable.initializer(owner);
        }
    
        #[abi(embed_v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                // This function can only be called by the owner
                self.ownable.assert_only_owner();
    
                // Replace the class hash upgrading the contract
                self.upgradeable.upgrade(new_class_hash);
            }
        }
    }

[](#security)
Security
----------------------

Upgrades can be very sensitive operations, and security should always be top of mind while performing one. Please make sure you thoroughly review the changes and their consequences before upgrading. Some aspects to consider are:

*   API changes that might affect integration. For example, changing an external function’s arguments might break existing contracts or offchain systems calling your contract.
    
*   Storage changes that might result in lost data (e.g. changing a storage slot name, making existing storage inaccessible).
    
*   Collisions (e.g. mistakenly reusing the same storage slot from another component) are also possible, although less likely if best practices are followed, for example prepending storage variables with the component’s name (e.g. `ERC20_balances`).
    
*   Always check for [backwards compatibility](backwards-compatibility)
     before upgrading between versions of OpenZeppelin Contracts.
    

[](#proxies_in_starknet)
Proxies in Starknet
--------------------------------------------

Proxies enable different patterns such as upgrades and clones. But since Starknet achieves the same in different ways is that there’s no support to implement them.

In the case of contract upgrades, it is achieved by simply changing the contract’s class hash. As of clones, contracts already are like clones of the class they implement.

Implementing a proxy pattern in Starknet has an important limitation: there is no fallback mechanism to be used for redirecting every potential function call to the implementation. This means that a generic proxy contract can’t be implemented. Instead, a limited proxy contract can implement specific functions that forward their execution to another contract class. This can still be useful for example to upgrade the logic of some functions.

[← API Reference](/contracts-cairo/0.15.0/api/udc)

[API Reference →](/contracts-cairo/0.15.0/api/upgrades)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

Reference of interfaces and utilities related to upgradeability.

[](#core)
Core
--------------

### [](#IUpgradeable)
`IUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/upgrades/interface.cairo#L3)

    use openzeppelin::upgrades::interface::IUpgradeable;

Interface of an upgradeable contract.

Functions

*   [`upgrade(new_class_hash)`](#IUpgradeable-upgrade)
    

#### [](#IUpgradeable-Functions)
Functions

#### [](#IUpgradeable-upgrade)
`upgrade(new_class_hash: ClassHash)` external

Upgrades the contract code by updating its [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

|     |     |
| --- | --- |
|     | This function is usually protected by an [Access Control](../access)<br> mechanism. |

### [](#UpgradeableComponent)
`UpgradeableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/upgrades/upgradeable.cairo)

    use openzeppelin::upgrades::upgradeable::UpgradeableComponent;

Upgradeable component.

Internal Implementations

InternalImpl

*   [`upgrade(self, new_class_hash)`](#UpgradeableComponent-upgrade)
    

Events

*   [`Upgraded(class_hash)`](#UpgradeableComponent-Upgraded)
    

#### [](#UpgradeableComponent-Internal-Functions)
Internal Functions

#### [](#UpgradeableComponent-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` internal

Upgrades the contract by updating the contract [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

Requirements:

*   `new_class_hash` must be different from zero.
    

Emits an [Upgraded](#UpgradeableComponent-Upgraded)
 event.

#### [](#UpgradeableComponent-Events)
Events

#### [](#UpgradeableComponent-Upgraded)
`Upgraded(class_hash: ClassHash)` event

Emitted when the [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
 is upgraded.

[← Upgrades](/contracts-cairo/0.15.0/upgrades)

[Utilities →](/contracts-cairo/0.15.0/api/utilities)




 Universal Deployer - OpenZeppelin Docs       

Universal Deployer
==================

Reference of the Universal Deployer Contract (UDC) interface and preset.

[](#core)
Core
--------------

### [](#IUniversalDeployer)
`IUniversalDeployer`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/utils/universal_deployer/interface.cairo#L7)

    use openzeppelin::utils::interfaces::IUniversalDeployer;

Functions

*   [`deploy_contract(class_hash, salt, from_zero, calldata)`](#IUniversalDeployer-deploy_contract)
    

Events

*   [`ContractDeployed(address, deployer, from_zero, class_hash, calldata, salt)`](#IUniversalDeployer-ContractDeployed)
    

#### [](#IUniversalDeployer-Functions)
Functions

#### [](#IUniversalDeployer-deploy_contract)
`deploy_contract(class_hash: ClassHash, salt: felt252, from_zero: bool, calldata: Span<felt252>) → ContractAddress` external

Deploys a contract through the Universal Deployer Contract.

#### [](#IUniversalDeployer-Events)
Events

#### [](#IUniversalDeployer-ContractDeployed)
`ContractDeployed(address: ContractAddress, deployer: ContractAddress, from_zero: bool, class_hash: ClassHash, calldata: Span<felt252>, salt: felt252)` event

Emitted when `deployer` deploys a contract through the Universal Deployer Contract.

[](#presets)
Presets
--------------------

### [](#UniversalDeployer)
`UniversalDeployer`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/presets/universal_deployer.cairo)

    use openzeppelin::presets::UniversalDeployer;

The standard Universal Deployer Contract.

[Sierra class hash](../presets)

0x0536e18e3e9820b48e0477e83e0a4d6d923ccddc06deb61585dfd7402dd40733

Embedded Implementations

UniversalDeployerImpl

*   [`deploy_contract(self, address, deployer, from_zero, class_hash, calldata, salt)`](#UniversalDeployer-deploy_contract)
    

#### [](#UniversalDeployer-deploy_contract)
`deploy_contract(ref self: ContractState, address: ContractAddress, deployer: ContractAddress, from_zero: bool, class_hash: ClassHash, calldata: Span<felt252>, salt: felt252) -> ContractAddress` external

Deploys a contract through the Universal Deployer Contract.

When `from_zero` is `false`, `salt` is hashed with the caller address and the modified salt is passed to the inner `deploy_syscall`. This type of deployment is [origin-dependent](../udc#origin_dependent)
.

When `from_zero` is `true`, the deployment type is [origin-independent](../udc#origin_independent)
.

Emits an [ContractDeployed](#IUniversalDeployer-ContractDeployed)
 event.

[← Universal Deployer Contract](/contracts-cairo/0.13.0/udc)

[Upgrades →](/contracts-cairo/0.13.0/upgrades)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

Reference of interfaces and utilities related to upgradeability.

[](#core)
Core
--------------

### [](#IUpgradeable)
`IUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/upgrades/interface.cairo#L3)

    use openzeppelin::upgrades::interface::IUpgradeable;

Interface of an upgradeable contract.

Functions

*   [`upgrade(new_class_hash)`](#IUpgradeable-upgrade)
    

#### [](#IUpgradeable-Functions)
Functions

#### [](#IUpgradeable-upgrade)
`upgrade(new_class_hash: ClassHash)` external

Upgrades the contract code by updating its [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

|     |     |
| --- | --- |
|     | This function is usually protected by an [Access Control](../access)<br> mechanism. |

### [](#UpgradeableComponent)
`UpgradeableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/upgrades/upgradeable.cairo)

    use openzeppelin::upgrades::upgradeable::UpgradeableComponent;

Upgradeable component.

Internal Implementations

InternalImpl

*   [`_upgrade(self, new_class_hash)`](#UpgradeableComponent-_upgrade)
    

Events

*   [`Upgraded(class_hash)`](#UpgradeableComponent-Upgraded)
    

#### [](#UpgradeableComponent-Internal-Functions)
Internal Functions

#### [](#UpgradeableComponent-_upgrade)
`_upgrade(ref self: ContractState, new_class_hash: ClassHash)` internal

Upgrades the contract by updating the contract [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

Requirements:

*   `new_class_hash` must be different from zero.
    

Emits an [Upgraded](#UpgradeableComponent-Upgraded)
 event.

#### [](#UpgradeableComponent-Events)
Events

#### [](#UpgradeableComponent-Upgraded)
`Upgraded(class_hash: ClassHash)` event

Emitted when the [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
 is upgraded.

[← Upgrades](/contracts-cairo/0.13.0/upgrades)

[Utilities →](/contracts-cairo/0.13.0/api/utilities)




 Universal Deployer Contract - OpenZeppelin Docs       

Universal Deployer Contract
===========================

The Universal Deployer Contract (UDC) is a singleton smart contract that wraps the [deploy syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy)
 to expose it to any contract that doesn’t implement it, such as account contracts. You can think of it as a standardized generic factory for Starknet contracts.

Since Starknet has no deployment transaction type, it offers a standardized way to deploy smart contracts by following the [Standard Deployer Interface](https://community.starknet.io/t/snip-deployer-contract-interface/2772)
 and emitting a [ContractDeployed](api/udc#IUniversalDeployer-ContractDeployed)
 event.

For details on the motivation and the decision making process, see the [Universal Deployer Contract proposal](https://community.starknet.io/t/universal-deployer-contract-proposal/1864)
.

[](#udc_contract_address)
UDC contract address
----------------------------------------------

The UDC address is deployed at address `0x04a64cd09a853868621d94cae9952b106f2c36a3f81260f85de6696c6b050221` in Mainnet and Sepolia testnet.

[](#interface)
Interface
------------------------

    trait IUniversalDeployer {
        fn deploy_contract(
            class_hash: ClassHash,
            salt: felt252,
            from_zero: bool,
            calldata: Span<felt252>
        ) -> ContractAddress;
    }

[](#deploying_a_contract_with_the_udc)
Deploying a contract with the UDC
------------------------------------------------------------------------

First, [declare](https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#declare-transaction)
 the target contract (if it’s not already declared). Next, call the UDC’s `deploy_contract` method. Here’s an implementation example in Cairo:

    use openzeppelin::utils::interfaces::{IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait};
    
    const UDC_ADDRESS: felt252 = 0x04a64cd09a853868621d94cae9952b106f2c36a3f81260f85de6696c6b050221;
    
    fn deploy() -> ContractAddress {
        let dispatcher = IUniversalDeployerDispatcher {
            contract_address: UDC_ADDRESS.try_into().unwrap()
        };
    
        // Deployment parameters
        let class_hash = class_hash_const::<
           0x5c478ee27f2112411f86f207605b2e2c58cdb647bac0df27f660ef2252359c6
        >();
        let salt = 1234567879;
        let from_zero = false;
        let mut calldata = array![];
    
        // The UDC returns the deployed contract address
        dispatcher.deploy_contract(class_hash, salt, from_zero, calldata.span())
    }

[](#deployment_types)
Deployment types
--------------------------------------

The Universal Deployer Contract offers two types of addresses to deploy: origin-dependent and origin-independent. As the names suggest, the origin-dependent type includes the deployer’s address in the address calculation, whereas, the origin-independent type does not. The `from_zero` boolean parameter ultimately determines the type of deployment.

|     |     |
| --- | --- |
|     | When deploying a contract that uses `get_caller_address` in the constructor calldata, remember that the UDC, not the account, deploys that contract. Therefore, querying `get_caller_address` in a contract’s constructor returns the UDC’s address, _not the account’s address_. |

### [](#origin_dependent)
Origin-dependent

By making deployments dependent upon the origin address, users can reserve a whole address space to prevent someone else from taking ownership of the address.

Only the owner of the origin address can deploy to those addresses.

Achieving this type of deployment necessitates that the origin sets `from_zero` to `false` in the [deploy\_contract](api/udc#UniversalDeployer-deploy_contract)
 call. Under the hood, the function passes a modified salt to the `deploy_syscall`, which is the hash of the origin’s address with the given salt.

To deploy a unique contract address pass:

    let deployed_addr = udc.deploy_contract(class_hash, salt, false, calldata.span());

### [](#origin_independent)
Origin-independent

Origin-independent contract deployments create contract addresses independent of the deployer and the UDC instance. Instead, only the class hash, salt, and constructor arguments determine the address. This type of deployment enables redeployments of accounts and known systems across multiple networks. To deploy a reproducible deployment, set `from_zero` to `true`.

    let deployed_addr = udc.deploy_contract(class_hash, salt, true, calldata.span());

[](#version_changes)
Version changes
------------------------------------

|     |     |
| --- | --- |
|     | See the [previous Universal Deployer API](https://docs.openzeppelin.com/contracts-cairo/0.6.1/udc#api_specification)<br> for the initial spec. |

The latest iteration of the UDC includes some notable changes to the API which include:

*   `deployContract` method is replaced with the snake\_case [deploy\_contract](api/udc#UniversalDeployer-deploy_contract)
    .
    
*   [Pedersen](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#pedersen_hash)
     hashing algorithm is replaced with the [Poseidon](https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/hash-functions/#poseidon_hash)
     hashing algorithm for computing the salt on [origin-dependent deployments](#origin_dependent)
    .
    
*   `unique` parameter is replaced with `from_zero` in both the `deploy_contract` method and [ContractDeployed](api/udc#IUniversalDeployer-ContractDeployed)
     event.
    

|     |     |
| --- | --- |
|     | Origin-dependent deployments previously meant that the `unique` argument would be `true`. Origin-dependent deployments from the new UDC iteration, however, requires that `from_zero` is `false`. It’s especially important to keep this in mind when dealing with `ContractDeployed` events because this change will appear as the opposite boolean per deployment type. |

[](#precomputing_contract_addresses)
Precomputing contract addresses
--------------------------------------------------------------------

This library offers utility functions written in Cairo to precompute contract addresses. They include the generic [calculate\_contract\_address\_from\_deploy\_syscall](api/utilities#deployments-calculate_contract_address_from_deploy_syscall)
 as well as the UDC-specific [calculate\_contract\_address\_from\_udc](api/utilities#deployments-calculate_contract_address_from_udc)
. Check out the [deployments](api/utilities#deployments)
 for more information.

[← API Reference](/contracts-cairo/0.13.0/api/erc1155)

[API Reference →](/contracts-cairo/0.13.0/api/udc)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

Reference of interfaces and utilities related to ERC20 contracts.

|     |     |
| --- | --- |
|     | For an overview of ERC20, read our [ERC20 guide](../erc20)<br>. |

[](#core)
Core
--------------

### [](#IERC20)
`IERC20`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc20/interface.cairo)

    use openzeppelin::token::erc20::interface::IERC20;

Interface of the IERC20 standard as defined in [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
.

Functions

*   [`total_supply()`](#IERC20-total_supply)
    
*   [`balance_of()`](#IERC20-balance_of)
    
*   [`allowance(owner, spender)`](#IERC20-allowance)
    
*   [`transfer(recipient, amount)`](#IERC20-transfer)
    
*   [`transfer_from(sender, recipient, amount)`](#IERC20-transfer_from)
    
*   [`approve(spender, amount)`](#IERC20-approve)
    

Events

*   [`Transfer(from, to, value)`](#IERC20-Transfer)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval)
    

#### [](#IERC20-Functions)
Functions

#### [](#IERC20-total_supply)
`total_supply() → u256` external

Returns the amount of tokens in existence.

#### [](#IERC20-balance_of)
`balance_of(account: ContractAddress) → u256` external

Returns the amount of tokens owned by `account`.

#### [](#IERC20-allowance)
`allowance(owner: ContractAddress, spender: ContractAddress) → u256` external

Returns the remaining number of tokens that `spender` is allowed to spend on behalf of `owner` through [transfer\_from](#transfer_from)
. This is zero by default.

This value changes when [approve](#IERC20-approve)
 or [transfer\_from](#IERC20-transfer_from)
 are called.

#### [](#IERC20-transfer)
`transfer(recipient: ContractAddress, amount: u256) → bool` external

Moves `amount` tokens from the caller’s token balance to `to`. Returns `true` on success, reverts otherwise.

Emits a [Transfer](#ERC20-Transfer)
 event.

#### [](#IERC20-transfer_from)
`transfer_from(sender: ContractAddress, recipient: ContractAddress, amount: u256) → bool` external

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. Returns `true` on success, reverts otherwise.

Emits a [Transfer](#ERC20-Transfer)
 event.

#### [](#IERC20-approve)
`approve(spender: ContractAddress, amount: u256) → bool` external

Sets `amount` as the allowance of `spender` over the caller’s tokens. Returns `true` on success, reverts otherwise.

Emits an [Approval](#ERC20-Approval)
 event.

#### [](#IERC20-Events)
Events

#### [](#IERC20-Transfer)
`Transfer(from: ContractAddress, to: ContractAddress, value: u256)` event

Emitted when `value` tokens are moved from one address (`from`) to another (`to`).

Note that `value` may be zero.

#### [](#IERC20-Approval)
`Approval(owner: ContractAddress, spender: ContractAddress, value: u256)` event

Emitted when the allowance of a `spender` for an `owner` is set. `value` is the new allowance.

### [](#IERC20Metadata)
`IERC20Metadata`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc20/interface.cairo#L19)

    use openzeppelin::token::erc20::interface::IERC20Metadata;

Interface for the optional metadata functions in [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
.

Functions

*   [`name()`](#IERC20Metadata-name)
    
*   [`symbol()`](#IERC20Metadata-symbol)
    
*   [`decimals()`](#IERC20Metadata-decimals)
    

#### [](#IERC20Metadata-Functions)
Functions

#### [](#IERC20Metadata-name)
`name() → ByteArray` external

Returns the name of the token.

#### [](#IERC20Metadata-symbol)
`symbol() → ByteArray` external

Returns the ticker symbol of the token.

#### [](#IERC20Metadata-decimals)
`decimals() → u8` external

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user-readable representation.

For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`).

Tokens usually opt for a value of `18`, imitating the relationship between Ether and Wei. This is the default value returned by this function. To create a custom decimals implementation, see [Customizing decimals](../erc20#customizing_decimals)
.

|     |     |
| --- | --- |
|     | This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract. |

### [](#ERC20Component)
`ERC20Component`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc20/erc20.cairo)

    use openzeppelin::token::erc20::ERC20Component;

ERC20 component extending [IERC20](#IERC20)
 and [IERC20Metadata](#IERC20Metadata)
.

[Embeddable Mixin Implementations](../components#mixins)

ERC20MixinImpl

*   [`ERC20Impl`](#ERC20Component-Embeddable-Impls-ERC20Impl)
    
*   [`ERC20MetadataImpl`](#ERC20Component-Embeddable-Impls-ERC20MetadataImpl)
    
*   [`ERC20CamelOnlyImpl`](#ERC20Component-Embeddable-Impls-ERC20CamelOnlyImpl)
    

Embeddable Implementations

ERC20Impl

*   [`total_supply(self)`](#ERC20Component-total_supply)
    
*   [`balance_of(self, account)`](#ERC20Component-balance_of)
    
*   [`allowance(self, owner, spender)`](#ERC20Component-allowance)
    
*   [`transfer(self, recipient, amount)`](#ERC20Component-transfer)
    
*   [`transfer_from(self, sender, recipient, amount)`](#ERC20Component-transfer_from)
    
*   [`approve(self, spender, amount)`](#ERC20Component-approve)
    

ERC20MetadataImpl

*   [`name(self)`](#ERC20Component-name)
    
*   [`symbol(self)`](#ERC20Component-symbol)
    
*   [`decimals(self)`](#ERC20Component-decimals)
    

ERC20CamelOnlyImpl

*   [`totalSupply(self)`](#ERC20Component-totalSupply)
    
*   [`balanceOf(self, account)`](#ERC20Component-balanceOf)
    
*   [`transferFrom(self, sender, recipient, amount)`](#ERC20Component-transferFrom)
    

Internal implementations

InternalImpl

*   [`initializer(self, name, symbol)`](#ERC20Component-initializer)
    
*   [`_transfer(self, sender, recipient, amount)`](#ERC20Component-_transfer)
    
*   [`_approve(self, owner, spender, amount)`](#ERC20Component-_approve)
    
*   [`_mint(self, recipient, amount)`](#ERC20Component-_mint)
    
*   [`_burn(self, account, amount)`](#ERC20Component-_burn)
    
*   [`_spend_allowance(self, owner, spender, amount)`](#ERC20Component-_spend_allowance)
    

Events

*   [`Transfer(from, to, value)`](#ERC20Component-Transfer)
    
*   [`Approval(owner, spender, value)`](#ERC20Component-Approval)
    

#### [](#ERC20Component-Embeddable-functions)
Embeddable functions

#### [](#ERC20Component-total_supply)
`total_supply(@self: ContractState) → u256` external

See [IERC20::total\_supply](#IERC20-total_supply)
.

#### [](#ERC20Component-balance_of)
`balance_of(@self: ContractState, account: ContractAddress) → u256` external

See [IERC20::balance\_of](#IERC20-balance_of)
.

#### [](#ERC20Component-allowance)
`allowance(@self: ContractState, owner: ContractAddress, spender: ContractAddress) → u256` external

See [IERC20::allowance](#IERC20-allowance)
.

#### [](#ERC20Component-transfer)
`transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) → bool` external

See [IERC20::transfer](#IERC20-transfer)
.

Requirements:

*   `recipient` cannot be the zero address.
    
*   The caller must have a balance of at least `amount`.
    

#### [](#ERC20Component-transfer_from)
`transfer_from(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256) → bool` external

See [IERC20::transfer\_from](#IERC20-transfer_from)
.

Requirements:

*   `sender` cannot be the zero address.
    
*   `sender` must have a balance of at least `amount`.
    
*   `recipient` cannot be the zero address.
    
*   The caller must have allowance for `sender`'s tokens of at least `amount`.
    

#### [](#ERC20Component-approve)
`approve(ref self: ContractState, spender: ContractAddress, amount: u256) → bool` external

See [IERC20::approve](#IERC20-approve)
.

Requirements:

*   `spender` cannot be the zero address.
    

#### [](#ERC20Component-name)
`name() → ByteArray` external

See [IERC20Metadata::name](#IERC20Metadata-name)
.

#### [](#ERC20Component-symbol)
`symbol() → ByteArray` external

See [IERC20Metadata::symbol](#IERC20Metadata-symbol)
.

#### [](#ERC20Component-decimals)
`decimals() → u8` external

See [IERC20Metadata::decimals](#IERC20Metadata-decimals)
.

#### [](#ERC20Component-totalSupply)
`totalSupply(self: @ContractState) → u256` external

See [IERC20::total\_supply](#IERC20-total_supply)
.

Supports the Cairo v0 convention of writing external methods in camelCase as discussed [here](https://github.com/OpenZeppelin/cairo-contracts/discussions/34)
.

#### [](#ERC20Component-balanceOf)
`balanceOf(self: @ContractState, account: ContractAddress) → u256` external

See [IERC20::balance\_of](#IERC20-balance_of)
.

Supports the Cairo v0 convention of writing external methods in camelCase as discussed [here](https://github.com/OpenZeppelin/cairo-contracts/discussions/34)
.

#### [](#ERC20Component-transferFrom)
`transferFrom(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress) → bool` external

See [IERC20::transfer\_from](#IERC20-transfer_from)
.

Supports the Cairo v0 convention of writing external methods in camelCase as discussed [here](https://github.com/OpenZeppelin/cairo-contracts/discussions/34)
.

#### [](#ERC20Component-Internal-functions)
Internal functions

#### [](#ERC20Component-initializer)
`initializer(ref self: ContractState, name: ByteArray, symbol: ByteArray)` internal

Initializes the contract by setting the token name and symbol. This should be used inside of the contract’s constructor.

#### [](#ERC20Component-_transfer)
`_transfer(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256)` internal

Moves `amount` of tokens from `from` to `to`.

This internal function does not check for access permissions but can be useful as a building block, for example to implement automatic token fees, slashing mechanisms, etc.

Emits a [Transfer](#ERC20Component-Transfer)
 event.

Requirements:

*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    
*   `from` must have a balance of at least `amount`.
    

#### [](#ERC20Component-_approve)
`_approve(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256)` internal

Sets `amount` as the allowance of `spender` over `owner`'s tokens.

This internal function does not check for access permissions but can be useful as a building block, for example to implement automatic allowances on behalf of other addresses.

Emits an [Approval](#ERC20Component-Approval)
 event.

Requirements:

*   `owner` cannot be the zero address.
    
*   `spender` cannot be the zero address.
    

#### [](#ERC20Component-_mint)
`_mint(ref self: ContractState, recipient: ContractAddress, amount: u256)` internal

Creates an `amount` number of tokens and assigns them to `recipient`.

Emits a [Transfer](#ERC20Component-Transfer)
 event with `from` being the zero address.

Requirements:

*   `recipient` cannot be the zero address.
    

#### [](#ERC20Component-_burn)
`_burn(ref self: ContractState, account: ContractAddress, amount: u256)` internal

Destroys `amount` number of tokens from `account`.

Emits a [Transfer](#ERC20Component-Transfer)
 event with `to` set to the zero address.

Requirements:

*   `account` cannot be the zero address.
    

#### [](#ERC20Component-_spend_allowance)
`_spend_allowance(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256)` internal

Updates `owner`'s allowance for `spender` based on spent `amount`.

This internal function does not update the allowance value in the case of infinite allowance.

Possibly emits an [Approval](#ERC20Component-Approval)
 event.

#### [](#ERC20Component-Events)
Events

#### [](#ERC20Component-Transfer)
`Transfer(from: ContractAddress, to: ContractAddress, value: u256)` event

See [IERC20::Transfer](#IERC20-Transfer)
.

#### [](#ERC20Component-Approval)
`Approval(owner: ContractAddress, spender: ContractAddress, value: u256)` event

See [IERC20::Approval](#IERC20-Approval)
.

[](#presets)
Presets
--------------------

### [](#ERC20)
`ERC20`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/presets/erc20.cairo)

    use openzeppelin::presets::ERC20;

Basic ERC20 contract leveraging [ERC20Component](#ERC20Component)
 with a fixed-supply mechanism for token distribution.

[Sierra class hash](../presets)

0x03b6024fbaf5276e4aa0b4632b80caa6228dbf7b3fe2a0d6144aacb5eb14f1a0

Constructor

*   [`constructor(self, name, symbol, fixed_supply, recipient)`](#ERC20-constructor)
    

Embedded Implementations

ERC20MixinImpl

*   [`ERC20MixinImpl`](#ERC20Component-Embeddable-Mixin-Impl)
    

#### [](#ERC20-constructor-section)
Constructor

#### [](#ERC20-constructor)
`constructor(ref self: ContractState, name: ByteArray, symbol: ByteArray, fixed_supply: u256, recipient: ContractAddress)` constructor

Sets the `name` and `symbol` and mints `fixed_supply` tokens to `recipient`.

[← Creating Supply](/contracts-cairo/0.10.0/guides/erc20-supply)

[ERC721 →](/contracts-cairo/0.10.0/erc721)




 ERC 777 - OpenZeppelin Docs       

ERC 777
=======

|     |     |
| --- | --- |
|     | This document is better viewed at [https://docs.openzeppelin.com/contracts/api/token/erc777](https://docs.openzeppelin.com/contracts/api/token/erc777) |

This set of interfaces and contracts are all related to the \[ERC777 token standard\]([https://eips.ethereum.org/EIPS/eip-777](https://eips.ethereum.org/EIPS/eip-777)
).

|     |     |
| --- | --- |
|     | For an overview of ERC777 tokens and a walk through on how to create a token contract read our [ERC777 guide](../../erc777)<br>. |

The token behavior itself is implemented in the core contracts: [`IERC777`](#IERC777)
, [`ERC777`](#ERC777)
.

Additionally there are interfaces used to develop contracts that react to token movements: [`IERC777Sender`](#IERC777Sender)
, [`IERC777Recipient`](#IERC777Recipient)
.

[](#core)
Core
--------------

### [](#IERC777)
`IERC777`

Interface of the ERC777Token standard as defined in the EIP.

This contract uses the [ERC1820 registry standard](https://eips.ethereum.org/EIPS/eip-1820)
 to let token holders and recipients react to token movements by using setting implementers for the associated interfaces in said registry. See [`IERC1820Registry`](../introspection#IERC1820Registry)
 and [`ERC1820Implementer`](../introspection#ERC1820Implementer)
.

Functions

*   [`name()`](#IERC777-name--)
    
*   [`symbol()`](#IERC777-symbol--)
    
*   [`granularity()`](#IERC777-granularity--)
    
*   [`totalSupply()`](#IERC777-totalSupply--)
    
*   [`balanceOf(owner)`](#IERC777-balanceOf-address-)
    
*   [`send(recipient, amount, data)`](#IERC777-send-address-uint256-bytes-)
    
*   [`burn(amount, data)`](#IERC777-burn-uint256-bytes-)
    
*   [`isOperatorFor(operator, tokenHolder)`](#IERC777-isOperatorFor-address-address-)
    
*   [`authorizeOperator(operator)`](#IERC777-authorizeOperator-address-)
    
*   [`revokeOperator(operator)`](#IERC777-revokeOperator-address-)
    
*   [`defaultOperators()`](#IERC777-defaultOperators--)
    
*   [`operatorSend(sender, recipient, amount, data, operatorData)`](#IERC777-operatorSend-address-address-uint256-bytes-bytes-)
    
*   [`operatorBurn(account, amount, data, operatorData)`](#IERC777-operatorBurn-address-uint256-bytes-bytes-)
    

Events

*   [`Sent(operator, from, to, amount, data, operatorData)`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
    
*   [`Minted(operator, to, amount, data, operatorData)`](#IERC777-Minted-address-address-uint256-bytes-bytes-)
    
*   [`Burned(operator, from, amount, data, operatorData)`](#IERC777-Burned-address-address-uint256-bytes-bytes-)
    
*   [`AuthorizedOperator(operator, tokenHolder)`](#IERC777-AuthorizedOperator-address-address-)
    
*   [`RevokedOperator(operator, tokenHolder)`](#IERC777-RevokedOperator-address-address-)
    

#### [](#IERC777-name--)
`name() → string` external

Returns the name of the token.

#### [](#IERC777-symbol--)
`symbol() → string` external

Returns the symbol of the token, usually a shorter version of the name.

#### [](#IERC777-granularity--)
`granularity() → uint256` external

Returns the smallest part of the token that is not divisible. This means all token operations (creation, movement and destruction) must have amounts that are a multiple of this number.

For most token contracts, this value will equal 1.

#### [](#IERC777-totalSupply--)
`totalSupply() → uint256` external

Returns the amount of tokens in existence.

#### [](#IERC777-balanceOf-address-)
`balanceOf(address owner) → uint256` external

Returns the amount of tokens owned by an account (`owner`).

#### [](#IERC777-send-address-uint256-bytes-)
`send(address recipient, uint256 amount, bytes data)` external

Moves `amount` tokens from the caller’s account to `recipient`.

If send or receive hooks are registered for the caller and `recipient`, the corresponding functions will be called with `data` and empty `operatorData`. See [`IERC777Sender`](#IERC777Sender)
 and [`IERC777Recipient`](#IERC777Recipient)
.

Emits a [`Sent`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
 event.

Requirements

*   the caller must have at least `amount` tokens.
    
*   `recipient` cannot be the zero address.
    
*   if `recipient` is a contract, it must implement the [`IERC777Recipient`](#IERC777Recipient)
     interface.
    

#### [](#IERC777-burn-uint256-bytes-)
`burn(uint256 amount, bytes data)` external

Destroys `amount` tokens from the caller’s account, reducing the total supply.

If a send hook is registered for the caller, the corresponding function will be called with `data` and empty `operatorData`. See [`IERC777Sender`](#IERC777Sender)
.

Emits a [`Burned`](#IERC777-Burned-address-address-uint256-bytes-bytes-)
 event.

Requirements

*   the caller must have at least `amount` tokens.
    

#### [](#IERC777-isOperatorFor-address-address-)
`isOperatorFor(address operator, address tokenHolder) → bool` external

Returns true if an account is an operator of `tokenHolder`. Operators can send and burn tokens on behalf of their owners. All accounts are their own operator.

See [`operatorSend`](#IERC777-operatorSend-address-address-uint256-bytes-bytes-)
 and [`operatorBurn`](#IERC777-operatorBurn-address-uint256-bytes-bytes-)
.

#### [](#IERC777-authorizeOperator-address-)
`authorizeOperator(address operator)` external

Make an account an operator of the caller.

See [`isOperatorFor`](#IERC777-isOperatorFor-address-address-)
.

Emits an [`AuthorizedOperator`](#IERC777-AuthorizedOperator-address-address-)
 event.

Requirements

*   `operator` cannot be calling address.
    

#### [](#IERC777-revokeOperator-address-)
`revokeOperator(address operator)` external

Revoke an account’s operator status for the caller.

See [`isOperatorFor`](#IERC777-isOperatorFor-address-address-)
 and [`defaultOperators`](#IERC777-defaultOperators--)
.

Emits a [`RevokedOperator`](#IERC777-RevokedOperator-address-address-)
 event.

Requirements

*   `operator` cannot be calling address.
    

#### [](#IERC777-defaultOperators--)
`defaultOperators() → address[]` external

Returns the list of default operators. These accounts are operators for all token holders, even if [`authorizeOperator`](#IERC777-authorizeOperator-address-)
 was never called on them.

This list is immutable, but individual holders may revoke these via [`revokeOperator`](#IERC777-revokeOperator-address-)
, in which case [`isOperatorFor`](#IERC777-isOperatorFor-address-address-)
 will return false.

#### [](#IERC777-operatorSend-address-address-uint256-bytes-bytes-)
`operatorSend(address sender, address recipient, uint256 amount, bytes data, bytes operatorData)` external

Moves `amount` tokens from `sender` to `recipient`. The caller must be an operator of `sender`.

If send or receive hooks are registered for `sender` and `recipient`, the corresponding functions will be called with `data` and `operatorData`. See [`IERC777Sender`](#IERC777Sender)
 and [`IERC777Recipient`](#IERC777Recipient)
.

Emits a [`Sent`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
 event.

Requirements

*   `sender` cannot be the zero address.
    
*   `sender` must have at least `amount` tokens.
    
*   the caller must be an operator for `sender`.
    
*   `recipient` cannot be the zero address.
    
*   if `recipient` is a contract, it must implement the [`IERC777Recipient`](#IERC777Recipient)
     interface.
    

#### [](#IERC777-operatorBurn-address-uint256-bytes-bytes-)
`operatorBurn(address account, uint256 amount, bytes data, bytes operatorData)` external

Destroys `amount` tokens from `account`, reducing the total supply. The caller must be an operator of `account`.

If a send hook is registered for `account`, the corresponding function will be called with `data` and `operatorData`. See [`IERC777Sender`](#IERC777Sender)
.

Emits a [`Burned`](#IERC777-Burned-address-address-uint256-bytes-bytes-)
 event.

Requirements

*   `account` cannot be the zero address.
    
*   `account` must have at least `amount` tokens.
    
*   the caller must be an operator for `account`.
    

#### [](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
`Sent(address operator, address from, address to, uint256 amount, bytes data, bytes operatorData)` event

#### [](#IERC777-Minted-address-address-uint256-bytes-bytes-)
`Minted(address operator, address to, uint256 amount, bytes data, bytes operatorData)` event

#### [](#IERC777-Burned-address-address-uint256-bytes-bytes-)
`Burned(address operator, address from, uint256 amount, bytes data, bytes operatorData)` event

#### [](#IERC777-AuthorizedOperator-address-address-)
`AuthorizedOperator(address operator, address tokenHolder)` event

#### [](#IERC777-RevokedOperator-address-address-)
`RevokedOperator(address operator, address tokenHolder)` event

### [](#ERC777)
`ERC777`

Implementation of the [`IERC777`](#IERC777)
 interface.

This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using [`_mint`](#ERC777-_mint-address-uint256-bytes-bytes-)
.

Support for ERC20 is included in this contract, as specified by the EIP: both the ERC777 and ERC20 interfaces can be safely used when interacting with it. Both [`IERC777.Sent`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
 and [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 events are emitted on token movements.

Additionally, the [`IERC777.granularity`](#IERC777-granularity--)
 value is hard-coded to `1`, meaning that there are no special restrictions in the amount of tokens that created, moved, or destroyed. This makes integration with ERC20 applications seamless.

Functions

*   [`constructor(name_, symbol_, defaultOperators_)`](#ERC777-constructor-string-string-address---)
    
*   [`name()`](#ERC777-name--)
    
*   [`symbol()`](#ERC777-symbol--)
    
*   [`decimals()`](#ERC777-decimals--)
    
*   [`granularity()`](#ERC777-granularity--)
    
*   [`totalSupply()`](#ERC777-totalSupply--)
    
*   [`balanceOf(tokenHolder)`](#ERC777-balanceOf-address-)
    
*   [`send(recipient, amount, data)`](#ERC777-send-address-uint256-bytes-)
    
*   [`transfer(recipient, amount)`](#ERC777-transfer-address-uint256-)
    
*   [`burn(amount, data)`](#ERC777-burn-uint256-bytes-)
    
*   [`isOperatorFor(operator, tokenHolder)`](#ERC777-isOperatorFor-address-address-)
    
*   [`authorizeOperator(operator)`](#ERC777-authorizeOperator-address-)
    
*   [`revokeOperator(operator)`](#ERC777-revokeOperator-address-)
    
*   [`defaultOperators()`](#ERC777-defaultOperators--)
    
*   [`operatorSend(sender, recipient, amount, data, operatorData)`](#ERC777-operatorSend-address-address-uint256-bytes-bytes-)
    
*   [`operatorBurn(account, amount, data, operatorData)`](#ERC777-operatorBurn-address-uint256-bytes-bytes-)
    
*   [`allowance(holder, spender)`](#ERC777-allowance-address-address-)
    
*   [`approve(spender, value)`](#ERC777-approve-address-uint256-)
    
*   [`transferFrom(holder, recipient, amount)`](#ERC777-transferFrom-address-address-uint256-)
    
*   [`_mint(account, amount, userData, operatorData)`](#ERC777-_mint-address-uint256-bytes-bytes-)
    
*   [`_send(from, to, amount, userData, operatorData, requireReceptionAck)`](#ERC777-_send-address-address-uint256-bytes-bytes-bool-)
    
*   [`_burn(from, amount, data, operatorData)`](#ERC777-_burn-address-uint256-bytes-bytes-)
    
*   [`_approve(holder, spender, value)`](#ERC777-_approve-address-address-uint256-)
    
*   [`_beforeTokenTransfer(operator, from, to, amount)`](#ERC777-_beforeTokenTransfer-address-address-address-uint256-)
    

Events

IERC20

*   [`Transfer(from, to, value)`](ERC20#IERC20-Transfer-address-address-uint256-)
    
*   [`Approval(owner, spender, value)`](ERC20#IERC20-Approval-address-address-uint256-)
    

IERC777

*   [`Sent(operator, from, to, amount, data, operatorData)`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
    
*   [`Minted(operator, to, amount, data, operatorData)`](#IERC777-Minted-address-address-uint256-bytes-bytes-)
    
*   [`Burned(operator, from, amount, data, operatorData)`](#IERC777-Burned-address-address-uint256-bytes-bytes-)
    
*   [`AuthorizedOperator(operator, tokenHolder)`](#IERC777-AuthorizedOperator-address-address-)
    
*   [`RevokedOperator(operator, tokenHolder)`](#IERC777-RevokedOperator-address-address-)
    

#### [](#ERC777-constructor-string-string-address---)
`constructor(string name_, string symbol_, address[] defaultOperators_)` public

`defaultOperators` may be an empty array.

#### [](#ERC777-name--)
`name() → string` public

See [`IERC777.name`](#IERC777-name--)
.

#### [](#ERC777-symbol--)
`symbol() → string` public

See [`IERC777.symbol`](#IERC777-symbol--)
.

#### [](#ERC777-decimals--)
`decimals() → uint8` public

See [`ERC20.decimals`](ERC20#ERC20-decimals--)
.

Always returns 18, as per the \[ERC777 EIP\]([https://eips.ethereum.org/EIPS/eip-777#backward-compatibility](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility)
).

#### [](#ERC777-granularity--)
`granularity() → uint256` public

See [`IERC777.granularity`](#IERC777-granularity--)
.

This implementation always returns `1`.

#### [](#ERC777-totalSupply--)
`totalSupply() → uint256` public

See [`IERC777.totalSupply`](#IERC777-totalSupply--)
.

#### [](#ERC777-balanceOf-address-)
`balanceOf(address tokenHolder) → uint256` public

Returns the amount of tokens owned by an account (`tokenHolder`).

#### [](#ERC777-send-address-uint256-bytes-)
`send(address recipient, uint256 amount, bytes data)` public

See [`IERC777.send`](#IERC777-send-address-uint256-bytes-)
.

Also emits a [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 event for ERC20 compatibility.

#### [](#ERC777-transfer-address-uint256-)
`transfer(address recipient, uint256 amount) → bool` public

See [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
.

Unlike `send`, `recipient` is _not_ required to implement the [`IERC777Recipient`](#IERC777Recipient)
 interface if it is a contract.

Also emits a [`Sent`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
 event.

#### [](#ERC777-burn-uint256-bytes-)
`burn(uint256 amount, bytes data)` public

See [`IERC777.burn`](#IERC777-burn-uint256-bytes-)
.

Also emits a [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 event for ERC20 compatibility.

#### [](#ERC777-isOperatorFor-address-address-)
`isOperatorFor(address operator, address tokenHolder) → bool` public

See [`IERC777.isOperatorFor`](#IERC777-isOperatorFor-address-address-)
.

#### [](#ERC777-authorizeOperator-address-)
`authorizeOperator(address operator)` public

See [`IERC777.authorizeOperator`](#IERC777-authorizeOperator-address-)
.

#### [](#ERC777-revokeOperator-address-)
`revokeOperator(address operator)` public

See [`IERC777.revokeOperator`](#IERC777-revokeOperator-address-)
.

#### [](#ERC777-defaultOperators--)
`defaultOperators() → address[]` public

See [`IERC777.defaultOperators`](#IERC777-defaultOperators--)
.

#### [](#ERC777-operatorSend-address-address-uint256-bytes-bytes-)
`operatorSend(address sender, address recipient, uint256 amount, bytes data, bytes operatorData)` public

See [`IERC777.operatorSend`](#IERC777-operatorSend-address-address-uint256-bytes-bytes-)
.

Emits [`Sent`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
 and [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 events.

#### [](#ERC777-operatorBurn-address-uint256-bytes-bytes-)
`operatorBurn(address account, uint256 amount, bytes data, bytes operatorData)` public

See [`IERC777.operatorBurn`](#IERC777-operatorBurn-address-uint256-bytes-bytes-)
.

Emits [`Burned`](#IERC777-Burned-address-address-uint256-bytes-bytes-)
 and [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 events.

#### [](#ERC777-allowance-address-address-)
`allowance(address holder, address spender) → uint256` public

See [`IERC20.allowance`](ERC20#IERC20-allowance-address-address-)
.

Note that operator and allowance concepts are orthogonal: operators may not have allowance, and accounts with allowance may not be operators themselves.

#### [](#ERC777-approve-address-uint256-)
`approve(address spender, uint256 value) → bool` public

See [`IERC20.approve`](ERC20#IERC20-approve-address-uint256-)
.

Note that accounts cannot have allowance issued by their operators.

#### [](#ERC777-transferFrom-address-address-uint256-)
`transferFrom(address holder, address recipient, uint256 amount) → bool` public

See [`IERC20.transferFrom`](ERC20#IERC20-transferFrom-address-address-uint256-)
.

Note that operator and allowance concepts are orthogonal: operators cannot call `transferFrom` (unless they have allowance), and accounts with allowance cannot call `operatorSend` (unless they are operators).

Emits [`Sent`](#IERC777-Sent-address-address-address-uint256-bytes-bytes-)
, [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 and [`IERC20.Approval`](ERC20#IERC20-Approval-address-address-uint256-)
 events.

#### [](#ERC777-_mint-address-uint256-bytes-bytes-)
`_mint(address account, uint256 amount, bytes userData, bytes operatorData)` internal

Creates `amount` tokens and assigns them to `account`, increasing the total supply.

If a send hook is registered for `account`, the corresponding function will be called with `operator`, `data` and `operatorData`.

See [`IERC777Sender`](#IERC777Sender)
 and [`IERC777Recipient`](#IERC777Recipient)
.

Emits [`Minted`](#IERC777-Minted-address-address-uint256-bytes-bytes-)
 and [`IERC20.Transfer`](ERC20#IERC20-Transfer-address-address-uint256-)
 events.

Requirements

*   `account` cannot be the zero address.
    
*   if `account` is a contract, it must implement the [`IERC777Recipient`](#IERC777Recipient)
     interface.
    

#### [](#ERC777-_send-address-address-uint256-bytes-bytes-bool-)
`_send(address from, address to, uint256 amount, bytes userData, bytes operatorData, bool requireReceptionAck)` internal

Send tokens

#### [](#ERC777-_burn-address-uint256-bytes-bytes-)
`_burn(address from, uint256 amount, bytes data, bytes operatorData)` internal

Burn tokens

#### [](#ERC777-_approve-address-address-uint256-)
`_approve(address holder, address spender, uint256 value)` internal

See [`ERC20._approve`](ERC20#ERC20-_approve-address-address-uint256-)
.

Note that accounts cannot have allowance issued by their operators.

#### [](#ERC777-_beforeTokenTransfer-address-address-address-uint256-)
`_beforeTokenTransfer(address operator, address from, address to, uint256 amount)` internal

Hook that is called before any token transfer. This includes calls to [`send`](#ERC777-send-address-uint256-bytes-)
, [`transfer`](#ERC777-transfer-address-uint256-)
, [`operatorSend`](#ERC777-operatorSend-address-address-uint256-bytes-bytes-)
, minting and burning.

Calling conditions:

*   when `from` and `to` are both non-zero, `amount` of `from`'s tokens will be to transferred to `to`.
    
*   when `from` is zero, `amount` tokens will be minted for `to`.
    
*   when `to` is zero, `amount` of `from`'s tokens will be burned.
    
*   `from` and `to` are never both zero.
    

To learn more about hooks, head to [Using Hooks](../../extending-contracts#using-hooks)
.

[](#hooks)
Hooks
----------------

### [](#IERC777Sender)
`IERC777Sender`

Interface of the ERC777TokensSender standard as defined in the EIP.

[`IERC777`](#IERC777)
 Token holders can be notified of operations performed on their tokens by having a contract implement this interface (contract holders can be their own implementer) and registering it on the [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820)
.

See [`IERC1820Registry`](../introspection#IERC1820Registry)
 and [`ERC1820Implementer`](../introspection#ERC1820Implementer)
.

Functions

*   [`tokensToSend(operator, from, to, amount, userData, operatorData)`](#IERC777Sender-tokensToSend-address-address-address-uint256-bytes-bytes-)
    

#### [](#IERC777Sender-tokensToSend-address-address-address-uint256-bytes-bytes-)
`tokensToSend(address operator, address from, address to, uint256 amount, bytes userData, bytes operatorData)` external

Called by an [`IERC777`](#IERC777)
 token contract whenever a registered holder’s (`from`) tokens are about to be moved or destroyed. The type of operation is conveyed by `to` being the zero address or not.

This call occurs _before_ the token contract’s state is updated, so [`IERC777.balanceOf`](#IERC777-balanceOf-address-)
, etc., can be used to query the pre-operation state.

This function may revert to prevent the operation from being executed.

### [](#IERC777Recipient)
`IERC777Recipient`

Interface of the ERC777TokensRecipient standard as defined in the EIP.

Accounts can be notified of [`IERC777`](#IERC777)
 tokens being sent to them by having a contract implement this interface (contract holders can be their own implementer) and registering it on the [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820)
.

See [`IERC1820Registry`](../introspection#IERC1820Registry)
 and [`ERC1820Implementer`](../introspection#ERC1820Implementer)
.

Functions

*   [`tokensReceived(operator, from, to, amount, userData, operatorData)`](#IERC777Recipient-tokensReceived-address-address-address-uint256-bytes-bytes-)
    

#### [](#IERC777Recipient-tokensReceived-address-address-address-uint256-bytes-bytes-)
`tokensReceived(address operator, address from, address to, uint256 amount, bytes userData, bytes operatorData)` external

Called by an [`IERC777`](#IERC777)
 token contract whenever tokens are being moved or created into a registered account (`to`). The type of operation is conveyed by `from` being the zero address or not.

This call occurs _after_ the token contract’s state is updated, so [`IERC777.balanceOf`](#IERC777-balanceOf-address-)
, etc., can be used to query the post-operation state.

This function may revert to prevent the operation from being executed.

[← ERC 721](/contracts/3.x/api/token/ERC721)

[ERC 1155 →](/contracts/3.x/api/token/ERC1155)




 Migrating ERC165 to SRC5 - OpenZeppelin Docs       

Migrating ERC165 to SRC5
========================

In the smart contract ecosystem, having the ability to query if a contract supports a given interface is an extremely important feature. The initial introspection design for Contracts for Cairo before version v0.7.0 followed Ethereum’s [EIP-165](https://eips.ethereum.org/EIPS/eip-165)
. Since the Cairo language evolved introducing native types, we needed an introspection solution tailored to the Cairo ecosystem: the [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard. SNIP-5 allows interface ID calculations to use Cairo types and the Starknet keccak (`sn_keccak`) function. For more information on the decision, see the [Starknet Shamans proposal](https://community.starknet.io/t/starknet-standard-interface-detection/92664)
 or the [Dual Introspection Detection](https://github.com/OpenZeppelin/cairo-contracts/discussions/640)
 discussion.

[](#how_to_migrate)
How to migrate
----------------------------------

Migrating from ERC165 to SRC5 involves four major steps:

1.  Integrate SRC5 into the contract.
    
2.  Register SRC5 IDs.
    
3.  Add a `migrate` function to apply introspection changes.
    
4.  Upgrade the contract and call `migrate`.
    

The following guide will go through the steps with examples.

### [](#component_integration)
Component integration

The first step is to integrate the necessary components into the new contract. The contract should include the new introspection mechanism, [SRC5Component](../api/introspection#SRC5Component)
. It should also include the [InitializableComponent](../api/security#InitializableComponent)
 which will be used in the `migrate` function. Here’s the setup:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::security::initializable::InitializableComponent;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl SRC5InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        // Initializable
        impl InitializableInternalImpl = InitializableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

### [](#interface_registration)
Interface registration

To successfully migrate ERC165 to SRC5, the contract needs to register the interface IDs that the contract supports with SRC5.

For this example, let’s say that this contract supports the [IERC721](../api/erc721#IERC721)
 and [IERC721Metadata](../api/erc721#IERC721Metadata)
 interfaces. The contract should implement an `InternalImpl` and add a function to register those interfaces like this:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID};
    
        (...)
    
        #[generate_trait]
        impl InternalImpl of InternalTrait {
            // Register SRC5 interfaces
            fn register_src5_interfaces(ref self: ContractState) {
                self.src5.register_interface(IERC721_ID);
                self.src5.register_interface(IERC721_METADATA_ID);
            }
        }
    }

Since the new contract integrates `SRC5Component`, it can leverage SRC5’s [register\_interface](../api/introspection#SRC5Component-register_interface)
 function to register the supported interfaces.

### [](#migration_initializer)
Migration initializer

Next, the contract should define and expose a migration function that will invoke the `register_src5_interfaces` function. Since the `migrate` function will be publicly callable, it should include some sort of [Access Control](../access)
 so that only permitted addresses can execute the migration. Finally, `migrate` should include a reinitialization check to ensure that it cannot be called more than once.

|     |     |
| --- | --- |
|     | If the original contract implemented `Initializable` at any point and called the `initialize` method, the `InitializableComponent` will not be usable at this time. Instead, the contract can take inspiration from `InitializableComponent` and create its own initialization mechanism. |

    #[starknet::contract]
    mod MigratingContract {
        (...)
    
        #[external(v0)]
        fn migrate(ref self: ContractState) {
            // WARNING: Missing Access Control mechanism. Make sure to add one
    
            // WARNING: If the contract ever implemented `Initializable` in the past,
            // this will not work. Make sure to create a new initialization mechanism
            self.initializable.initialize();
    
            // Register SRC5 interfaces
            self.register_src5_interfaces();
        }
    }

### [](#execute_migration)
Execute migration

Once the new contract is prepared for migration and **rigorously tested**, all that’s left is to migrate! Simply upgrade the contract and then call `migrate`.

[← Introspection](/contracts-cairo/0.15.0/introspection)

[API Reference →](/contracts-cairo/0.15.0/api/introspection)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

Reference of interfaces, presets, and utilities related to ERC1155 contracts.

|     |     |
| --- | --- |
|     | For an overview of ERC1155, read our [ERC1155 guide](../erc1155)<br>. |

[](#core)
Core
--------------

### [](#IERC1155)
`IERC1155`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc1155/interface.cairo)

    use openzeppelin::token::erc1155::interface::IERC1155;

Interface of the IERC1155 standard as defined in [EIP1155](https://eips.ethereum.org/EIPS/eip-1155)
.

[SRC5 ID](introspection#ISRC5)

0x6114a8f75559e1b39fcba08ce02961a1aa082d9256a158dd3e64964e4b1b52

Functions

*   [`balance_of(account, token_id)`](#IERC1155-balance_of)
    
*   [`balance_of_batch(accounts, token_ids)`](#IERC1155-balance_of_batch)
    
*   [`safe_transfer_from(from, to, token_id, value, data)`](#IERC1155-safe_transfer_from)
    
*   [`safe_batch_transfer_from(from, to, token_ids, values, data)`](#IERC1155-safe_batch_transfer_from)
    
*   [`set_approval_for_all(operator, approved)`](#IERC1155-set_approval_for_all)
    
*   [`is_approved_for_all(owner, operator)`](#IERC1155-is_approved_for_all)
    

Events

*   [`TransferSingle(operator, from, to, id, value)`](#IERC1155-TransferSingle)
    
*   [`TransferBatch(operator, from, to, ids, values)`](#IERC1155-TransferBatch)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC1155-ApprovalForAll)
    
*   [`URI(value, id)`](#IERC1155-URI)
    

#### [](#functions)
Functions

#### [](#IERC1155-balance_of)
`balance_of(account: ContractAddress, token_id: u256) → u256` external

Returns the amount of `token_id` tokens owned by `account`.

#### [](#IERC1155-balance_of_batch)
`balance_of_batch(accounts: Span<ContractAddress>, token_ids: Span<u256>) → Span<u256>` external

Returns a list of balances derived from the `accounts` and `token_ids` pairs.

#### [](#IERC1155-safe_transfer_from)
`safe_transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256, value: u256, data: Span<felt252>)` external

Transfers ownership of `value` amount of `token_id` from `from` if `to` is either `IERC1155Receiver` or an account.

`data` is additional data, it has no specified format and it is passed to `to`.

Emits a [TransferSingle](#IERC1155-TransferSingle)
 event.

#### [](#IERC1155-safe_batch_transfer_from)
`safe_batch_transfer_from(from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` external

Transfers ownership of `token_ids` and `values` pairs from `from` if `to` is either `IERC1155Receiver` or an account.

`data` is additional data, it has no specified format and it is passed to `to`.

Emits a [TransferBatch](#IERC1155-TransferBatch)
 event.

#### [](#IERC1155-set_approval_for_all)
`set_approval_for_all(operator: ContractAddress, approved: bool)` external

Enables or disables approval for `operator` to manage all of the caller’s assets.

Emits an [ApprovalForAll](#IERC1155-ApprovalForAll)
 event.

#### [](#IERC1155-is_approved_for_all)
`is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool` external

Queries if `operator` is an authorized operator for `owner`.

#### [](#events)
Events

#### [](#IERC1155-TransferSingle)
`TransferSingle(operator: ContractAddress, from: ContractAddress, to: ContractAddress, id: u256, value: u256)` event

Emitted when `value` amount of `id` token is transferred from `from` to `to` through `operator`.

#### [](#IERC1155-TransferBatch)
`TransferBatch(operator: ContractAddress, from: ContractAddress, to: ContractAddress, ids: Span<u256>, values: Span<u256>)` event

Emitted when a batch of `values` amount of `ids` tokens are transferred from `from` to `to` through `operator`.

#### [](#IERC1155-ApprovalForAll)
`ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)` event

Emitted when `owner` enables or disables `operator` to manage all of the owner’s assets.

#### [](#IERC1155-URI)
`URI(value: ByteArray, id: u256)` event

Emitted when the token URI is updated to `value` for the `id` token.

### [](#IERC1155MetadataURI)
`IERC1155MetadataURI`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc1155/interface.cairo)

    use openzeppelin::token::erc1155::interface::IERC1155MetadataURI;

Interface for the optional metadata function in [EIP1155](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

[SRC5 ID](introspection#ISRC5)

0xcabe2400d5fe509e1735ba9bad205ba5f3ca6e062da406f72f113feb889ef7

Functions

*   [`uri(token_id)`](#IERC1155MetadataURI-uri)
    

#### [](#functions_2)
Functions

#### [](#IERC1155MetadataURI-uri)
`uri(token_id: u256) -> ByteArray` external

Returns the Uniform Resource Identifier (URI) for the `token_id` token.

### [](#ERC1155Component)
`ERC1155Component`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc1155/erc1155.cairo)

    use openzeppelin::token::erc1155::ERC1155Component;

ERC1155 component implementing [IERC1155](#IERC1155)
 and [IERC1155MetadataURI](#IERC1155MetadataURI)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

Embeddable Implementations

ERC1155Impl

*   [`balance_of(self, account, token_id)`](#ERC1155Component-balance_of)
    
*   [`balance_of_batch(self, accounts, token_ids)`](#ERC1155Component-balance_of_batch)
    
*   [`safe_transfer_from(self, from, to, token_id, value, data)`](#ERC1155Component-safe_transfer_from)
    
*   [`safe_batch_transfer_from(self, from, to, token_ids, values, data)`](#ERC1155Component-safe_batch_transfer_from)
    
*   [`set_approval_for_all(self, operator, approved)`](#ERC1155Component-set_approval_for_all)
    
*   [`is_approved_for_all(self, owner, operator)`](#ERC1155Component-is_approved_for_all)
    

ERC1155MetadataURIImpl

*   [`uri(self, token_id)`](#ERC1155Component-uri)
    

Embeddable implementations (camelCase)

ER1155CamelImpl

*   [`balanceOf(self, account, tokenId)`](#ERC1155Component-balanceOf)
    
*   [`balanceOfBatch(self, accounts, tokenIds)`](#ERC1155Component-balanceOfBatch)
    
*   [`safeTransferFrom(self, from, to, tokenId, value, data)`](#ERC1155Component-safeTransferFrom)
    
*   [`safeBatchTransferFrom(self, from, to, tokenIds, values, data)`](#ERC1155Component-safeBatchTransferFrom)
    
*   [`setApprovalForAll(self, operator, approved)`](#ERC1155Component-setApprovalForAll)
    
*   [`isApprovedForAll(self, owner, operator)`](#ERC1155Component-isApprovedForAll)
    

Internal Functions

InternalImpl

*   [`initializer(self, base_uri)`](#ERC1155Component-initializer)
    
*   [`update(self, from, to, token_ids, values)`](#ERC1155Component-update)
    
*   [`update_with_acceptance_check(self, from, to, token_ids, values, data)`](#ERC1155Component-update_with_acceptance_check)
    
*   [`mint_with_acceptance_check(self, to, token_id, value, data)`](#ERC1155Component-mint_with_acceptance_check)
    
*   [`batch_mint_with_acceptance_check(self, to, token_ids, values, data)`](#ERC1155Component-batch_mint_with_acceptance_check)
    
*   [`burn(self, from, token_id, value)`](#ERC1155Component-burn)
    
*   [`batch_burn(self, from, token_ids, values)`](#ERC1155Component-batch_burn)
    
*   [`set_base_uri(self, base_uri)`](#ERC1155Component-set_base_uri)
    

Events

IERC1155

*   [`TransferSingle(operator, from, to, id, value)`](#ERC1155Component-TransferSingle)
    
*   [`TransferBatch(operator, from, to, ids, values)`](#ERC1155Component-TransferBatch)
    
*   [`ApprovalForAll(owner, operator, approved)`](#ERC1155Component-ApprovalForAll)
    
*   [`URI(value, id)`](#ERC1155Component-URI)
    

#### [](#embeddable_functions)
Embeddable functions

#### [](#ERC1155Component-balance_of)
`balance_of(self: @ContractState, account: ContractAddress, token_id: u256) → u256` external

Returns the amount of `token_id` tokens owned by `account`.

#### [](#ERC1155Component-balance_of_batch)
`balance_of_batch(self: @ContractState, accounts: Span<ContractAddress>, token_ids: Span<u256>) → Span<u256>` external

Returns a list of balances derived from the `accounts` and `token_ids` pairs.

Requirements:

*   `token_ids` and `accounts` must have the same length.
    

#### [](#ERC1155Component-safe_transfer_from)
`safe_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, value: u256, data: Span<felt252>)` external

Transfers ownership of `value` amount of `token_id` from `from` if `to` is either an account or `IERC1155Receiver`.

`data` is additional data, it has no specified format and it is passed to `to`.

|     |     |
| --- | --- |
|     | This function can potentially allow a reentrancy attack when transferring tokens to an untrusted contract, when invoking `on_ERC1155_received` on the receiver. Ensure to follow the checks-effects-interactions pattern and consider employing reentrancy guards when interacting with untrusted contracts. |

Requirements:

*   Caller is either approved or the `token_id` owner.
    
*   `from` is not the zero address.
    
*   `to` is not the zero address.
    
*   If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_received` and return the required magic value.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event.

#### [](#ERC1155Component-safe_batch_transfer_from)
`safe_batch_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` external

Transfers ownership of `values` and `token_ids` pairs from `from` if `to` is either an account or `IERC1155Receiver`.

`data` is additional data, it has no specified format and it is passed to `to`.

|     |     |
| --- | --- |
|     | This function can potentially allow a reentrancy attack when transferring tokens to an untrusted contract, when invoking `on_ERC1155_batch_received` on the receiver. Ensure to follow the checks-effects-interactions pattern and consider employing reentrancy guards when interacting with untrusted contracts. |

Requirements:

*   Caller is either approved or the `token_id` owner.
    
*   `from` is not the zero address.
    
*   `to` is not the zero address.
    
*   `token_ids` and `values` must have the same length.
    
*   If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` and return the acceptance magic value.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event if the arrays contain one element, and [TransferBatch](#ERC1155Component-TransferBatch)
 otherwise.

#### [](#ERC1155Component-set_approval_for_all)
`set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool)` external

Enables or disables approval for `operator` to manage all of the callers assets.

Requirements:

*   `operator` cannot be the caller.
    

Emits an [ApprovalForAll](#ERC1155Component-ApprovalForAll)
 event.

#### [](#ERC1155Component-is_approved_for_all)
`is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool` external

Queries if `operator` is an authorized operator for `owner`.

#### [](#ERC1155Component-uri)
`uri(self: @ContractState, token_id: u256) -> ByteArray` external

This implementation returns the same URI for **all** token types. It relies on the token type ID substitution mechanism [specified in the EIP](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

Clients calling this function must replace the `{id}` substring with the actual token type ID.

#### [](#camelcase_support)
camelCase Support

#### [](#ERC1155Component-balanceOf)
`balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) → u256` external

See [ERC1155Component::balance\_of](#ERC1155Component-balance_of)
.

#### [](#ERC1155Component-balanceOfBatch)
`balanceOfBatch(self: @ContractState, accounts: Span<ContractAddress>, tokenIds: Span<u256>) → Span<u256>` external

See [ERC1155Component::balance\_of\_batch](#ERC1155Component-balance_of_batch)
.

#### [](#ERC1155Component-safeTransferFrom)
`safeTransferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256, value: u256, data: Span<felt252>)` external

See [ERC1155Component::safe\_transfer\_from](#ERC1155Component-safe_transfer_from)
.

#### [](#ERC1155Component-safeBatchTransferFrom)
`safeBatchTransferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenIds: Span<u256>, values: Span<u256>, data: Span<felt252>)` external

See [ERC1155Component::safe\_batch\_transfer\_from](#ERC1155Component-safe_batch_transfer_from)
.

#### [](#ERC1155Component-setApprovalForAll)
`setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool)` external

See [ERC1155Component::set\_approval\_for\_all](#ERC1155Component-set_approval_for_all)
.

#### [](#ERC1155Component-isApprovedForAll)
`isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool` external

See [ERC1155Component::is\_approved\_for\_all](#ERC1155Component-is_approved_for_all)
.

#### [](#internal_functions)
Internal functions

#### [](#ERC1155Component-initializer)
`initializer(ref self: ContractState, base_uri: ByteArray)` internal

Initializes the contract by setting the token’s base URI as `base_uri`, and registering the supported interfaces. This should only be used inside the contract’s constructor.

#### [](#ERC1155Component-update)
`update(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` internal

Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` (or `to`) is the zero address.

Requirements:

*   `token_ids` and `values` must have the same length.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event if the arrays contain one element, and [TransferBatch](#ERC1155Component-TransferBatch)
 otherwise.

|     |     |
| --- | --- |
|     | The ERC1155 acceptance check is not performed in this function. See [update\_with\_acceptance\_check](#ERC1155Component-update_with_acceptance_check)<br> instead. |

#### [](#ERC1155Component-update_with_acceptance_check)
`update_with_acceptance_check(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` internal

Version of `update` that performs the token acceptance check by calling `onERC1155Received` or `onERC1155BatchReceived` in the receiver if it implements `IERC1155Receiver`, otherwise by checking if it is an account.

Requirements:

*   `to` is either an account contract or supports the `IERC1155Receiver` interface.
    
*   `token_ids` and `values` must have the same length.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event if the arrays contain one element, and [TransferBatch](#ERC1155Component-TransferBatch)
 otherwise.

#### [](#ERC1155Component-mint_with_acceptance_check)
`mint_with_acceptance_check(ref self: ContractState, to: ContractAddress, token_id: u256, value: u256, data: Span<felt252>)` internal

Creates a `value` amount of tokens of type `token_id`, and assigns them to `to`.

Requirements:

*   `to` cannot be the zero address.
    
*   If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_received` and return the acceptance magic value.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event.

#### [](#ERC1155Component-batch_mint_with_acceptance_check)
`batch_mint_with_acceptance_check(ref self: ContractState, to: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data: Span<felt252>)` internal

Batched version of [mint\_with\_acceptance\_check](#ERC1155Component-mint_with_acceptance_check)
.

Requirements:

*   `to` cannot be the zero address.
    
*   `token_ids` and `values` must have the same length.
    
*   If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` and return the acceptance magic value.
    

Emits a [TransferBatch](#ERC1155Component-TransferBatch)
 event.

#### [](#ERC1155Component-burn)
`burn(ref self: ContractState, from: ContractAddress, token_id: u256, value: u256)` internal

Destroys a `value` amount of tokens of type `token_id` from `from`.

Requirements:

*   `from` cannot be the zero address.
    
*   `from` must have at least `value` amount of tokens of type `token_id`.
    

Emits a [TransferSingle](#ERC1155Component-TransferSingle)
 event.

#### [](#ERC1155Component-batch_burn)
`batch_burn(ref self: ContractState, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` internal

Batched version of [burn](#ERC1155Component-burn)
.

Requirements:

*   `from` cannot be the zero address.
    
*   `from` must have at least `value` amount of tokens of type `token_id`.
    
*   `token_ids` and `values` must have the same length.
    

Emits a [TransferBatch](#ERC1155Component-TransferBatch)
 event.

#### [](#ERC1155Component-set_base_uri)
`set_base_uri(ref self: ContractState, base_uri: ByteArray)` internal

Sets a new URI for all token types, by relying on the token type ID substitution mechanism [specified in the EIP](https://eips.ethereum.org/EIPS/eip-1155#metadata)
.

By this mechanism, any occurrence of the `{id}` substring in either the URI or any of the values in the JSON file at said URI will be replaced by clients with the token type ID.

For example, the `https://token-cdn-domain/\{id\}.json` URI would be interpreted by clients as `https://token-cdn-domain/000000000000...000000000000004cce0.json` for token type ID `0x4cce0`.

Because these URIs cannot be meaningfully represented by the `URI` event, this function emits no events.

#### [](#events_2)
Events

#### [](#ERC1155Component-TransferSingle)
`TransferSingle(operator: ContractAddress, from: ContractAddress, to: ContractAddress, id: u256, value: u256)` event

See [IERC1155::TransferSingle](#IERC1155-TransferSingle)
.

#### [](#ERC1155Component-TransferBatch)
`TransferBatch(operator: ContractAddress, from: ContractAddress, to: ContractAddress, ids: Span<u256>, values: Span<u256>)` event

See [IERC1155::TransferBatch](#IERC1155-TransferBatch)
.

#### [](#ERC1155Component-ApprovalForAll)
`ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)` event

See [IERC1155::ApprovalForAll](#IERC1155-ApprovalForAll)
.

#### [](#ERC1155Component-URI)
`URI(value: ByteArray, id: u256)` event

See [IERC1155::URI](#IERC1155-URI)
.

[](#receiver)
Receiver
----------------------

### [](#IERC1155Receiver)
`IERC1155Receiver`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc1155/interface.cairo)

    use openzeppelin::token::erc1155::interface::IERC1155Receiver;

Interface for contracts that support receiving token transfers from `ERC1155` contracts.

[SRC5 ID](introspection#ISRC5)

0x15e8665b5af20040c3af1670509df02eb916375cdf7d8cbaf7bd553a257515e

Functions

*   [`on_erc1155_received(operator, from, token_id, value, data)`](#IERC1155Receiver-on_erc1155_received)
    
*   [`on_erc1155_batch_received(operator, from, token_ids, values, data)`](#IERC1155Receiver-on_erc1155_batch_received)
    

#### [](#functions_3)
Functions

#### [](#IERC1155Receiver-on_erc1155_received)
`on_erc1155_received(operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span<felt252>) -> felt252` external

This function is called whenever an ERC1155 `token_id` token is transferred to this `IERC1155Receiver` implementer via [IERC1155::safe\_transfer\_from](#IERC1155-safe_transfer_from)
 by `operator` from `from`.

#### [](#IERC1155Receiver-on_erc1155_batch_received)
`on_erc1155_batch_received(operator: ContractAddress, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data Span<felt252>) -> felt252` external

This function is called whenever multiple ERC1155 `token_ids` tokens are transferred to this `IERC1155Receiver` implementer via [IERC1155::safe\_batch\_transfer\_from](#IERC1155-safe_batch_transfer_from)
 by `operator` from `from`.

### [](#ERC1155ReceiverComponent)
`ERC1155ReceiverComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/token/erc1155/erc1155_receiver.cairo)

    use openzeppelin::token::erc1155::ERC1155ReceiverComponent;

ERC1155Receiver component implementing [IERC1155Receiver](#IERC1155Receiver)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

Embeddable Implementations

ERC1155ReceiverImpl

*   [`on_erc1155_received(self, operator, from, token_id, value, data)`](#ERC1155ReceiverComponent-on_erc1155_received)
    
*   [`on_erc1155_batch_received(self, operator, from, token_ids, values, data)`](#ERC1155ReceiverComponent-on_erc1155_batch_received)
    

Embeddable implementations (camelCase)

ERC1155ReceiverCamelImpl

*   [`onERC1155Received(self, operator, from, tokenId, value, data)`](#ERC1155ReceiverComponent-onERC1155Received)
    
*   [`onERC1155BatchReceived(self, operator, from, tokenIds, values, data)`](#ERC1155ReceiverComponent-onERC1155BatchReceived)
    

Internal Functions

InternalImpl

*   [`initializer(self)`](#ERC1155ReceiverComponent-initializer)
    

#### [](#embeddable_functions_2)
Embeddable functions

#### [](#ERC1155ReceiverComponent-on_erc1155_received)
`on_erc1155_received(operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span<felt252>) -> felt252` external

Returns the `IERC1155Receiver` interface ID.

#### [](#ERC1155ReceiverComponent-on_erc1155_batch_received)
`on_erc1155_batch_received(operator: ContractAddress, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data Span<felt252>) -> felt252` external

Returns the `IERC1155Receiver` interface ID.

#### [](#camelcase_support_2)
camelCase Support

#### [](#ERC1155ReceiverComponent-onERC1155Received)
`onERC1155Received(operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span<felt252>) -> felt252` external

See [ERC1155ReceiverComponent::on\_erc1155\_received](#ERC1155ReceiverComponent-on_erc1155_received)
.

#### [](#ERC1155ReceiverComponent-onERC1155BatchReceived)
`onERC1155BatchReceived(operator: ContractAddress, from: ContractAddress, token_ids: Span<u256>, values: Span<u256>, data Span<felt252>) -> felt252` external

See [ERC1155ReceiverComponent::on\_erc1155\_batch\_received](#ERC1155ReceiverComponent-on_erc1155_batch_received)
.

#### [](#internal_functions_2)
Internal functions

#### [](#ERC1155ReceiverComponent-initializer)
`initializer(ref self: ContractState)` internal

Registers the `IERC1155Receiver` interface ID as supported through introspection.

[](#presets)
Presets
--------------------

### [](#ERC1155)
`ERC1155`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/presets/erc1155.cairo)

    use openzeppelin::presets::ERC1155;

Basic ERC1155 contract leveraging [ERC1155Component](#ERC1155Component)
.

[Sierra class hash](../presets)

0x0518be7d9fa527c78d6929bf9e638e9c98b6077722e27e9546cc4342e830386e

Constructor

*   [`constructor(self, base_uri, recipient, token_ids, values)`](#ERC1155-constructor)
    

Embedded Implementations

ERC1155Component

*   [`ERC1155Impl`](#ERC1155Component-Embeddable-Impls-ERC1155Impl)
    
*   [`ERC1155MetadataURIImpl`](#ERC1155Component-Embeddable-Impls-ERC1155MetadataURIImpl)
    
*   [`ERC1155CamelImpl`](#ERC1155Component-Embeddable-Impls-ER1155CamelImpl)
    

SRC5Component

*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls-SRC5Impl)
    

#### [](#ERC1155-constructor-section)
Constructor

#### [](#ERC1155-constructor)
`constructor(ref self: ContractState, base_uri: ByteArray, recipient: ContractAddress, token_ids: Span<u256>, values: Span<u256>)` constructor

Sets the `base_uri` for all tokens and registers the supported interfaces. Mints the `values` for `token_ids` tokens to `recipient`.

Requirements:

*   `to` is either an account contract (supporting ISRC6) or supports the `IERC1155Receiver` interface.
    
*   `token_ids` and `values` must have the same length.
    

[← ERC1155](/contracts-cairo/0.10.0/erc1155)

[Upgrades →](/contracts-cairo/0.10.0/upgrades)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

The ERC1155 multi token standard is a specification for [fungibility-agnostic](https://docs.openzeppelin.com/contracts/5.x/tokens#different-kinds-of-tokens)
 token contracts. The ERC1155 library implements an approximation of [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155)
 in Cairo for StarkNet.

[](#multi_token_standard)
Multi Token Standard
----------------------------------------------

The distinctive feature of ERC1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its [balance\_of](api/erc1155#IERC1155-balance_of)
 function differs from ERC20’s and ERC777’s: it has an additional ID argument for the identifier of the token that you want to query the balance of.

This is similar to how ERC721 does things, but in that standard a token ID has no concept of balance: each token is non-fungible and exists or doesn’t. The ERC721 [balance\_of](api/erc721#IERC721-balance_of)
 function refers to how many different tokens an account has, not how many of each. On the other hand, in ERC1155 accounts have a distinct balance for each token ID, and non-fungible tokens are implemented by simply minting a single one of them.

This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC1155 token contract can hold the entire system state, reducing deployment costs and complexity.

[](#usage)
Usage
----------------

Using Contracts for Cairo, constructing an ERC1155 contract requires integrating both `ERC1155Component` and `SRC5Component`. The contract should also set up the constructor to initialize the token’s URI and interface support. Here’s an example of a basic contract:

    #[starknet::contract]
    mod MyERC1155 {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};
        use starknet::ContractAddress;
    
        component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC1155 Mixin
        #[abi(embed_v0)]
        impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl<ContractState>;
        impl ERC1155InternalImpl = ERC1155Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc1155: ERC1155Component::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC1155Event: ERC1155Component::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            token_uri: ByteArray,
            recipient: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>
        ) {
            self.erc1155.initializer(token_uri);
            self
                .erc1155
                .batch_mint_with_acceptance_check(recipient, token_ids, values, array![].span());
        }
    }

[](#interface)
Interface
------------------------

The following interface represents the full ABI of the Contracts for Cairo [ERC1155Component](api/erc1155#ERC1155Component)
. The interface includes the [IERC1155](api/erc1155#IERC1155)
 standard interface and the optional [IERC1155MetadataURI](api/erc1155#IERC1155MetadataURI)
 interface together with [ISRC5](api/introspection#ISRC5)
.

To support older token deployments, as mentioned in [Dual interfaces](interfaces#dual_interfaces)
, the component also includes implementations of the interface written in camelCase.

    #[starknet::interface]
    pub trait ERC1155ABI {
        // IERC1155
        fn balance_of(account: ContractAddress, token_id: u256) -> u256;
        fn balance_of_batch(
            accounts: Span<ContractAddress>, token_ids: Span<u256>
        ) -> Span<u256>;
        fn safe_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_id: u256,
            value: u256,
            data: Span<felt252>
        );
        fn safe_batch_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        );
        fn is_approved_for_all(
            owner: ContractAddress, operator: ContractAddress
        ) -> bool;
        fn set_approval_for_all(operator: ContractAddress, approved: bool);
    
        // IERC1155MetadataURI
        fn uri(token_id: u256) -> ByteArray;
    
        // ISRC5
        fn supports_interface(interface_id: felt252) -> bool;
    
        // IERC1155Camel
        fn balanceOf(account: ContractAddress, tokenId: u256) -> u256;
        fn balanceOfBatch(
            accounts: Span<ContractAddress>, tokenIds: Span<u256>
        ) -> Span<u256>;
        fn safeTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenId: u256,
            value: u256,
            data: Span<felt252>
        );
        fn safeBatchTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenIds: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        );
        fn isApprovedForAll(owner: ContractAddress, operator: ContractAddress) -> bool;
        fn setApprovalForAll(operator: ContractAddress, approved: bool);
    }

[](#erc1155_compatibility)
ERC1155 Compatibility
------------------------------------------------

Although Starknet is not EVM compatible, this implementation aims to be as close as possible to the ERC1155 standard but some differences can still be found, such as:

*   The optional `data` argument in both `safe_transfer_from` and `safe_batch_transfer_from` is implemented as `Span<felt252>`.
    
*   `IERC1155Receiver` compliant contracts must implement SRC5 and register the `IERC1155Receiver` interface ID.
    
*   `IERC1155Receiver::on_erc1155_received` must return that interface ID on success.
    

[](#batch_operations)
Batch operations
--------------------------------------

Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, [balance\_of\_batch](api/erc1155#IERC1155-balance_of_batch)
 and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)
, that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive. We also have [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)
 for non-batch operations.

In the spirit of the standard, we’ve also included batch operations in the non-standard functions, such as [batch\_mint\_with\_acceptance\_check](api/erc1155#ERC1155Component-batch_mint_with_acceptance_check)
.

|     |     |
| --- | --- |
|     | While [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)<br> and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)<br> prevent loss by checking the receiver can handle the tokens, this yields execution to the receiver which can result in a [reentrant call](security#reentrancy_guard)<br>. |

[](#receiving_tokens)
Receiving tokens
--------------------------------------

In order to be sure a non-account contract can safely accept ERC1155 tokens, said contract must implement the `IERC1155Receiver` interface. The recipient contract must also implement the [SRC5](introspection#src5)
 interface which supports interface introspection.

### [](#ierc1155receiver)
IERC1155Receiver

    #[starknet::interface]
    pub trait IERC1155Receiver {
        fn on_erc1155_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_id: u256,
            value: u256,
            data: Span<felt252>
        ) -> felt252;
        fn on_erc1155_batch_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        ) -> felt252;
    }

Implementing the `IERC1155Receiver` interface exposes the [on\_erc1155\_received](api/erc1155#IERC1155Receiver-on_erc1155_received)
 and [on\_erc1155\_batch\_received](api/erc1155#IERC1155Receiver-on_erc1155_batch_received)
 methods. When [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)
 and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)
 are called, they invoke the recipient contract’s `on_erc1155_received` or `on_erc1155_batch_received` methods respectively which **must** return the [IERC1155Receiver interface ID](api/erc1155#IERC1155Receiver)
. Otherwise, the transaction will fail.

|     |     |
| --- | --- |
|     | For information on how to calculate interface IDs, see [Computing the interface ID](introspection#computing_the_interface_id)<br>. |

### [](#creating_a_token_receiver_contract)
Creating a token receiver contract

The Contracts for Cairo [ERC1155ReceiverComponent](api/erc1155#ERC1155ReceiverComponent)
 already returns the correct interface ID for safe token transfers. To integrate the `IERC1155Receiver` interface into a contract, simply include the ABI embed directive to the implementations and add the `initializer` in the contract’s constructor. Here’s an example of a simple token receiver contract:

    #[starknet::contract]
    mod MyTokenReceiver {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc1155::ERC1155ReceiverComponent;
        use starknet::ContractAddress;
    
        component!(path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC1155Receiver Mixin
        #[abi(embed_v0)]
        impl ERC1155ReceiverMixinImpl = ERC1155ReceiverComponent::ERC1155ReceiverMixinImpl<ContractState>;
        impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc1155_receiver: ERC1155ReceiverComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            self.erc1155_receiver.initializer();
        }
    }

[← API Reference](/contracts-cairo/0.15.0/api/erc721)

[API Reference →](/contracts-cairo/0.15.0/api/erc1155)




 ERC721 - OpenZeppelin Docs       

ERC721
======

Reference of interfaces, presets, and utilities related to ERC721 contracts.

|     |     |
| --- | --- |
|     | For an overview of ERC721, read our [ERC721 guide](../erc721)<br>. |

[](#core)
Core
--------------

### [](#IERC721)
`IERC721`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc721/interface.cairo#L13-L31)

    use openzeppelin::token::erc721::interface::IERC721;

Interface of the IERC721 standard as defined in [EIP721](https://eips.ethereum.org/EIPS/eip-721)
.

[SRC5 ID](introspection#ISRC5)

0x33eb2f84c309543403fd69f0d0f363781ef06ef6faeb0131ff16ea3175bd943

Functions

*   [`balance_of(account)`](#IERC721-balance_of)
    
*   [`owner_of(token_id)`](#IERC721-owner_of)
    
*   [`safe_transfer_from(from, to, token_id, data)`](#IERC721-safe_transfer_from)
    
*   [`transfer_from(from, to, token_id)`](#IERC721-transfer_from)
    
*   [`approve(to, token_id)`](#IERC721-approve)
    
*   [`set_approval_for_all(operator, approved)`](#IERC721-set_approval_for_all)
    
*   [`get_approved(token_id)`](#IERC721-get_approved)
    
*   [`is_approved_for_all(owner, operator)`](#IERC721-is_approved_for_all)
    

Events

*   [`Approval(owner, approved, token_id)`](#IERC721-Approval)
    
*   [`ApprovalForAll(owner, operator, approved)`](#IERC721-ApprovalForAll)
    
*   [`Transfer(from, to, token_id)`](#IERC721-Transfer)
    

#### [](#functions)
Functions

#### [](#IERC721-balance_of)
`balance_of(account: ContractAddress) → u256` external

Returns the number of NFTs owned by `account`.

#### [](#IERC721-owner_of)
`owner_of(token_id: u256) → ContractAddress` external

Returns the owner address of `token_id`.

#### [](#IERC721-safe_transfer_from)
`safe_transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)` external

Transfer ownership of `token_id` from `from` to `to`, checking first that `to` is aware of the ERC721 protocol to prevent tokens being locked forever. For information regarding how contracts communicate their awareness of the ERC721 protocol, see [Receiving Tokens](../erc721#receiving_tokens)
.

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#IERC721-transfer_from)
`transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256)` external

Transfer ownership of `token_id` from `from` to `to`.

Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 transfers or else they may be permanently lost. Usage of [IERC721::safe\_transfer\_from](#IERC721-safe_transfer_from)
 prevents loss, though the caller must understand this adds an external call which potentially creates a reentrancy vulnerability.

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#IERC721-approve)
`approve(to: ContractAddress, token_id: u256)` external

Change or reaffirm the approved address for an NFT.

Emits an [Approval](#IERC721-Approval)
 event.

#### [](#IERC721-set_approval_for_all)
`set_approval_for_all(operator: ContractAddress, approved: bool)` external

Enable or disable approval for `operator` to manage all of the caller’s assets.

Emits an [ApprovalForAll](#IERC721-ApprovalForAll)
 event.

#### [](#IERC721-get_approved)
`get_approved(token_id: u256) -> u256` external

Returns the address approved for `token_id`.

#### [](#IERC721-is_approved_for_all)
`is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool` external

Query if `operator` is an authorized operator for `owner`.

#### [](#events)
Events

#### [](#IERC721-Approval)
`Approval(owner: ContractAddress, approved: ContractAddress, token_id: u256)` event

Emitted when `owner` enables `approved` to manage the `token_id` token.

#### [](#IERC721-ApprovalForAll)
`ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)` event

Emitted when `owner` enables or disables `operator` to manage the `token_id` token.

#### [](#IERC721-Transfer)
`Transfer(from: ContractAddress, to: ContractAddress, token_id: u256)` event

Emitted when `token_id` token is transferred from `from` to `to`.

### [](#IERC721Metadata)
`IERC721Metadata`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc721/interface.cairo#L54-L59)

    use openzeppelin::token::erc721::interface::IERC721Metadata;

Interface for the optional metadata functions in [EIP721](https://eips.ethereum.org/EIPS/eip-721)
.

[SRC5 ID](introspection#ISRC5)

0xabbcd595a567dce909050a1038e055daccb3c42af06f0add544fa90ee91f25

Functions

*   [`name()`](#IERC721Metadata-name)
    
*   [`symbol()`](#IERC721Metadata-symbol)
    
*   [`token_uri(token_id)`](#IERC721Metadata-token_uri)
    

#### [](#functions_2)
Functions

#### [](#IERC721Metadata-name)
`name() -> ByteArray` external

Returns the NFT name.

#### [](#IERC721Metadata-symbol)
`symbol() -> ByteArray` external

Returns the NFT ticker symbol.

#### [](#IERC721Metadata-token_uri)
`token_uri(token_id: u256) -> ByteArray` external

Returns the Uniform Resource Identifier (URI) for the `token_id` token. If the URI is not set for `token_id`, the return value will be an empty `ByteArray`.

### [](#ERC721Component)
`ERC721Component`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc721/erc721.cairo#L7)

    use openzeppelin::token::erc721::ERC721Component;

ERC721 component implementing [IERC721](#IERC721)
 and [IERC721Metadata](#IERC721Metadata)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

|     |     |
| --- | --- |
|     | See [Hooks](#ERC721Component-Hooks)<br> to understand how are hooks used. |

Hooks

ERC721HooksTrait

*   [`before_update(self, to, token_id, auth)`](#ERC721Component-before_update)
    
*   [`after_update(self, to, token_id, auth)`](#ERC721Component-after_update)
    

[Embeddable Mixin Implementations](../components#mixins)

ERC721MixinImpl

*   [`ERC721Impl`](#ERC721Component-Embeddable-Impls-ERC721Impl)
    
*   [`ERC721MetadataImpl`](#ERC721Component-Embeddable-Impls-ERC721MetadataImpl)
    
*   [`ERC721CamelOnlyImpl`](#ERC721Component-Embeddable-Impls-ERC721CamelOnlyImpl)
    
*   [`ERC721MetadataCamelOnlyImpl`](#ERC721Component-Embeddable-Impls-ERC721MetadataCamelOnlyImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

ERC721Impl

*   [`balance_of(self, account)`](#ERC721Component-balance_of)
    
*   [`owner_of(self, token_id)`](#ERC721Component-owner_of)
    
*   [`safe_transfer_from(self, from, to, token_id, data)`](#ERC721Component-safe_transfer_from)
    
*   [`transfer_from(self, from, to, token_id)`](#ERC721Component-transfer_from)
    
*   [`approve(self, to, token_id)`](#ERC721Component-approve)
    
*   [`set_approval_for_all(self, operator, approved)`](#ERC721Component-set_approval_for_all)
    
*   [`get_approved(self, token_id)`](#ERC721Component-get_approved)
    
*   [`is_approved_for_all(self, owner, operator)`](#ERC721Component-is_approved_for_all)
    

ERC721MetadataImpl

*   [`name(self)`](#ERC721Component-name)
    
*   [`symbol(self)`](#ERC721Component-symbol)
    
*   [`token_uri(self, token_id)`](#ERC721Component-token_uri)
    

ERC721CamelOnlyImpl

*   [`balanceOf(self, account)`](#ERC721Component-balanceOf)
    
*   [`ownerOf(self, tokenId)`](#ERC721Component-ownerOf)
    
*   [`safeTransferFrom(self, from, to, tokenId, data)`](#ERC721Component-safeTransferFrom)
    
*   [`transferFrom(self, from, to, tokenId)`](#ERC721Component-transferFrom)
    
*   [`setApprovalForAll(self, operator, approved)`](#ERC721Component-setApprovalForAll)
    
*   [`getApproved(self, tokenId)`](#ERC721Component-getApproved)
    
*   [`isApprovedForAll(self, owner, operator)`](#ERC721Component-isApprovedForAll)
    

ERC721MetadataCamelOnlyImpl

*   [`tokenURI(self, tokenId)`](#ERC721Component-tokenURI)
    

SRC5Impl

*   [`supports_interface(self, interface_id: felt252)`](introspection#ISRC5-supports_interface)
    

Internal functions

InternalImpl

*   [`initializer(self, name, symbol, base_uri)`](#ERC721Component-initializer)
    
*   [`exists(self, token_id)`](#ERC721Component-exists)
    
*   [`transfer(self, from, to, token_id)`](#ERC721Component-transfer)
    
*   [`mint(self, to, token_id)`](#ERC721Component-mint)
    
*   [`safe_transfer(self, from, to, token_id, data)`](#ERC721Component-safe_transfer)
    
*   [`safe_mint(self, to, token_id, data)`](#ERC721Component-safe_mint)
    
*   [`burn(self, token_id)`](#ERC721Component-burn)
    
*   [`update(self, to, token_id, auth)`](#ERC721Component-update)
    
*   [`_owner_of(self, token_id)`](#ERC721Component-_owner_of)
    
*   [`_require_owned(self, token_id)`](#ERC721Component-_require_owned)
    
*   [`_approve(self, to, token_id, auth)`](#ERC721Component-_approve)
    
*   [`_approve_with_optional_event(self, to, token_id, auth, emit_event)`](#ERC721Component-_approve_with_optional_event)
    
*   [`_set_approval_for_all(self, owner, operator, approved)`](#ERC721Component-_set_approval_for_all)
    
*   [`_set_base_uri(self, base_uri)`](#ERC721Component-_set_base_uri)
    
*   [`_base_uri(self)`](#ERC721Component-_base_uri)
    
*   [`_is_authorized(self, owner, spender, token_id)`](#ERC721Component-_is_authorized)
    
*   [`_check_authorized(self, owner, spender, token_id)`](#ERC721Component-_check_authorized)
    

Events

IERC721

*   [`Approval(owner, approved, token_id)`](#ERC721Component-Approval)
    
*   [`ApprovalForAll(owner, operator, approved)`](#ERC721Component-ApprovalForAll)
    
*   [`Transfer(from, to, token_id)`](#ERC721Component-Transfer)
    

#### [](#ERC721Component-Hooks)
Hooks

Hooks are functions which implementations can extend the functionality of the component source code. Every contract using ERC721Component is expected to provide an implementation of the ERC721HooksTrait. For basic token contracts, an empty implementation with no logic must be provided.

|     |     |
| --- | --- |
|     | You can use `openzeppelin::token::erc721::ERC721HooksEmptyImpl` which is already available as part of the library for this purpose. |

#### [](#ERC721Component-before_update)
`before_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)` hook

Function executed at the beginning of the [update](#ERC721Component-update)
 function prior to any other logic.

#### [](#ERC721Component-after_update)
`after_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)` hook

Function executed at the end of the [update](#ERC721Component-update)
 function.

#### [](#embeddable_functions)
Embeddable functions

#### [](#ERC721Component-balance_of)
`balance_of(self: @ContractState, account: ContractAddress) → u256` external

See [IERC721::balance\_of](#IERC721-balance_of)
.

#### [](#ERC721Component-owner_of)
`owner_of(self: @ContractState, token_id: u256) → ContractAddress` external

See [IERC721::owner\_of](#IERC721-owner_of)
.

Requirements:

*   `token_id` exists.
    

#### [](#ERC721Component-safe_transfer_from)
`safe_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)` external

See [IERC721::safe\_transfer\_from](#IERC721-safe_transfer_from)
.

Requirements:

*   Caller is either approved or the `token_id` owner.
    
*   `to` is not the zero address.
    
*   `from` is not the zero address.
    
*   `token_id` exists.
    
*   `to` is either an account contract or supports the [IERC721Receiver](#IERC721Receiver)
     interface.
    

#### [](#ERC721Component-transfer_from)
`transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)` external

See [IERC721::transfer\_from](#IERC721-transfer_from)
.

Requirements:

*   Caller either approved or the `token_id` owner.
    
*   `to` is not the zero address.
    
*   `from` is not the zero address.
    
*   `token_id` exists.
    

#### [](#ERC721Component-approve)
`approve(ref self: ContractState, to: ContractAddress, token_id: u256)` external

See [IERC721::approve](#IERC721-approve)
.

Requirements:

*   The caller is either an approved operator or the `token_id` owner.
    
*   `to` cannot be the token owner or the zero address.
    
*   `token_id` exists.
    

#### [](#ERC721Component-set_approval_for_all)
`set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool)` external

See [IERC721::set\_approval\_for\_all](#IERC721-set_approval_for_all)
.

Requirements:

*   `operator` is not the zero address.
    

#### [](#ERC721Component-get_approved)
`get_approved(self: @ContractState, token_id: u256) -> u256` external

See [IERC721::get\_approved](#IERC721-get_approved)
.

Requirements:

*   `token_id` exists.
    

#### [](#ERC721Component-is_approved_for_all)
`is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool` external

See [IERC721::is\_approved\_for\_all](#IERC721-is_approved_for_all)
.

#### [](#ERC721Component-name)
`name(self: @ContractState) -> ByteArray` external

See [IERC721Metadata::name](#IERC721Metadata-name)
.

#### [](#ERC721Component-symbol)
`symbol(self: @ContractState) -> ByteArray` external

See [IERC721Metadata::symbol](#IERC721Metadata-symbol)
.

#### [](#ERC721Component-token_uri)
`token_uri(self: @ContractState, token_id: u256) -> ByteArray` external

Returns the Uniform Resource Identifier (URI) for the `token_id` token. If a base URI is set, the resulting URI for each token will be the concatenation of the base URI and the token ID. For example, the base URI `https://token-cdn-domain/` would be returned as `https://token-cdn-domain/123` for token ID `123`.

If the URI is not set for `token_id`, the return value will be an empty `ByteArray`.

#### [](#ERC721Component-balanceOf)
`balanceOf(self: @ContractState, account: ContractAddress) -> u256` external

See [ERC721Component::balance\_of](#ERC721Component-balance_of)
.

#### [](#ERC721Component-ownerOf)
`ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress` external

See [ERC721Component::owner\_of](#ERC721Component-owner_of)
.

#### [](#ERC721Component-safeTransferFrom)
`safeTransferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256, data: Span<felt252>)` external

See [ERC721Component::safe\_transfer\_from](#ERC721Component-safe_transfer_from)
.

#### [](#ERC721Component-transferFrom)
`transferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256)` external

See [ERC721Component::transfer\_from](#ERC721Component-transfer_from)
.

#### [](#ERC721Component-setApprovalForAll)
`setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool)` external

See [ERC721Component::set\_approval\_for\_all](#ERC721Component-set_approval_for_all)
.

#### [](#ERC721Component-getApproved)
`getApproved(self: @ContractState, tokenId: u256) -> ContractAddress` external

See [ERC721Component::get\_approved](#ERC721Component-get_approved)
.

#### [](#ERC721Component-isApprovedForAll)
`isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool` external

See [ERC721Component::is\_approved\_for\_all](#ERC721Component-is_approved_for_all)
.

#### [](#ERC721Component-tokenURI)
`tokenURI(self: @ContractState, tokenId: u256) -> ByteArray` external

See [ERC721Component::token\_uri](#ERC721Component-token_uri)
.

#### [](#internal_functions)
Internal functions

#### [](#ERC721Component-initializer)
`initializer(ref self: ContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray)` internal

Initializes the contract by setting the token name and symbol. This should be used inside the contract’s constructor.

#### [](#ERC721Component-exists)
`exists(self: @ContractState, token_id: u256) -> bool` internal

Internal function that returns whether `token_id` exists.

Tokens start existing when they are minted ([mint](#ERC721-mint)
), and stop existing when they are burned ([burn](#ERC721-burn)
).

#### [](#ERC721Component-transfer)
`transfer(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)` internal

Transfers `token_id` from `from` to `to`.

Internal function without access restriction.

|     |     |
| --- | --- |
|     | This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. |

Requirements:

*   `to` is not the zero address.
    
*   `from` is the token owner.
    
*   `token_id` exists.
    

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#ERC721Component-mint)
`mint(ref self: ContractState, to: ContractAddress, token_id: u256)` internal

Mints `token_id` and transfers it to `to`. Internal function without access restriction.

|     |     |
| --- | --- |
|     | This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. |

Requirements:

*   `to` is not the zero address.
    
*   `token_id` does not exist.
    

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#ERC721Component-safe_transfer)
`safe_transfer(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)` internal

Transfers ownership of `token_id` from `from` if `to` is either an account or `IERC721Receiver`.

`data` is additional data, it has no specified format and is forwarded in `IERC721Receiver::on_erc721_received` to `to`.

|     |     |
| --- | --- |
|     | This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. |

Requirements:

*   `to` cannot be the zero address.
    
*   `from` must be the token owner.
    
*   `token_id` exists.
    
*   `to` is either an account contract or supports the `IERC721Receiver` interface.
    

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#ERC721Component-safe_mint)
`safe_mint(ref self: ContractState, to: ContractAddress, token_id: u256, data: Span<felt252>)` internal

Mints `token_id` if `to` is either an account or `IERC721Receiver`.

`data` is additional data, it has no specified format and is forwarded in `IERC721Receiver::on_erc721_received` to `to`.

|     |     |
| --- | --- |
|     | This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. |

Requirements:

*   `token_id` does not exist.
    
*   `to` is either an account contract or supports the `IERC721Receiver` interface.
    

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#ERC721Component-burn)
`burn(ref self: ContractState, token_id: u256)` internal

Destroys `token_id`. The approval is cleared when the token is burned.

This internal function does not check if the caller is authorized to operate on the token.

Requirements:

*   `token_id` exists.
    

Emits a [Transfer](#IERC721-Transfer)
 event.

#### [](#ERC721Component-update)
`update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)` internal

Transfers `token_id` from its current owner to `to`, or alternatively mints (or burns) if the current owner (or `to`) is the zero address. Returns the owner of the `token_id` before the update.

The `auth` argument is optional. If the value passed is non-zero, then this function will check that `auth` is either the owner of the token, or approved to operate on the token (by the owner).

Emits a [Transfer](#IERC721-Transfer)
 event.

|     |     |
| --- | --- |
|     | This function can be extended using the `ERC721HooksTrait`, to add functionality before and/or after the transfer, mint, or burn. |

#### [](#ERC721Component-_owner_of)
`_owner_of(self: @ContractState, token_id: felt252) -> ContractAddress` internal

Internal function that returns the owner address of `token_id`.

#### [](#ERC721Component-_require_owned)
`_require_owned(self: @ContractState, token_id: felt252) -> ContractAddress` internal

Version of [\_owner\_of](#ERC721Component-_owner_of)
 that panics if owner is the zero address.

#### [](#ERC721Component-_approve)
`_approve(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)` internal

Approve `to` to operate on `token_id`

The `auth` argument is optional. If the value passed is non-zero, then this function will check that `auth` is either the owner of the token, or approved to operate on all tokens held by this owner.

Emits an [Approval](#IERC721-Approval)
 event.

#### [](#ERC721Component-_approve_with_optional_event)
`_approve_with_optional_event(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress, emit_event: bool)` internal

Variant of [\_approve](#ERC721Component-_approve)
 with an optional flag to enable or disable the `Approval` event. The event is not emitted in the context of transfers.

|     |     |
| --- | --- |
|     | If `auth` is zero and `emit_event` is false, this function will not check that the token exists. |

Requirements:

*   if `auth` is non-zero, it must be either the owner of the token or approved to operate on all of its tokens.
    

May emit an [Approval](#IERC721-Approval)
 event.

#### [](#ERC721Component-_set_approval_for_all)
`_set_approval_for_all(ref self: ContractState, owner: ContractAddress, operator: ContractAddress, approved: bool)` internal

Enables or disables approval for `operator` to manage all of the `owner` assets.

Requirements:

*   `operator` is not the zero address.
    

Emits an [Approval](#IERC721-Approval)
 event.

#### [](#ERC721Component-_set_base_uri)
`_set_base_uri(ref self: ContractState, base_uri: ByteArray)` internal

Internal function that sets the `base_uri`.

#### [](#ERC721Component-_base_uri)
`_base_uri(self: @ContractState) -> ByteArray` internal

Base URI for computing [token\_uri](#IERC721Metadata-token_uri)
.

If set, the resulting URI for each token will be the concatenation of the base URI and the token ID. Returns an empty `ByteArray` if not set.

#### [](#ERC721Component-_is_authorized)
`_is_authorized(self: @ContractState, owner: ContractAddress, spender: ContractAddress, token_id: u256) -> bool` internal

Returns whether `spender` is allowed to manage `owner`'s tokens, or `token_id` in particular (ignoring whether it is owned by `owner`).

|     |     |
| --- | --- |
|     | This function assumes that `owner` is the actual owner of `token_id` and does not verify this assumption. |

#### [](#ERC721Component-_check_authorized)
`_check_authorized(self: @ContractState, owner: ContractAddress, spender: ContractAddress, token_id: u256) -> bool` internal

Checks if `spender` can operate on `token_id`, assuming the provided `owner` is the actual owner.

Requirements:

*   `owner` cannot be the zero address.
    
*   `spender` cannot be the zero address.
    
*   `spender` must be the owner of `token_id` or be approved to operate on it.
    

|     |     |
| --- | --- |
|     | This function assumes that `owner` is the actual owner of `token_id` and does not verify this assumption. |

#### [](#events_2)
Events

#### [](#ERC721Component-Approval)
`Approval(owner: ContractAddress, approved: ContractAddress, token_id: u256)` event

See [IERC721::Approval](#IERC721-Approval)
.

#### [](#ERC721Component-ApprovalForAll)
`ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)` event

See [IERC721::ApprovalForAll](#IERC721-ApprovalForAll)
.

#### [](#ERC721Component-Transfer)
`Transfer(from: ContractAddress, to: ContractAddress, token_id: u256)` event

See [IERC721::Transfer](#IERC721-Transfer)
.

[](#receiver)
Receiver
----------------------

### [](#IERC721Receiver)
`IERC721Receiver`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc721/interface.cairo#L70-L79)

    use openzeppelin::token::erc721::interface::IERC721Receiver;

Interface for contracts that support receiving `safe_transfer_from` transfers.

[SRC5 ID](introspection#ISRC5)

0x3a0dff5f70d80458ad14ae37bb182a728e3c8cdda0402a5daa86620bdf910bc

Functions

*   [`on_erc721_received(operator, from, token_id, data)`](#IERC721Receiver-on_erc721_received)
    

#### [](#functions_3)
Functions

#### [](#IERC721Receiver-on_erc721_received)
`on_erc721_received(operator: ContractAddress, from: ContractAddress, token_id: u256, data: Span<felt252>) -> felt252` external

Whenever an IERC721 `token_id` token is transferred to this non-account contract via [IERC721::safe\_transfer\_from](#IERC721-safe_transfer_from)
 by `operator` from `from`, this function is called.

### [](#ERC721ReceiverComponent)
`ERC721ReceiverComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc721/erc721_receiver.cairo)

    use openzeppelin::token::erc721::ERC721ReceiverComponent;

ERC721Receiver component implementing [IERC721Receiver](#IERC721Receiver)
.

|     |     |
| --- | --- |
|     | Implementing [SRC5Component](introspection#SRC5Component)<br> is a requirement for this component to be implemented. |

[Embeddable Mixin Implementations](../components#mixins)

ERCReceiverMixinImpl

*   [`ERC721ReceiverImpl`](#ERC721ReceiverComponent-Embeddable-Impls-ERC721ReceiverImpl)
    
*   [`ERC721ReceiverCamelImpl`](#ERC721ReceiverComponent-Embeddable-Impls-ERC721ReceiverCamelImpl)
    
*   [`SRC5Impl`](introspection#SRC5Component-Embeddable-Impls)
    

Embeddable Implementations

ERC721ReceiverImpl

*   [`on_erc721_received(self, operator, from, token_id, data)`](#ERC721ReceiverComponent-on_erc721_received)
    

ERC721ReceiverCamelImpl

*   [`onERC721Received(self, operator, from, tokenId, data)`](#ERC721ReceiverComponent-onERC721Received)
    

Internal Functions

InternalImpl

*   [`initializer(self)`](#ERC721ReceiverComponent-initializer)
    

#### [](#embeddable_functions_2)
Embeddable functions

#### [](#ERC721ReceiverComponent-on_erc721_received)
`on_erc721_received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span<felt252>) -> felt252` external

Returns the `IERC721Receiver` interface ID.

#### [](#ERC721ReceiverComponent-onERC721Received)
`onERC721Received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span<felt252>) -> felt252` external

See [ERC721ReceiverComponent::on\_erc721\_received](#ERC721ReceiverComponent-on_erc721_received)
.

#### [](#internal_functions_2)
Internal functions

#### [](#ERC721ReceiverComponent-initializer)
`initializer(ref self: ContractState)` internal

Registers the `IERC721Receiver` interface ID as supported through introspection.

[](#presets)
Presets
--------------------

### [](#ERC721Upgradeable)
`ERC721Upgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/presets/erc721.cairo)

    use openzeppelin::presets::ERC721Upgradeable;

Upgradeable ERC721 contract leveraging [ERC721Component](#ERC721Component)
.

[Sierra class hash](../presets)

0x022e2c5b978e1decf9d03a34e3985d340664a15a2acd6f116c684d4055e6911d

Constructor

*   [`constructor(self, name, symbol, recipient, token_ids, base_uri, owner)`](#ERC721Upgradeable-constructor)
    

Embedded Implementations

ERC721MixinImpl

*   [`ERC721MixinImpl`](#ERC721Component-Embeddable-Mixin-Impl)
    

OwnableMixinImpl

*   [`OwnableMixinImpl`](access#OwnableComponent-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#ERC721Upgradeable-upgrade)
    

#### [](#ERC721Upgradeable-constructor-section)
Constructor

#### [](#ERC721Upgradeable-constructor)
`constructor(ref self: ContractState, name: ByteArray, symbol: ByteArray, recipient: ContractAddress, token_ids: Span<u256>, base_uri: ByteArray, owner: ContractAddress)` constructor

Sets the `name` and `symbol`. Mints `token_ids` tokens to `recipient` and sets the `base_uri`. Assigns `owner` as the contract owner with permissions to upgrade.

#### [](#ERC721Upgradeable-external-functions)
External functions

#### [](#ERC721Upgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the contract owner.
    
*   `new_class_hash` cannot be zero.
    

[← ERC721](/contracts-cairo/0.15.0/erc721)

[ERC1155 →](/contracts-cairo/0.15.0/erc1155)




 Migrating ERC165 to SRC5 - OpenZeppelin Docs       

Migrating ERC165 to SRC5
========================

In the smart contract ecosystem, having the ability to query if a contract supports a given interface is an extremely important feature. The initial introspection design for Contracts for Cairo before version v0.7.0 followed Ethereum’s [EIP-165](https://eips.ethereum.org/EIPS/eip-165)
. Since the Cairo language evolved introducing native types, we needed an introspection solution tailored to the Cairo ecosystem: the [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard. SNIP-5 allows interface ID calculations to use Cairo types and the Starknet keccak (`sn_keccak`) function. For more information on the decision, see the [Starknet Shamans proposal](https://community.starknet.io/t/starknet-standard-interface-detection/92664)
 or the [Dual Introspection Detection](https://github.com/OpenZeppelin/cairo-contracts/discussions/640)
 discussion.

[](#how_to_migrate)
How to migrate
----------------------------------

Migrating from ERC165 to SRC5 involves four major steps:

1.  Integrate SRC5 into the contract.
    
2.  Register SRC5 IDs.
    
3.  Add a `migrate` function to apply introspection changes.
    
4.  Upgrade the contract and call `migrate`.
    

The following guide will go through the steps with examples.

### [](#component_integration)
Component integration

The first step is to integrate the necessary components into the new contract. The contract should include the new introspection mechanism, [SRC5Component](../api/introspection#SRC5Component)
. It should also include the [InitializableComponent](../api/security#InitializableComponent)
 which will be used in the `migrate` function. Here’s the setup:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::security::initializable::InitializableComponent;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl SRC5InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        // Initializable
        impl InitializableInternalImpl = InitializableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

### [](#interface_registration)
Interface registration

To successfully migrate ERC165 to SRC5, the contract needs to register the interface IDs that the contract supports with SRC5.

For this example, let’s say that this contract supports the [IERC721](../api/erc721#IERC721)
 and [IERC721Metadata](../api/erc721#IERC721Metadata)
 interfaces. The contract should implement an `InternalImpl` and add a function to register those interfaces like this:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID};
    
        (...)
    
        #[generate_trait]
        impl InternalImpl of InternalTrait {
            // Register SRC5 interfaces
            fn register_src5_interfaces(ref self: ContractState) {
                self.src5.register_interface(IERC721_ID);
                self.src5.register_interface(IERC721_METADATA_ID);
            }
        }
    }

Since the new contract integrates `SRC5Component`, it can leverage SRC5’s [register\_interface](../api/introspection#SRC5Component-register_interface)
 function to register the supported interfaces.

### [](#migration_initializer)
Migration initializer

Next, the contract should define and expose a migration function that will invoke the `register_src5_interfaces` function. Since the `migrate` function will be publicly callable, it should include some sort of [Access Control](../access)
 so that only permitted addresses can execute the migration. Finally, `migrate` should include a reinitialization check to ensure that it cannot be called more than once.

|     |     |
| --- | --- |
|     | If the original contract implemented `Initializable` at any point and called the `initialize` method, the `InitializableComponent` will not be usable at this time. Instead, the contract can take inspiration from `InitializableComponent` and create its own initialization mechanism. |

    #[starknet::contract]
    mod MigratingContract {
        (...)
    
        #[external(v0)]
        fn migrate(ref self: ContractState) {
            // WARNING: Missing Access Control mechanism. Make sure to add one
    
            // WARNING: If the contract ever implemented `Initializable` in the past,
            // this will not work. Make sure to create a new initialization mechanism
            self.initializable.initialize();
    
            // Register SRC5 interfaces
            self.register_src5_interfaces();
        }
    }

### [](#execute_migration)
Execute migration

Once the new contract is prepared for migration and **rigorously tested**, all that’s left is to migrate! Simply upgrade the contract and then call `migrate`.

[← Introspection](/contracts-cairo/0.13.0/introspection)

[API Reference →](/contracts-cairo/0.13.0/api/introspection)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

The ERC1155 multi token standard is a specification for [fungibility-agnostic](https://docs.openzeppelin.com/contracts/5.x/tokens#different-kinds-of-tokens)
 token contracts. The ERC1155 library implements an approximation of [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155)
 in Cairo for StarkNet.

[](#multi_token_standard)
Multi Token Standard
----------------------------------------------

The distinctive feature of ERC1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its [balance\_of](api/erc1155#IERC1155-balance_of)
 function differs from ERC20’s and ERC777’s: it has an additional ID argument for the identifier of the token that you want to query the balance of.

This is similar to how ERC721 does things, but in that standard a token ID has no concept of balance: each token is non-fungible and exists or doesn’t. The ERC721 [balance\_of](api/erc721#IERC721-balance_of)
 function refers to how many different tokens an account has, not how many of each. On the other hand, in ERC1155 accounts have a distinct balance for each token ID, and non-fungible tokens are implemented by simply minting a single one of them.

This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC1155 token contract can hold the entire system state, reducing deployment costs and complexity.

[](#interface)
Interface
------------------------

The following interface represents the full ABI of the Contracts for Cairo [ERC1155Component](api/erc1155#ERC1155Component)
. The interface includes the [IERC1155](api/erc1155#IERC1155)
 standard interface and the optional [IERC1155MetadataURI](api/erc1155#IERC1155MetadataURI)
 interface together with [ISRC5](api/introspection#ISRC5)
.

To support older token deployments, as mentioned in [Dual interfaces](interfaces#dual_interfaces)
, the component also includes implementations of the interface written in camelCase.

    trait ERC1155ABI {
        // IERC1155
        fn balance_of(account: ContractAddress, token_id: u256) -> u256;
        fn balance_of_batch(
            accounts: Span<ContractAddress>, token_ids: Span<u256>
        ) -> Span<u256>;
        fn safe_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_id: u256,
            value: u256,
            data: Span<felt252>
        );
        fn safe_batch_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        );
        fn is_approved_for_all(
            owner: ContractAddress, operator: ContractAddress
        ) -> bool;
        fn set_approval_for_all(operator: ContractAddress, approved: bool);
    
        // IERC1155MetadataURI
        fn uri(token_id: u256) -> ByteArray;
    
        // ISRC5
        fn supports_interface(interface_id: felt252) -> bool;
    
        // IERC1155Camel
        fn balanceOf(account: ContractAddress, tokenId: u256) -> u256;
        fn balanceOfBatch(
            accounts: Span<ContractAddress>, tokenIds: Span<u256>
        ) -> Span<u256>;
        fn safeTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenId: u256,
            value: u256,
            data: Span<felt252>
        );
        fn safeBatchTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenIds: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        );
        fn isApprovedForAll(owner: ContractAddress, operator: ContractAddress) -> bool;
        fn setApprovalForAll(operator: ContractAddress, approved: bool);
    }

### [](#erc1155_compatibility)
ERC1155 Compatibility

Although Starknet is not EVM compatible, this implementation aims to be as close as possible to the ERC1155 standard but some differences can still be found, such as:

*   The optional `data` argument in both `safe_transfer_from` and `safe_batch_transfer_from` is implemented as `Span<felt252>`.
    
*   `IERC1155Receiver` compliant contracts must implement SRC5 and register the `IERC1155Receiver` interface ID.
    
*   `IERC1155Receiver::on_erc1155_received` must return that interface ID on success.
    

[](#usage)
Usage
----------------

Using Contracts for Cairo, constructing an ERC1155 contract requires integrating both `ERC1155Component` and `SRC5Component`. The contract should also set up the constructor to initialize the token’s URI and interface support. Here’s an example of a basic contract:

    #[starknet::contract]
    mod MyERC1155 {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc1155::ERC1155Component;
        use starknet::ContractAddress;
    
        component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC1155
        #[abi(embed_v0)]
        impl ERC1155Impl = ERC1155Component::ERC1155Impl<ContractState>;
        #[abi(embed_v0)]
        impl ERC1155MetadataURIImpl =
            ERC1155Component::ERC1155MetadataURIImpl<ContractState>;
        #[abi(embed_v0)]
        impl ERC1155Camel = ERC1155Component::ERC1155CamelImpl<ContractState>;
        impl ERC1155InternalImpl = ERC1155Component::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc1155: ERC1155Component::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC1155Event: ERC1155Component::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            token_uri: ByteArray,
            recipient: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>
        ) {
            self.erc1155.initializer(token_uri);
            self
                .erc1155
                .batch_mint_with_acceptance_check(recipient, token_ids, values, array![].span());
        }
    }

### [](#batch_operations)
Batch operations

Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, [balance\_of\_batch](api/erc1155#IERC1155-balance_of_batch)
 and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)
, that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive. We also have [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)
 for non-batch operations.

In the spirit of the standard, we’ve also included batch operations in the non-standard functions, such as [batch\_mint\_with\_acceptance\_check](api/erc1155#ERC1155Component-batch_mint_with_acceptance_check)
.

|     |     |
| --- | --- |
|     | While [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)<br> and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)<br> prevent loss by checking the receiver can handle the tokens, this yields execution to the receiver which can result in a [reentrant call](security#reentrancy_guard)<br>. |

### [](#receiving_tokens)
Receiving tokens

In order to be sure a non-account contract can safely accept ERC1155 tokens, said contract must implement the `IERC1155Receiver` interface. The recipient contract must also implement the [SRC5](introspection#src5)
 interface which supports interface introspection.

#### [](#ierc1155receiver)
IERC1155Receiver

    trait IERC1155Receiver {
        fn on_erc1155_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_id: u256,
            value: u256,
            data: Span<felt252>
        ) -> felt252;
        fn on_erc1155_batch_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        ) -> felt252;
    }

Implementing the `IERC1155Receiver` interface exposes the [on\_erc1155\_received](api/erc1155#IERC1155Receiver-on_erc1155_received)
 and [on\_erc1155\_batch\_received](api/erc1155#IERC1155Receiver-on_erc1155_batch_received)
 methods. When [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)
 and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)
 are called, they invoke the recipient contract’s `on_erc1155_received` or `on_erc1155_batch_received` methods respectively which **must** return the [IERC1155Receiver interface ID](api/erc1155#IERC1155Receiver)
. Otherwise, the transaction will fail.

|     |     |
| --- | --- |
|     | For information on how to calculate interface IDs, see [Computing the interface ID](introspection#computing_the_interface_id)<br>. |

#### [](#creating_a_token_receiver_contract)
Creating a token receiver contract

The Contracts for Cairo [ERC1155ReceiverComponent](api/erc1155#ERC1155ReceiverComponent)
 already returns the correct interface ID for safe token transfers. To integrate the `IERC1155Receiver` interface into a contract, simply include the ABI embed directive to the implementations and add the `initializer` in the contract’s constructor. Here’s an example of a simple token receiver contract:

    #[starknet::contract]
    mod MyTokenReceiver {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc1155::ERC1155ReceiverComponent;
        use starknet::ContractAddress;
    
        component!(path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC1155Receiver
        #[abi(embed_v0)]
        impl ERC1155ReceiverImpl = ERC1155ReceiverComponent::ERC1155ReceiverImpl<ContractState>;
        #[abi(embed_v0)]
        impl ERC1155ReceiverCamelImpl = ERC1155ReceiverComponent::ERC1155ReceiverCamelImpl<ContractState>;
        impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl<ContractState>;
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc1155_receiver: ERC1155ReceiverComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            self.erc721_receiver.initializer();
        }
    }

[← API Reference](/contracts-cairo/0.10.0/api/erc721)

[API Reference →](/contracts-cairo/0.10.0/api/erc1155)




 Migrating ERC165 to SRC5 - OpenZeppelin Docs       

Migrating ERC165 to SRC5
========================

In the smart contract ecosystem, having the ability to query if a contract supports a given interface is an extremely important feature. The initial introspection design for Contracts for Cairo before version v0.7.0 followed Ethereum’s [EIP-165](https://eips.ethereum.org/EIPS/eip-165)
. Since the Cairo language evolved introducing native types, we needed an introspection solution tailored to the Cairo ecosystem: the [SNIP-5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard. SNIP-5 allows interface ID calculations to use Cairo types and the Starknet keccak (`sn_keccak`) function. For more information on the decision, see the [Starknet Shamans proposal](https://community.starknet.io/t/starknet-standard-interface-detection/92664)
 or the [Dual Introspection Detection](https://github.com/OpenZeppelin/cairo-contracts/discussions/640)
 discussion.

[](#how_to_migrate)
How to migrate
----------------------------------

Migrating from ERC165 to SRC5 involves four major steps:

1.  Integrate SRC5 into the contract.
    
2.  Register SRC5 IDs.
    
3.  Add a `migrate` function to apply introspection changes.
    
4.  Upgrade the contract and call `migrate`.
    

The following guide will go through the steps with examples.

### [](#component_integration)
Component integration

The first step is to integrate the necessary components into the new contract. The contract should include the new introspection mechanism, [SRC5Component](../api/introspection#SRC5Component)
. It should also include the [InitializableComponent](../api/security#InitializableComponent)
 which will be used in the `migrate` function. Here’s the setup:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::security::initializable::InitializableComponent;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
        component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    
        // SRC5
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        #[abi(embed_v0)]
        impl SRC5CamelOnlyImpl = SRC5Component::SRC5CamelImpl<ContractState>;
        impl SRC5InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        // Initializable
        impl InitializableInternalImpl = InitializableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage,
            #[substorage(v0)]
            initializable: InitializableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event,
            #[flat]
            InitializableEvent: InitializableComponent::Event
        }
    }

### [](#interface_registration)
Interface registration

To successfully migrate ERC165 to SRC5, the contract needs to register the interface IDs that the contract supports with SRC5.

For this example, let’s say that this contract supports the [IERC721](../api/erc721#IERC721)
 and [IERC721Metadata](../api/erc721#IERC721Metadata)
 interfaces. The contract should implement an `InternalImpl` and add a function to register those interfaces like this:

    #[starknet::contract]
    mod MigratingContract {
        use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID};
    
        (...)
    
        #[generate_trait]
        impl InternalImpl of InternalTrait {
            // Register SRC5 interfaces
            fn register_src5_interfaces(ref self: ContractState) {
                self.src5.register_interface(IERC721_ID);
                self.src5.register_interface(IERC721_METADATA_ID);
            }
        }
    }

Since the new contract integrates `SRC5Component`, it can leverage SRC5’s [register\_interface](../api/introspection#SRC5Component-register_interface)
 function to register the supported interfaces.

### [](#migration_initializer)
Migration initializer

Next, the contract should define and expose a migration function that will invoke the `register_src5_interfaces` function. Since the `migrate` function will be publicly callable, it should include some sort of [Access Control](../access)
 so that only permitted addresses can execute the migration. Finally, `migrate` should include a reinitialization check to ensure that it cannot be called more than once.

|     |     |
| --- | --- |
|     | If the original contract implemented `Initializable` at any point and called the `initialize` method, the `InitializableComponent` will not be usable at this time. Instead, the contract can take inspiration from `InitializableComponent` and create its own initialization mechanism. |

    #[starknet::contract]
    mod MigratingContract {
        (...)
    
        #[external(v0)]
        fn migrate(ref self: ContractState) {
            // WARNING: Missing Access Control mechanism. Make sure to add one
    
            // WARNING: If the contract ever implemented `Initializable` in the past,
            // this will not work. Make sure to create a new initialization mechanism
            self.initializable.initialize();
    
            // Register SRC5 interfaces
            self.register_src5_interfaces();
        }
    }

### [](#execute_migration)
Execute migration

Once the new contract is prepared for migration and **rigorously tested**, all that’s left is to migrate! Simply upgrade the contract and then call `migrate`.

[← Introspection](/contracts-cairo/0.10.0/introspection)

[API Reference →](/contracts-cairo/0.10.0/api/introspection)




 Utilities - OpenZeppelin Docs       

Utilities
=========

The following documentation provides reasoning and examples for functions and constants found in `openzeppelin::utils` and `openzeppelin::tests::utils`.

|     |     |
| --- | --- |
|     | Expect this module to evolve (as it has already done). |

[](#core_utilities)
Core utilities
----------------------------------

### [](#utils)
`utils`

    use openzeppelin::utils;

Module containing core utilities of the library.

Members

Functions

*   [`try_selector_with_fallback(target, selector, fallback, args)`](#utils-try_selector_with_fallback)
    

Traits

*   [`UnwrapAndCast`](#utils-UnwrapAndCast)
    

Inner modules

*   [`selectors`](#utils-selectors)
    
*   [`serde`](#utils-serde)
    

#### [](#utils-Functions)
Functions

#### [](#utils-try_selector_with_fallback)
`try_selector_with_fallback(target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>) → SyscallResult<Span<felt252>>` function

Tries to call a given selector on a given contract, and if it fails, tries to call a fallback selector.

It was designed for falling back to the `camelCase` selector for backward compatibility in the case of a failure of the `snake_case` selector.

Returns a `SyscallResult` with the result of the successful call.

Note that:

*   If the first call succeeds, the second call is not attempted.
    
*   If the first call fails with an error different than `ENTRYPOINT_NOT_FOUND`, the error is returned without falling back to the second selector.
    
*   If the first call fails with `ENTRYPOINT_NOT_FOUND`, the second call is attempted, and if it fails its error is returned.
    

|     |     |
| --- | --- |
|     | The fallback mechanism won’t work on live chains (mainnet or testnets) until they implement panic handling in their runtime. |

#### [](#utils-Traits)
Traits

#### [](#utils-UnwrapAndCast)
`UnwrapAndCast` trait

Trait for exposing an `unwrap_and_cast` function to `SyscallResult` objects. This may be useful when unwrapping a syscall result to a type implementing the `Serde` trait, and you want to avoid the boilerplate of casting and unwrapping the result multiple times.

Usage example:

    use openzeppelin::utils::selectors;
    use openzeppelin::utils::UnwrapAndCast;
    
    fn call_and_cast_to_bool(target: ContractAddress, args: Span<felt252>) -> bool {
        try_selector_with_fallback(
            target, selectors::has_role, selectors::hasRole, args
        ).unwrap_and_cast()
    }
    
    fn call_and_cast_to_felt252(target: ContractAddress, args: Span<felt252>) -> felt252 {
        try_selector_with_fallback(
            target, selectors::get_role_admin, selectors::getRoleAdmin, args
        ).unwrap_and_cast()
    }

Note that it can be automatically casted to any type implementing the `Serde` trait.

#### [](#utils-Inner-Modules)
Inner modules

#### [](#utils-selectors)
`selectors` module

See [`openzeppelin::utils::selectors`](#selectors)
.

#### [](#utils-serde)
`serde` module

See [`openzeppelin::utils::serde`](#serde)
.

### [](#selectors)
`selectors`

    use openzeppelin::utils::selectors;

Module containing constants matching multiple selectors used through the library. To see the full list of selectors, see [selectors.cairo](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/utils/selectors.cairo)
.

### [](#serde)
`serde`

    use openzeppelin::utils::serde;

Module containing utilities related to serialization and deserialization of Cairo data structures.

Members

Traits

*   [`SerializedAppend`](#serde-SerializedAppend)
    

#### [](#serde-Traits)
Traits

#### [](#serde-SerializedAppend)
`SerializedAppend` trait

Importing this trait allows the ability to append a serialized representation of a Cairo data structure already implementing the `Serde` trait to a `felt252` buffer.

Usage example:

    use openzeppelin::utils::serde::SerializedAppend;
    use starknet::ContractAddress;
    
    fn to_calldata(recipient: ContractAddress, amount: u256) -> Array<felt252> {
        let mut calldata = array![];
        calldata.append_serde(recipient);
        calldata.append_serde(amount);
        calldata
    }

Note that the `append_serde` method is automatically available for arrays of felts, and it accepts any data structure that implements the `Serde` trait.

[](#test_utilities)
Test utilities
----------------------------------

### [](#testutils)
`utils`

    use openzeppelin::tests::utils;

Module containing utilities for testing the library.

Members

Functions

*   [`deploy(contract_class_hash, calldata)`](#testutils-deploy)
    
*   [`pop_log<T>(address)`](#testutils-pop_log)
    
*   [`assert_indexed_keys<T>(event, expected_keys)`](#testutils-assert_indexed_keys)
    
*   [`assert_no_events_left(address)`](#testutils-assert_no_events_left)
    
*   [`drop_event(address)`](#testutils-drop_event)
    

Inner modules

*   [`constants`](#testutils-constants)
    

#### [](#testutils-Functions)
Functions

#### [](#testutils-deploy)
`deploy(contract_class_hash: felt252, calldata: Array<felt252>) → ContractAddress` function

Uses the `[deploy_syscall](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls/#deploy) ` to deploy an instance of the contract given the class hash and the calldata.

The `contract_address_salt` is always set to zero, and `deploy_from_zero` is set to false.

Usage example:

    use openzeppelin::presets::Account;
    use openzeppelin::tests::utils;
    use starknet::ContractAddress;
    
    const PUBKEY: felt252 = 'PUBKEY';
    
    fn deploy_test_contract() -> ContractAddress {
        let calldata = array![PUBKEY];
        utils::deploy(Account::TEST_CLASS_HASH, calldata)
    }

#### [](#testutils-pop_log)
`pop_log<T>(address: ContractAddress) → Option<T>` function

Pops the earliest unpopped logged event for the contract as the requested type and checks that there’s no more keys or data left on the event, preventing unaccounted params.

Required traits for `T`:

*   `Drop`
    
*   `starknet::Event`
    

Requirements:

*   No extra data or keys are left on the raw event after deserialization.
    

|     |     |
| --- | --- |
|     | This method doesn’t currently work for component events that are not flattened because an extra key is added, pushing the event ID key to the second position. |

#### [](#testutils-assert_indexed_keys)
`assert_indexed_keys<T>(event: T, expected_keys: Span<felt252>)` function

Asserts that `expected_keys` exactly matches the indexed keys from `event`.

`expected_keys` must include all indexed event keys for `event` in the order that they’re defined.

|     |     |
| --- | --- |
|     | If the event is not flattened, the first key will be the event member name e.g. selector!("EnumMemberName"). |

Required traits for `T`:

*   `Drop`
    
*   `starknet::Event`
    

#### [](#testutils-assert_no_events_left)
`assert_no_events_left(address: ContractAddress)` function

Asserts that there are no more events left in the queue for the given address.

#### [](#testutils-drop_event)
`drop_event(address: ContractAddress)` function

Removes an event from the queue for the given address.

If the queue is empty, this function won’t do anything.

#### [](#testutils-Inner-Modules)
Inner modules

#### [](#testutils-constants)
`constants` module

See [`openzeppelin::tests::utils::constants`](#constants)
.

### [](#constants)
`constants`

    use openzeppelin::tests::utils::constants;

Module containing constants that are repeatedly used among tests. To see the full list, see [constants.cairo](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/tests/utils/constants.cairo)
.

[← API Reference](/contracts-cairo/0.10.0/api/upgrades)

[Backwards Compatibility →](/contracts-cairo/0.10.0/backwards-compatibility)




 Introspection - OpenZeppelin Docs       

Introspection
=============

To smooth interoperability, often standards require smart contracts to implement [introspection mechanisms](https://en.wikipedia.org/wiki/Type_introspection)
.

In Ethereum, the [EIP165](https://eips.ethereum.org/EIPS/eip-165)
 standard defines how contracts should declare their support for a given interface, and how other contracts may query this support.

Starknet offers a similar mechanism for interface introspection defined by the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard.

[](#src5)
SRC5
--------------

Similar to its Ethereum counterpart, the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard requires contracts to implement the `supports_interface` function, which can be used by others to query if a given interface is supported.

### [](#usage)
Usage

To expose this functionality, the contract must implement the [SRC5Component](api/introspection#SRC5Component)
, which defines the `supports_interface` function. Here is an example contract:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl SRC5InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            self.src5.register_interface(selector!("some_interface"));
        }
    }

### [](#interface)
Interface

    #[starknet::interface]
    pub trait ISRC5 {
        /// Query if a contract implements an interface.
        /// Receives the interface identifier as specified in SRC-5.
        /// Returns `true` if the contract implements `interface_id`, `false` otherwise.
        fn supports_interface(interface_id: felt252) -> bool;
    }

[](#computing_the_interface_id)
Computing the interface ID
----------------------------------------------------------

The interface ID, as specified in the standard, is the [XOR](https://en.wikipedia.org/wiki/Exclusive_or)
 of all the [Extended Function Selectors](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#extended-function-selector)
 of the interface. We strongly advise reading the SNIP to understand the specifics of computing these extended function selectors. There are tools such as [src5-rs](https://github.com/ericnordelo/src5-rs)
 that can help with this process.

[](#registering_interfaces)
Registering interfaces
--------------------------------------------------

For a contract to declare its support for a given interface, we recommend using the SRC5 component to register support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            // Register the contract's support for the ISRC6 interface
            self.src5.register_interface(interface::ISRC6_ID);
        }
    
        (...)
    }

[](#querying_interfaces)
Querying interfaces
--------------------------------------------

Use the `supports_interface` function to query a contract’s support for a given interface.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::interface::ISRC5DispatcherTrait;
        use openzeppelin::introspection::interface::ISRC5Dispatcher;
        use starknet::ContractAddress;
    
        #[storage]
        struct Storage {}
    
        #[external(v0)]
        fn query_is_account(self: @ContractState, target: ContractAddress) -> bool {
            let dispatcher = ISRC5Dispatcher { contract_address: target };
            dispatcher.supports_interface(interface::ISRC6_ID)
        }
    }

|     |     |
| --- | --- |
|     | If you are unsure whether a contract implements SRC5 or not, you can follow the process described in [here](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#how-to-detect-if-a-contract-implements-src-5)<br>. |

[← API Reference](/contracts-cairo/0.15.0/api/governance)

[Migrating ERC165 to SRC5 →](/contracts-cairo/0.15.0/guides/src5-migration)




 ERC1155 - OpenZeppelin Docs       

ERC1155
=======

The ERC1155 multi token standard is a specification for [fungibility-agnostic](https://docs.openzeppelin.com/contracts/5.x/tokens#different-kinds-of-tokens)
 token contracts. The ERC1155 library implements an approximation of [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155)
 in Cairo for StarkNet.

[](#multi_token_standard)
Multi Token Standard
----------------------------------------------

The distinctive feature of ERC1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its [balance\_of](api/erc1155#IERC1155-balance_of)
 function differs from ERC20’s and ERC777’s: it has an additional ID argument for the identifier of the token that you want to query the balance of.

This is similar to how ERC721 does things, but in that standard a token ID has no concept of balance: each token is non-fungible and exists or doesn’t. The ERC721 [balance\_of](api/erc721#IERC721-balance_of)
 function refers to how many different tokens an account has, not how many of each. On the other hand, in ERC1155 accounts have a distinct balance for each token ID, and non-fungible tokens are implemented by simply minting a single one of them.

This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC1155 token contract can hold the entire system state, reducing deployment costs and complexity.

[](#interface)
Interface
------------------------

The following interface represents the full ABI of the Contracts for Cairo [ERC1155Component](api/erc1155#ERC1155Component)
. The interface includes the [IERC1155](api/erc1155#IERC1155)
 standard interface and the optional [IERC1155MetadataURI](api/erc1155#IERC1155MetadataURI)
 interface together with [ISRC5](api/introspection#ISRC5)
.

To support older token deployments, as mentioned in [Dual interfaces](interfaces#dual_interfaces)
, the component also includes implementations of the interface written in camelCase.

    trait ERC1155ABI {
        // IERC1155
        fn balance_of(account: ContractAddress, token_id: u256) -> u256;
        fn balance_of_batch(
            accounts: Span<ContractAddress>, token_ids: Span<u256>
        ) -> Span<u256>;
        fn safe_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_id: u256,
            value: u256,
            data: Span<felt252>
        );
        fn safe_batch_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        );
        fn is_approved_for_all(
            owner: ContractAddress, operator: ContractAddress
        ) -> bool;
        fn set_approval_for_all(operator: ContractAddress, approved: bool);
    
        // IERC1155MetadataURI
        fn uri(token_id: u256) -> ByteArray;
    
        // ISRC5
        fn supports_interface(interface_id: felt252) -> bool;
    
        // IERC1155Camel
        fn balanceOf(account: ContractAddress, tokenId: u256) -> u256;
        fn balanceOfBatch(
            accounts: Span<ContractAddress>, tokenIds: Span<u256>
        ) -> Span<u256>;
        fn safeTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenId: u256,
            value: u256,
            data: Span<felt252>
        );
        fn safeBatchTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenIds: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        );
        fn isApprovedForAll(owner: ContractAddress, operator: ContractAddress) -> bool;
        fn setApprovalForAll(operator: ContractAddress, approved: bool);
    }

### [](#erc1155_compatibility)
ERC1155 Compatibility

Although Starknet is not EVM compatible, this implementation aims to be as close as possible to the ERC1155 standard but some differences can still be found, such as:

*   The optional `data` argument in both `safe_transfer_from` and `safe_batch_transfer_from` is implemented as `Span<felt252>`.
    
*   `IERC1155Receiver` compliant contracts must implement SRC5 and register the `IERC1155Receiver` interface ID.
    
*   `IERC1155Receiver::on_erc1155_received` must return that interface ID on success.
    

[](#usage)
Usage
----------------

Using Contracts for Cairo, constructing an ERC1155 contract requires integrating both `ERC1155Component` and `SRC5Component`. The contract should also set up the constructor to initialize the token’s URI and interface support. Here’s an example of a basic contract:

    #[starknet::contract]
    mod MyERC1155 {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl};
        use starknet::ContractAddress;
    
        component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC1155 Mixin
        #[abi(embed_v0)]
        impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl<ContractState>;
        impl ERC1155InternalImpl = ERC1155Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc1155: ERC1155Component::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC1155Event: ERC1155Component::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            token_uri: ByteArray,
            recipient: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>
        ) {
            self.erc1155.initializer(token_uri);
            self
                .erc1155
                .batch_mint_with_acceptance_check(recipient, token_ids, values, array![].span());
        }
    }

### [](#batch_operations)
Batch operations

Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, [balance\_of\_batch](api/erc1155#IERC1155-balance_of_batch)
 and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)
, that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive. We also have [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)
 for non-batch operations.

In the spirit of the standard, we’ve also included batch operations in the non-standard functions, such as [batch\_mint\_with\_acceptance\_check](api/erc1155#ERC1155Component-batch_mint_with_acceptance_check)
.

|     |     |
| --- | --- |
|     | While [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)<br> and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)<br> prevent loss by checking the receiver can handle the tokens, this yields execution to the receiver which can result in a [reentrant call](security#reentrancy_guard)<br>. |

### [](#receiving_tokens)
Receiving tokens

In order to be sure a non-account contract can safely accept ERC1155 tokens, said contract must implement the `IERC1155Receiver` interface. The recipient contract must also implement the [SRC5](introspection#src5)
 interface which supports interface introspection.

#### [](#ierc1155receiver)
IERC1155Receiver

    trait IERC1155Receiver {
        fn on_erc1155_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_id: u256,
            value: u256,
            data: Span<felt252>
        ) -> felt252;
        fn on_erc1155_batch_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_ids: Span<u256>,
            values: Span<u256>,
            data: Span<felt252>
        ) -> felt252;
    }

Implementing the `IERC1155Receiver` interface exposes the [on\_erc1155\_received](api/erc1155#IERC1155Receiver-on_erc1155_received)
 and [on\_erc1155\_batch\_received](api/erc1155#IERC1155Receiver-on_erc1155_batch_received)
 methods. When [safe\_transfer\_from](api/erc1155#IERC1155-safe_transfer_from)
 and [safe\_batch\_transfer\_from](api/erc1155#IERC1155-safe_batch_transfer_from)
 are called, they invoke the recipient contract’s `on_erc1155_received` or `on_erc1155_batch_received` methods respectively which **must** return the [IERC1155Receiver interface ID](api/erc1155#IERC1155Receiver)
. Otherwise, the transaction will fail.

|     |     |
| --- | --- |
|     | For information on how to calculate interface IDs, see [Computing the interface ID](introspection#computing_the_interface_id)<br>. |

#### [](#creating_a_token_receiver_contract)
Creating a token receiver contract

The Contracts for Cairo [ERC1155ReceiverComponent](api/erc1155#ERC1155ReceiverComponent)
 already returns the correct interface ID for safe token transfers. To integrate the `IERC1155Receiver` interface into a contract, simply include the ABI embed directive to the implementations and add the `initializer` in the contract’s constructor. Here’s an example of a simple token receiver contract:

    #[starknet::contract]
    mod MyTokenReceiver {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc1155::ERC1155ReceiverComponent;
        use starknet::ContractAddress;
    
        component!(path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC1155Receiver Mixin
        #[abi(embed_v0)]
        impl ERC1155ReceiverMixinImpl = ERC1155ReceiverComponent::ERC1155ReceiverMixinImpl<ContractState>;
        impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc1155_receiver: ERC1155ReceiverComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            self.erc1155_receiver.initializer();
        }
    }

[← API Reference](/contracts-cairo/0.13.0/api/erc721)

[API Reference →](/contracts-cairo/0.13.0/api/erc1155)




 Universal Deployer - OpenZeppelin Docs       

Universal Deployer
==================

Reference of the Universal Deployer Contract (UDC) interface and preset.

[](#core)
Core
--------------

### [](#IUniversalDeployer)
`IUniversalDeployer`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/utils/universal_deployer/interface.cairo#L7)

    use openzeppelin::utils::interfaces::IUniversalDeployer;

Functions

*   [`deploy_contract(class_hash, salt, from_zero, calldata)`](#IUniversalDeployer-deploy_contract)
    

Events

*   [`ContractDeployed(address, deployer, from_zero, class_hash, calldata, salt)`](#IUniversalDeployer-ContractDeployed)
    

#### [](#IUniversalDeployer-Functions)
Functions

#### [](#IUniversalDeployer-deploy_contract)
`deploy_contract(class_hash: ClassHash, salt: felt252, from_zero: bool, calldata: Span<felt252>) → ContractAddress` external

Deploys a contract through the Universal Deployer Contract.

#### [](#IUniversalDeployer-Events)
Events

#### [](#IUniversalDeployer-ContractDeployed)
`ContractDeployed(address: ContractAddress, deployer: ContractAddress, from_zero: bool, class_hash: ClassHash, calldata: Span<felt252>, salt: felt252)` event

Emitted when `deployer` deploys a contract through the Universal Deployer Contract.

[](#presets)
Presets
--------------------

### [](#UniversalDeployer)
`UniversalDeployer`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/presets/universal_deployer.cairo)

    use openzeppelin::presets::UniversalDeployer;

The standard Universal Deployer Contract.

[Sierra class hash](../presets)

0x03edeadb23f0c66167da93651affc6acc6f3b7256ef651b2fddfd6a63288a742

Embedded Implementations

UniversalDeployerImpl

*   [`deploy_contract(self, address, deployer, from_zero, class_hash, calldata, salt)`](#UniversalDeployer-deploy_contract)
    

#### [](#UniversalDeployer-deploy_contract)
`deploy_contract(ref self: ContractState, address: ContractAddress, deployer: ContractAddress, from_zero: bool, class_hash: ClassHash, calldata: Span<felt252>, salt: felt252) -> ContractAddress` external

Deploys a contract through the Universal Deployer Contract.

When `from_zero` is `false`, `salt` is hashed with the caller address and the modified salt is passed to the inner `deploy_syscall`. This type of deployment is [origin-dependent](../udc#origin_dependent)
.

When `from_zero` is `true`, the deployment type is [origin-independent](../udc#origin_independent)
.

Emits an [ContractDeployed](#IUniversalDeployer-ContractDeployed)
 event.

[← Universal Deployer Contract](/contracts-cairo/0.15.0/udc)

[Upgrades →](/contracts-cairo/0.15.0/upgrades)




 Introspection - OpenZeppelin Docs       

Introspection
=============

To smooth interoperability, often standards require smart contracts to implement [introspection mechanisms](https://en.wikipedia.org/wiki/Type_introspection)
.

In Ethereum, the [EIP165](https://eips.ethereum.org/EIPS/eip-165)
 standard defines how contracts should declare their support for a given interface, and how other contracts may query this support.

Starknet offers a similar mechanism for interface introspection defined by the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard.

[](#src5)
SRC5
--------------

Similar to its Ethereum counterpart, the [SRC5](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md)
 standard requires contracts to implement the `supports_interface` function, which can be used by others to query if a given interface is supported:

    trait ISRC5 {
        /// Query if a contract implements an interface.
        /// Receives the interface identifier as specified in SRC-5.
        /// Returns `true` if the contract implements `interface_id`, `false` otherwise.
        fn supports_interface(interface_id: felt252) -> bool;
    }

### [](#computing_the_interface_id)
Computing the interface ID

The interface ID, as specified in the standard, is the [XOR](https://en.wikipedia.org/wiki/Exclusive_or)
 of all the [Extended Function Selectors](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#extended-function-selector)
 of the interface. We strongly advise reading the SNIP to understand the specifics of computing these extended function selectors. There are tools such as [src5-rs](https://github.com/ericnordelo/src5-rs)
 that can help with this process.

### [](#registering_interfaces)
Registering interfaces

For a contract to declare its support for a given interface, we recommend using the SRC5 component to register support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this:

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::src5::SRC5Component;
    
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        #[abi(embed_v0)]
        impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
        impl InternalImpl = SRC5Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            // Register the contract's support for the ISRC6 interface
            self.src5.register_interface(interface::ISRC6_ID);
        }
    
        (...)
    }

### [](#querying_interfaces)
Querying interfaces

Use the `supports_interface` function to query a contract’s support for a given interface.

    #[starknet::contract]
    mod MyContract {
        use openzeppelin::account::interface;
        use openzeppelin::introspection::interface::ISRC5DispatcherTrait;
        use openzeppelin::introspection::interface::ISRC5Dispatcher;
        use starknet::ContractAddress;
    
        #[storage]
        struct Storage {}
    
        #[external(v0)]
        fn query_is_account(self: @ContractState, target: ContractAddress) -> bool {
            let dispatcher = ISRC5Dispatcher { contract_address: target };
            dispatcher.supports_interface(interface::ISRC6_ID)
        }
    }

|     |     |
| --- | --- |
|     | If you are unsure whether a contract implements SRC5 or not, you can follow the process described in [here](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#how-to-detect-if-a-contract-implements-src-5)<br>. |

[← API Reference](/contracts-cairo/0.10.0/api/account)

[Migrating ERC165 to SRC5 →](/contracts-cairo/0.10.0/guides/src5-migration)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

Reference of interfaces and utilities related to upgradeability.

[](#core)
Core
--------------

### [](#IUpgradeable)
`IUpgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/upgrades/interface.cairo#L3)

    use openzeppelin::upgrades::interface::IUpgradeable;

Interface of an upgradeable contract.

Functions

*   [`upgrade(new_class_hash)`](#IUpgradeable-upgrade)
    

#### [](#IUpgradeable-Functions)
Functions

#### [](#IUpgradeable-upgrade)
`upgrade(new_class_hash: ClassHash)` external

Upgrades the contract code by updating its [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

|     |     |
| --- | --- |
|     | This function is usually protected by an [Access Control](../access)<br> mechanism. |

### [](#UpgradeableComponent)
`UpgradeableComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/upgrades/upgradeable.cairo)

    use openzeppelin::upgrades::upgradeable::UpgradeableComponent;

Upgradeable component.

Internal Implementations

InternalImpl

*   [`_upgrade(self, new_class_hash)`](#UpgradeableComponent-_upgrade)
    

Events

*   [`Upgraded(class_hash)`](#UpgradeableComponent-Upgraded)
    

#### [](#UpgradeableComponent-Internal-Functions)
Internal Functions

#### [](#UpgradeableComponent-_upgrade)
`_upgrade(ref self: ContractState, new_class_hash: ClassHash)` internal

Upgrades the contract by updating the contract [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
.

Requirements:

*   `new_class_hash` must be different from zero.
    

Emits an [Upgraded](#UpgradeableComponent-Upgraded)
 event.

#### [](#UpgradeableComponent-Events)
Events

#### [](#UpgradeableComponent-Upgraded)
`Upgraded(class_hash: ClassHash)` event

Emitted when the [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
 is upgraded.

[← Upgrades](/contracts-cairo/0.10.0/upgrades)

[Utilities →](/contracts-cairo/0.10.0/utilities)




 Upgrades - OpenZeppelin Docs       

Upgrades
========

In different blockchains, multiple patterns have been developed for making a contract upgradeable including the widely adopted proxy patterns.

Starknet has native upgradeability through a syscall that updates the contract source code, removing [the need for proxies](#proxies_in_starknet)
.

|     |     |
| --- | --- |
|     | Make sure you follow [our security recommendations](#security)<br> before upgrading. |

[](#replacing_contract_classes)
Replacing contract classes
----------------------------------------------------------

To better comprehend how upgradeability works in Starknet, it’s important to understand the difference between a contract and its contract class.

[Contract Classes](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-classes/)
 represent the source code of a program. All contracts are associated to a class, and many contracts can be instances of the same one. Classes are usually represented by a [class hash](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/)
, and before a contract of a class can be deployed, the class hash needs to be declared.

### [](#replace_class_syscall)
`replace_class_syscall`

The `[replace_class](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#replace_class) ` syscall allows a contract to update its source code by replacing its class hash once deployed.

    /// Upgrades the contract source code to the new contract class.
    fn _upgrade(new_class_hash: ClassHash) {
        assert(!new_class_hash.is_zero(), 'Class hash cannot be zero');
        starknet::replace_class_syscall(new_class_hash).unwrap_syscall();
    }

|     |     |
| --- | --- |
|     | If a contract is deployed without this mechanism, its class hash can still be replaced through [library calls](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#library_call)<br>. |

[](#upgradeable_component)
`Upgradeable` component
--------------------------------------------------

OpenZeppelin Contracts for Cairo provides [Upgradeable](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.13.0/src/upgrades/upgradeable.cairo)
 to add upgradeability support to your contracts.

### [](#usage)
Usage

Upgrades are often very sensitive operations, and some form of access control is usually required to avoid unauthorized upgrades. The [Ownable](access#ownership_and_ownable)
 module is used in this example.

|     |     |
| --- | --- |
|     | We will be using the following module to implement the [IUpgradeable](api/upgrades#IUpgradeable)<br> interface described in the API Reference section. |

    #[starknet::contract]
    mod UpgradeableContract {
        use openzeppelin::access::ownable::OwnableComponent;
        use openzeppelin::upgrades::UpgradeableComponent;
        use openzeppelin::upgrades::interface::IUpgradeable;
        use starknet::ClassHash;
        use starknet::ContractAddress;
    
        component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
        component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
    
        // Ownable Mixin
        #[abi(embed_v0)]
        impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
        impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    
        // Upgradeable
        impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            ownable: OwnableComponent::Storage,
            #[substorage(v0)]
            upgradeable: UpgradeableComponent::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            OwnableEvent: OwnableComponent::Event,
            #[flat]
            UpgradeableEvent: UpgradeableComponent::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, owner: ContractAddress) {
            self.ownable.initializer(owner);
        }
    
        #[external(v0)]
        impl UpgradeableImpl of IUpgradeable<ContractState> {
            fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
                // This function can only be called by the owner
                self.ownable.assert_only_owner();
    
                // Replace the class hash upgrading the contract
                self.upgradeable._upgrade(new_class_hash);
            }
        }
    }

[](#security)
Security
----------------------

Upgrades can be very sensitive operations, and security should always be top of mind while performing one. Please make sure you thoroughly review the changes and their consequences before upgrading. Some aspects to consider are:

*   API changes that might affect integration. For example, changing an external function’s arguments might break existing contracts or offchain systems calling your contract.
    
*   Storage changes that might result in lost data (e.g. changing a storage slot name, making existing storage inaccessible).
    
*   Collisions (e.g. mistakenly reusing the same storage slot from another component) are also possible, although less likely if best practices are followed, for example prepending storage variables with the component’s name (e.g. `ERC20_balances`).
    
*   Always check for [backwards compatibility](backwards-compatibility)
     before upgrading between versions of OpenZeppelin Contracts.
    

[](#proxies_in_starknet)
Proxies in Starknet
--------------------------------------------

Proxies enable different patterns such as upgrades and clones. But since Starknet achieves the same in different ways is that there’s no support to implement them.

In the case of contract upgrades, it is achieved by simply changing the contract’s class hash. As of clones, contracts already are like clones of the class they implement.

Implementing a proxy pattern in Starknet has an important limitation: there is no fallback mechanism to be used for redirecting every potential function call to the implementation. This means that a generic proxy contract can’t be implemented. Instead, a limited proxy contract can implement specific functions that forward their execution to another contract class. This can still be useful for example to upgrade the logic of some functions.

[← API Reference](/contracts-cairo/0.13.0/api/udc)

[API Reference →](/contracts-cairo/0.13.0/api/upgrades)




 ERC721 - OpenZeppelin Docs       

ERC721
======

The ERC721 token standard is a specification for [non-fungible tokens](https://docs.openzeppelin.com/contracts/5.x/tokens#different-kinds-of-tokens)
, or more colloquially: NFTs. `token::erc721::ERC721Component` provides an approximation of [EIP-721](https://eips.ethereum.org/EIPS/eip-721)
 in Cairo for Starknet.

[](#usage)
Usage
----------------

Using Contracts for Cairo, constructing an ERC721 contract requires integrating both `ERC721Component` and `SRC5Component`. The contract should also set up the constructor to initialize the token’s name, symbol, and interface support. Here’s an example of a basic contract:

    #[starknet::contract]
    mod MyNFT {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};
        use starknet::ContractAddress;
    
        component!(path: ERC721Component, storage: erc721, event: ERC721Event);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC721 Mixin
        #[abi(embed_v0)]
        impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl<ContractState>;
        impl ERC721InternalImpl = ERC721Component::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc721: ERC721Component::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC721Event: ERC721Component::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(
            ref self: ContractState,
            recipient: ContractAddress
        ) {
            let name = "MyNFT";
            let symbol = "NFT";
            let base_uri = "https://api.example.com/v1/";
            let token_id = 1;
    
            self.erc721.initializer(name, symbol, base_uri);
            self.erc721.mint(recipient, token_id);
        }
    }

[](#interface)
Interface
------------------------

The following interface represents the full ABI of the Contracts for Cairo [ERC721Component](api/erc721#ERC721Component)
. The interface includes the [IERC721](api/erc721#IERC721)
 standard interface and the optional [IERC721Metadata](api/erc721#IERC721Metadata)
 interface.

To support older token deployments, as mentioned in [Dual interfaces](interfaces#dual_interfaces)
, the component also includes implementations of the interface written in camelCase.

    #[starknet::interface]
    pub trait ERC721ABI {
        // IERC721
        fn balance_of(account: ContractAddress) -> u256;
        fn owner_of(token_id: u256) -> ContractAddress;
        fn safe_transfer_from(
            from: ContractAddress,
            to: ContractAddress,
            token_id: u256,
            data: Span<felt252>
        );
        fn transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256);
        fn approve(to: ContractAddress, token_id: u256);
        fn set_approval_for_all(operator: ContractAddress, approved: bool);
        fn get_approved(token_id: u256) -> ContractAddress;
        fn is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool;
    
        // IERC721Metadata
        fn name() -> ByteArray;
        fn symbol() -> ByteArray;
        fn token_uri(token_id: u256) -> ByteArray;
    
        // IERC721CamelOnly
        fn balanceOf(account: ContractAddress) -> u256;
        fn ownerOf(tokenId: u256) -> ContractAddress;
        fn safeTransferFrom(
            from: ContractAddress,
            to: ContractAddress,
            tokenId: u256,
            data: Span<felt252>
        );
        fn transferFrom(from: ContractAddress, to: ContractAddress, tokenId: u256);
        fn setApprovalForAll(operator: ContractAddress, approved: bool);
        fn getApproved(tokenId: u256) -> ContractAddress;
        fn isApprovedForAll(owner: ContractAddress, operator: ContractAddress) -> bool;
    
        // IERC721MetadataCamelOnly
        fn tokenURI(tokenId: u256) -> ByteArray;
    }

[](#erc721_compatibility)
ERC721 compatibility
----------------------------------------------

Although Starknet is not EVM compatible, this implementation aims to be as close as possible to the ERC721 standard. This implementation does, however, include a few notable differences such as:

*   `interface_id`s are hardcoded and initialized by the constructor. The hardcoded values derive from Starknet’s selector calculations. See the [Introspection](introspection)
     docs.
    
*   `safe_transfer_from` can only be expressed as a single function in Cairo as opposed to the two functions declared in EIP721, because function overloading is currently not possible in Cairo. The difference between both functions consists of accepting `data` as an argument. `safe_transfer_from` by default accepts the `data` argument which is interpreted as `Span<felt252>`. If `data` is not used, simply pass an empty array.
    
*   ERC721 utilizes [SRC5](introspection#src5)
     to declare and query interface support on Starknet as opposed to Ethereum’s [EIP165](https://eips.ethereum.org/EIPS/eip-165)
    . The design for `SRC5` is similar to OpenZeppelin’s [ERC165Storage](https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC165Storage)
    .
    
*   `IERC721Receiver` compliant contracts return a hardcoded interface ID according to Starknet selectors (as opposed to selector calculation in Solidity).
    

[](#token_transfers)
Token transfers
------------------------------------

This library includes [transfer\_from](api/erc721#IERC721-transfer_from)
 and [safe\_transfer\_from](api/erc721#IERC721-safe_transfer_from)
 to transfer NFTs. If using `transfer_from`, **the caller is responsible to confirm that the recipient is capable of receiving NFTs or else they may be permanently lost.** The `safe_transfer_from` method mitigates this risk by querying the recipient contract’s interface support.

|     |     |
| --- | --- |
|     | Usage of `safe_transfer_from` prevents loss, though the caller must understand this adds an external call which potentially creates a reentrancy vulnerability. |

[](#receiving_tokens)
Receiving tokens
--------------------------------------

In order to be sure a non-account contract can safely accept ERC721 tokens, said contract must implement the `IERC721Receiver` interface. The recipient contract must also implement the [SRC5](introspection#src5)
 interface which, as described earlier, supports interface introspection.

### [](#ierc721receiver)
IERC721Receiver

    #[starknet::interface]
    pub trait IERC721Receiver {
        fn on_erc721_received(
            operator: ContractAddress,
            from: ContractAddress,
            token_id: u256,
            data: Span<felt252>
        ) -> felt252;
    }

Implementing the `IERC721Receiver` interface exposes the [on\_erc721\_received](api/erc721#IERC721Receiver-on_erc721_received)
 method. When safe methods such as [safe\_transfer\_from](api/erc721#IERC721-safe_transfer_from)
 and [safe\_mint](api/erc721#ERC721-safe_mint)
 are called, they invoke the recipient contract’s `on_erc721_received` method which **must** return the [IERC721Receiver interface ID](api/erc721#IERC721Receiver)
. Otherwise, the transaction will fail.

|     |     |
| --- | --- |
|     | For information on how to calculate interface IDs, see [Computing the interface ID](introspection#computing_the_interface_id)<br>. |

### [](#creating_a_token_receiver_contract)
Creating a token receiver contract

The Contracts for Cairo `IERC721ReceiverImpl` already returns the correct interface ID for safe token transfers. To integrate the `IERC721Receiver` interface into a contract, simply include the ABI embed directive to the implementation and add the `initializer` in the contract’s constructor. Here’s an example of a simple token receiver contract:

    #[starknet::contract]
    mod MyTokenReceiver {
        use openzeppelin::introspection::src5::SRC5Component;
        use openzeppelin::token::erc721::ERC721ReceiverComponent;
        use starknet::ContractAddress;
    
        component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent);
        component!(path: SRC5Component, storage: src5, event: SRC5Event);
    
        // ERC721Receiver Mixin
        #[abi(embed_v0)]
        impl ERC721ReceiverMixinImpl = ERC721ReceiverComponent::ERC721ReceiverMixinImpl<ContractState>;
        impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl<ContractState>;
    
        #[storage]
        struct Storage {
            #[substorage(v0)]
            erc721_receiver: ERC721ReceiverComponent::Storage,
            #[substorage(v0)]
            src5: SRC5Component::Storage
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            #[flat]
            ERC721ReceiverEvent: ERC721ReceiverComponent::Event,
            #[flat]
            SRC5Event: SRC5Component::Event
        }
    
        #[constructor]
        fn constructor(ref self: ContractState) {
            self.erc721_receiver.initializer();
        }
    }

[](#storing_erc721_uris)
Storing ERC721 URIs
--------------------------------------------

Token URIs were previously stored as single field elements prior to Cairo v0.2.5. ERC721Component now stores only the base URI as a `ByteArray` and the full token URI is returned as the `ByteArray` concatenation of the base URI and the token ID through the [token\_uri](api/erc721#IERC721Metadata-token_uri)
 method. This design mirrors OpenZeppelin’s default [Solidity implementation](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/932fddf69a699a9a80fd2396fd1a2ab91cdda123/contracts/token/ERC721/ERC721.sol#L85-L93)
 for ERC721.

[← API Reference](/contracts-cairo/0.15.0/api/erc20)

[API Reference →](/contracts-cairo/0.15.0/api/erc721)




 ERC20 - OpenZeppelin Docs       

ERC20
=====

Reference of interfaces and utilities related to ERC20 contracts.

|     |     |
| --- | --- |
|     | For an overview of ERC20, read our [ERC20 guide](../erc20)<br>. |

[](#core)
Core
--------------

### [](#IERC20)
`IERC20`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc20/interface.cairo)

    use openzeppelin::token::erc20::interface::IERC20;

Interface of the IERC20 standard as defined in [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
.

Functions

*   [`total_supply()`](#IERC20-total_supply)
    
*   [`balance_of()`](#IERC20-balance_of)
    
*   [`allowance(owner, spender)`](#IERC20-allowance)
    
*   [`transfer(recipient, amount)`](#IERC20-transfer)
    
*   [`transfer_from(sender, recipient, amount)`](#IERC20-transfer_from)
    
*   [`approve(spender, amount)`](#IERC20-approve)
    

Events

*   [`Transfer(from, to, value)`](#IERC20-Transfer)
    
*   [`Approval(owner, spender, value)`](#IERC20-Approval)
    

#### [](#IERC20-Functions)
Functions

#### [](#IERC20-total_supply)
`total_supply() → u256` external

Returns the amount of tokens in existence.

#### [](#IERC20-balance_of)
`balance_of(account: ContractAddress) → u256` external

Returns the amount of tokens owned by `account`.

#### [](#IERC20-allowance)
`allowance(owner: ContractAddress, spender: ContractAddress) → u256` external

Returns the remaining number of tokens that `spender` is allowed to spend on behalf of `owner` through [transfer\_from](#transfer_from)
. This is zero by default.

This value changes when [approve](#IERC20-approve)
 or [transfer\_from](#IERC20-transfer_from)
 are called.

#### [](#IERC20-transfer)
`transfer(recipient: ContractAddress, amount: u256) → bool` external

Moves `amount` tokens from the caller’s token balance to `to`. Returns `true` on success, reverts otherwise.

Emits a [Transfer](#IERC20-Transfer)
 event.

#### [](#IERC20-transfer_from)
`transfer_from(sender: ContractAddress, recipient: ContractAddress, amount: u256) → bool` external

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller’s allowance. Returns `true` on success, reverts otherwise.

Emits a [Transfer](#IERC20-Transfer)
 event.

#### [](#IERC20-approve)
`approve(spender: ContractAddress, amount: u256) → bool` external

Sets `amount` as the allowance of `spender` over the caller’s tokens. Returns `true` on success, reverts otherwise.

Emits an [Approval](#ERC20-Approval)
 event.

#### [](#IERC20-Events)
Events

#### [](#IERC20-Transfer)
`Transfer(from: ContractAddress, to: ContractAddress, value: u256)` event

Emitted when `value` tokens are moved from one address (`from`) to another (`to`).

Note that `value` may be zero.

#### [](#IERC20-Approval)
`Approval(owner: ContractAddress, spender: ContractAddress, value: u256)` event

Emitted when the allowance of a `spender` for an `owner` is set. `value` is the new allowance.

### [](#IERC20Metadata)
`IERC20Metadata`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc20/interface.cairo#L19)

    use openzeppelin::token::erc20::interface::IERC20Metadata;

Interface for the optional metadata functions in [EIP-20](https://eips.ethereum.org/EIPS/eip-20)
.

Functions

*   [`name()`](#IERC20Metadata-name)
    
*   [`symbol()`](#IERC20Metadata-symbol)
    
*   [`decimals()`](#IERC20Metadata-decimals)
    

#### [](#IERC20Metadata-Functions)
Functions

#### [](#IERC20Metadata-name)
`name() → ByteArray` external

Returns the name of the token.

#### [](#IERC20Metadata-symbol)
`symbol() → ByteArray` external

Returns the ticker symbol of the token.

#### [](#IERC20Metadata-decimals)
`decimals() → u8` external

Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user-readable representation.

For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`).

Tokens usually opt for a value of `18`, imitating the relationship between Ether and Wei. This is the default value returned by this function. To create a custom decimals implementation, see [Customizing decimals](../erc20#customizing_decimals)
.

|     |     |
| --- | --- |
|     | This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract. |

### [](#ERC20Component)
`ERC20Component`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc20/erc20.cairo)

    use openzeppelin::token::erc20::ERC20Component;

ERC20 component extending [IERC20](#IERC20)
 and [IERC20Metadata](#IERC20Metadata)
.

|     |     |
| --- | --- |
|     | See [Hooks](#ERC20Component-Hooks)<br> to understand how are hooks used. |

Hooks

ERC20HooksTrait

*   [`before_update(self, from, recipient, amount)`](#ERC20Component-before_update)
    
*   [`after_update(self, from, recipient, amount)`](#ERC20Component-after_update)
    

[Embeddable Mixin Implementations](../components#mixins)

ERC20MixinImpl

*   [`ERC20Impl`](#ERC20Component-Embeddable-Impls-ERC20Impl)
    
*   [`ERC20MetadataImpl`](#ERC20Component-Embeddable-Impls-ERC20MetadataImpl)
    
*   [`ERC20CamelOnlyImpl`](#ERC20Component-Embeddable-Impls-ERC20CamelOnlyImpl)
    

Embeddable Implementations

ERC20Impl

*   [`total_supply(self)`](#ERC20Component-total_supply)
    
*   [`balance_of(self, account)`](#ERC20Component-balance_of)
    
*   [`allowance(self, owner, spender)`](#ERC20Component-allowance)
    
*   [`transfer(self, recipient, amount)`](#ERC20Component-transfer)
    
*   [`transfer_from(self, sender, recipient, amount)`](#ERC20Component-transfer_from)
    
*   [`approve(self, spender, amount)`](#ERC20Component-approve)
    

ERC20MetadataImpl

*   [`name(self)`](#ERC20Component-name)
    
*   [`symbol(self)`](#ERC20Component-symbol)
    
*   [`decimals(self)`](#ERC20Component-decimals)
    

ERC20CamelOnlyImpl

*   [`totalSupply(self)`](#ERC20Component-totalSupply)
    
*   [`balanceOf(self, account)`](#ERC20Component-balanceOf)
    
*   [`transferFrom(self, sender, recipient, amount)`](#ERC20Component-transferFrom)
    

Internal implementations

InternalImpl

*   [`initializer(self, name, symbol)`](#ERC20Component-initializer)
    
*   [`mint(self, recipient, amount)`](#ERC20Component-mint)
    
*   [`burn(self, account, amount)`](#ERC20Component-burn)
    
*   [`update(self, from, to, amount)`](#ERC20Component-update)
    
*   [`_transfer(self, sender, recipient, amount)`](#ERC20Component-_transfer)
    
*   [`_approve(self, owner, spender, amount)`](#ERC20Component-_approve)
    
*   [`_spend_allowance(self, owner, spender, amount)`](#ERC20Component-_spend_allowance)
    

Events

*   [`Transfer(from, to, value)`](#ERC20Component-Transfer)
    
*   [`Approval(owner, spender, value)`](#ERC20Component-Approval)
    

#### [](#ERC20Component-Hooks)
Hooks

Hooks are functions which implementations can extend the functionality of the component source code. Every contract using ERC20Component is expected to provide an implementation of the ERC20HooksTrait. For basic token contracts, an empty implementation with no logic must be provided.

|     |     |
| --- | --- |
|     | You can use `openzeppelin::token::erc20::ERC20HooksEmptyImpl` which is already available as part of the library for this purpose. |

#### [](#ERC20Component-before_update)
`before_update(ref self: ContractState, from: ContractAddress, recipient: ContractAddress, amount: u256)` hook

Function executed at the beginning of the [update](#ERC20Component-update)
 function prior to any other logic.

#### [](#ERC20Component-after_update)
`after_update(ref self: ContractState, from: ContractAddress, recipient: ContractAddress, amount: u256)` hook

Function executed at the end of the [update](#ERC20Component-update)
 function.

#### [](#ERC20Component-Embeddable-functions)
Embeddable functions

#### [](#ERC20Component-total_supply)
`total_supply(@self: ContractState) → u256` external

See [IERC20::total\_supply](#IERC20-total_supply)
.

#### [](#ERC20Component-balance_of)
`balance_of(@self: ContractState, account: ContractAddress) → u256` external

See [IERC20::balance\_of](#IERC20-balance_of)
.

#### [](#ERC20Component-allowance)
`allowance(@self: ContractState, owner: ContractAddress, spender: ContractAddress) → u256` external

See [IERC20::allowance](#IERC20-allowance)
.

#### [](#ERC20Component-transfer)
`transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) → bool` external

See [IERC20::transfer](#IERC20-transfer)
.

Requirements:

*   `recipient` cannot be the zero address.
    
*   The caller must have a balance of at least `amount`.
    

#### [](#ERC20Component-transfer_from)
`transfer_from(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256) → bool` external

See [IERC20::transfer\_from](#IERC20-transfer_from)
.

Requirements:

*   `sender` cannot be the zero address.
    
*   `sender` must have a balance of at least `amount`.
    
*   `recipient` cannot be the zero address.
    
*   The caller must have allowance for `sender`'s tokens of at least `amount`.
    

#### [](#ERC20Component-approve)
`approve(ref self: ContractState, spender: ContractAddress, amount: u256) → bool` external

See [IERC20::approve](#IERC20-approve)
.

Requirements:

*   `spender` cannot be the zero address.
    

#### [](#ERC20Component-name)
`name() → ByteArray` external

See [IERC20Metadata::name](#IERC20Metadata-name)
.

#### [](#ERC20Component-symbol)
`symbol() → ByteArray` external

See [IERC20Metadata::symbol](#IERC20Metadata-symbol)
.

#### [](#ERC20Component-decimals)
`decimals() → u8` external

See [IERC20Metadata::decimals](#IERC20Metadata-decimals)
.

#### [](#ERC20Component-totalSupply)
`totalSupply(self: @ContractState) → u256` external

See [IERC20::total\_supply](#IERC20-total_supply)
.

Supports the Cairo v0 convention of writing external methods in camelCase as discussed [here](https://github.com/OpenZeppelin/cairo-contracts/discussions/34)
.

#### [](#ERC20Component-balanceOf)
`balanceOf(self: @ContractState, account: ContractAddress) → u256` external

See [IERC20::balance\_of](#IERC20-balance_of)
.

Supports the Cairo v0 convention of writing external methods in camelCase as discussed [here](https://github.com/OpenZeppelin/cairo-contracts/discussions/34)
.

#### [](#ERC20Component-transferFrom)
`transferFrom(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress) → bool` external

See [IERC20::transfer\_from](#IERC20-transfer_from)
.

Supports the Cairo v0 convention of writing external methods in camelCase as discussed [here](https://github.com/OpenZeppelin/cairo-contracts/discussions/34)
.

#### [](#ERC20Component-Internal-functions)
Internal functions

#### [](#ERC20Component-initializer)
`initializer(ref self: ContractState, name: ByteArray, symbol: ByteArray)` internal

Initializes the contract by setting the token name and symbol. This should be used inside of the contract’s constructor.

#### [](#ERC20Component-mint)
`mint(ref self: ContractState, recipient: ContractAddress, amount: u256)` internal

Creates an `amount` number of tokens and assigns them to `recipient`.

Emits a [Transfer](#ERC20Component-Transfer)
 event with `from` being the zero address.

Requirements:

*   `recipient` cannot be the zero address.
    

#### [](#ERC20Component-burn)
`burn(ref self: ContractState, account: ContractAddress, amount: u256)` internal

Destroys `amount` number of tokens from `account`.

Emits a [Transfer](#ERC20Component-Transfer)
 event with `to` set to the zero address.

Requirements:

*   `account` cannot be the zero address.
    

#### [](#ERC20Component-update)
`update(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)` internal

Transfers an `amount` of tokens from `from` to `to`, or alternatively mints (or burns) if `from` (or `to`) is the zero address.

|     |     |
| --- | --- |
|     | This function can be extended using the [ERC20HooksTrait](#ERC20Component-ERC20HooksTrait)<br>, to add functionality before and/or after the transfer, mint, or burn. |

Emits a [Transfer](#ERC20Component-Transfer)
 event.

#### [](#ERC20Component-_transfer)
`_transfer(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256)` internal

Moves `amount` of tokens from `from` to `to`.

This internal function does not check for access permissions but can be useful as a building block, for example to implement automatic token fees, slashing mechanisms, etc.

Emits a [Transfer](#ERC20Component-Transfer)
 event.

Requirements:

*   `from` cannot be the zero address.
    
*   `to` cannot be the zero address.
    
*   `from` must have a balance of at least `amount`.
    

#### [](#ERC20Component-_approve)
`_approve(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256)` internal

Sets `amount` as the allowance of `spender` over `owner`'s tokens.

This internal function does not check for access permissions but can be useful as a building block, for example to implement automatic allowances on behalf of other addresses.

Emits an [Approval](#ERC20Component-Approval)
 event.

Requirements:

*   `owner` cannot be the zero address.
    
*   `spender` cannot be the zero address.
    

#### [](#ERC20Component-_spend_allowance)
`_spend_allowance(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256)` internal

Updates `owner`'s allowance for `spender` based on spent `amount`.

This internal function does not update the allowance value in the case of infinite allowance.

Possibly emits an [Approval](#ERC20Component-Approval)
 event.

#### [](#ERC20Component-Events)
Events

#### [](#ERC20Component-Transfer)
`Transfer(from: ContractAddress, to: ContractAddress, value: u256)` event

See [IERC20::Transfer](#IERC20-Transfer)
.

#### [](#ERC20Component-Approval)
`Approval(owner: ContractAddress, spender: ContractAddress, value: u256)` event

See [IERC20::Approval](#IERC20-Approval)
.

[](#extensions)
Extensions
--------------------------

### [](#ERC20VotesComponent)
`ERC20VotesComponent`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/token/erc20/extensions/erc20_votes.cairo)

    use openzeppelin::token::extensions::ERC20VotesComponent;

Extension of ERC20 to support voting and delegation.

|     |     |
| --- | --- |
|     | Implementing [ERC20Component](#ERC20Component)<br> is a requirement for this component to be implemented. |

|     |     |
| --- | --- |
|     | To track voting units, this extension requires that the [transfer\_voting\_units](#ERC20VotesComponent-transfer_voting_units)<br> function is called after every transfer, mint, or burn operation. For this, the [ERC20HooksTrait](#ERC20Component-ERC20HooksTrait)<br> must be used. |

This extension keeps a history (checkpoints) of each account’s vote power. Vote power can be delegated either by calling the [delegate](#ERC20VotesComponent-delegate)
 function directly, or by providing a signature to be used with [delegate\_by\_sig](#ERC20VotesComponent-delegate_by_sig)
. Voting power can be queried through the public accessors [get\_votes](#ERC20VotesComponent-get_votes)
 and [get\_past\_votes](#ERC20VotesComponent-get_past_votes)
.

By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.

Embeddable Implementations

ERC20VotesImpl

*   [`get_votes(self, account)`](#ERC20VotesComponent-get_votes)
    
*   [`get_past_votes(self, account, timepoint)`](#ERC20VotesComponent-get_past_votes)
    
*   [`get_past_total_supply(self, timepoint)`](#ERC20VotesComponent-get_past_total_supply)
    
*   [`delegates(self, account)`](#ERC20VotesComponent-delegates)
    
*   [`delegate(self, delegatee)`](#ERC20VotesComponent-delegate)
    
*   [`delegate_by_sig(self, delegator, delegatee, nonce, expiry, signature)`](#ERC20VotesComponent-delegate_by_sig)
    

Internal implementations

InternalImpl

*   [`get_total_supply(self)`](#ERC20VotesComponent-get_total_supply)
    
*   [`_delegate(self, account, delegatee)`](#ERC20VotesComponent-_delegate)
    
*   [`move_delegate_votes(self, from, to, amount)`](#ERC20VotesComponent-move_delegate_votes)
    
*   [`transfer_voting_units(self, from, to, amount)`](#ERC20VotesComponent-transfer_voting_units)
    
*   [`num_checkpoints(self, account)`](#ERC20VotesComponent-num_checkpoints)
    
*   [`checkpoints(self, account, pos)`](#ERC20VotesComponent-checkpoints)
    
*   [`get_voting_units(self, account)`](#ERC20VotesComponent-get_voting_units)
    

Events

*   [`DelegateChanged(delegator, from_delegate, to_delegate)`](#ERC20VotesComponent-DelegateChanged)
    
*   [`DelegateVotesChanged(delegate, previous_votes, new_votes)`](#ERC20VotesComponent-DelegateVotesChanged)
    

#### [](#ERC20VotesComponent-Embeddable-functions)
Embeddable functions

#### [](#ERC20VotesComponent-get_votes)
`get_votes(self: @ContractState, account: ContractAddress) → u256` external

Returns the current amount of votes that `account` has.

#### [](#ERC20VotesComponent-get_past_votes)
`get_past_votes(self: @ContractState, account: ContractAddress, timepoint: u64) → u256` external

Returns the amount of votes that `account` had at a specific moment in the past.

Requirements:

*   `timepoint` must be in the past.
    

#### [](#ERC20VotesComponent-get_past_total_supply)
`get_past_total_supply(self: @ContractState, timepoint: u64) → u256` external

Returns the total supply of votes available at a specific moment in the past.

|     |     |
| --- | --- |
|     | This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. Votes that have not been delegated are still part of total supply, even though they would not participate in a vote. |

#### [](#ERC20VotesComponent-delegates)
`delegates(self: @ContractState, account: ContractAddress) → ContractAddress` external

Returns the delegate that `account` has chosen.

#### [](#ERC20VotesComponent-delegate)
`delegate(ref self: ContractState, delegatee: ContractAddress)` external

Delegates votes from the caller to `delegatee`.

Emits a [DelegateChanged](#ERC20VotesComponent-DelegateChanged)
 event.

May emit one or two [DelegateVotesChanged](#ERC20VotesComponent-DelegateVotesChanged)
 events.

#### [](#ERC20VotesComponent-delegate_by_sig)
`delegate_by_sig(ref self: ContractState, delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Array<felt252>)` external

Delegates votes from `delegator` to `delegatee` through a SNIP12 message signature validation.

Requirements:

*   `expiry` must not be in the past.
    
*   `nonce` must match the account’s current nonce.
    
*   `delegator` must implement `SRC6::is_valid_signature`.
    
*   `signature` should be valid for the message hash.
    

Emits a [DelegateChanged](#ERC20VotesComponent-DelegateChanged)
 event.

May emit one or two [DelegateVotesChanged](#ERC20VotesComponent-DelegateVotesChanged)
 events.

#### [](#ERC20VotesComponent-Internal-functions)
Internal functions

#### [](#ERC20VotesComponent-get_total_supply)
`get_total_supply(self: @ContractState) → u256` internal

Returns the current total supply of votes.

#### [](#ERC20VotesComponent-_delegate)
`_delegate(ref self: ContractState, account: ContractAddress, delegatee: ContractAddress)` internal

Delegates all of `account`'s voting units to `delegatee`.

Emits a [DelegateChanged](#ERC20VotesComponent-DelegateChanged)
 event.

May emit one or two [DelegateVotesChanged](#ERC20VotesComponent-DelegateVotesChanged)
 events.

#### [](#ERC20VotesComponent-move_delegate_votes)
`move_delegate_votes(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)` internal

Moves `amount` of delegated votes from `from` to `to`.

May emit one or two [DelegateVotesChanged](#ERC20VotesComponent-DelegateVotesChanged)
 events.

#### [](#ERC20VotesComponent-transfer_voting_units)
`transfer_voting_units(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)` internal

Transfers, mints, or burns voting units.

To register a mint, `from` should be zero. To register a burn, `to` should be zero. Total supply of voting units will be adjusted with mints and burns.

May emit one or two [DelegateVotesChanged](#ERC20VotesComponent-DelegateVotesChanged)
 events.

#### [](#ERC20VotesComponent-num_checkpoints)
`num_checkpoints(self: @ContractState, account: ContractAddress) → u32` internal

Returns the number of checkpoints for `account`.

#### [](#ERC20VotesComponent-checkpoints)
`checkpoints(self: @ContractState, account: ContractAddress, pos: u32) → Checkpoint` internal

Returns the `pos`\-th checkpoint for `account`.

#### [](#ERC20VotesComponent-get_voting_units)
`get_voting_units(self: @ContractState, account: ContractAddress) → u256` internal

Returns the voting units of an `account`.

#### [](#ERC20VotesComponent-Events)
Events

#### [](#ERC20VotesComponent-DelegateChanged)
`DelegateChanged(delegator: ContractAddress, from_delegate: ContractAddress, to_delegate: ContractAddress)` event

Emitted when `delegator` delegates their votes from `from_delegate` to `to_delegate`.

#### [](#ERC20VotesComponent-DelegateVotesChanged)
`DelegateVotesChanged(delegate: ContractAddress, previous_votes: u256, new_votes: u256)` event

Emitted when `delegate` votes are updated from `previous_votes` to `new_votes`.

[](#presets)
Presets
--------------------

### [](#ERC20Upgradeable)
`ERC20Upgradeable`[](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0/src/presets/erc20.cairo)

    use openzeppelin::presets::ERC20Upgradeable;

Upgradeable ERC20 contract leveraging [ERC20Component](#ERC20Component)
 with a fixed-supply mechanism for token distribution.

[Sierra class hash](../presets)

0x05ea7bb131bc998b4ce1c0da6170bc8d224c9da558f10cf8a1e2bef193c1074e

Constructor

*   [`constructor(self, name, symbol, fixed_supply, recipient, owner)`](#ERC20Upgradeable-constructor)
    

Embedded Implementations

ERC20MixinImpl

*   [`ERC20MixinImpl`](#ERC20Component-Embeddable-Mixin-Impl)
    

OwnableMixinImpl

*   [`OwnableMixinImpl`](access#OwnableComponent-Mixin-Impl)
    

External Functions

*   [`upgrade(self, new_class_hash)`](#ERC20Upgradeable-upgrade)
    

#### [](#ERC20Upgradeable-constructor-section)
Constructor

#### [](#ERC20Upgradeable-constructor)
`constructor(ref self: ContractState, name: ByteArray, symbol: ByteArray, fixed_supply: u256, recipient: ContractAddress, owner: ContractAddress)` constructor

Sets the `name` and `symbol` and mints `fixed_supply` tokens to `recipient`. Assigns `owner` as the contract owner with permissions to upgrade.

#### [](#ERC20Upgradeable-external-functions)
External functions

#### [](#ERC20Upgradeable-upgrade)
`upgrade(ref self: ContractState, new_class_hash: ClassHash)` external

Upgrades the contract to a new implementation given by `new_class_hash`.

Requirements:

*   The caller is the contract owner.
    
*   `new_class_hash` cannot be zero.
    

[← Creating Supply](/contracts-cairo/0.15.0/guides/erc20-supply)

[ERC721 →](/contracts-cairo/0.15.0/erc721)