Skip to main content
Glama

OpenZeppelin Contracts MCP Server

Official
by OpenZeppelin
erc20.test.ts.md68.2 kB
# Snapshot report for `src/erc20.test.ts` The actual snapshot is saved in `erc20.test.ts.snap`. Generated by [AVA](https://avajs.dev). ## basic erc20, non-upgradeable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ self.erc20.initializer("MyToken", "MTK");␊ }␊ }␊ ` ## basic erc20 > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 burnable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ self.erc20.burn(get_caller_address(), value);␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 pausable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn before_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let contract_state = self.get_contract();␊ contract_state.pausable.assert_not_paused();␊ }␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.unpause();␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 pausable with roles > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ use super::{PAUSER_ROLE, UPGRADER_ROLE};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl AccessControlMixinImpl = AccessControlComponent::AccessControlMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;␊ impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ accesscontrol: AccessControlComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ AccessControlEvent: AccessControlComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ default_admin: ContractAddress,␊ pauser: ContractAddress,␊ upgrader: ContractAddress,␊ ) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.accesscontrol.initializer();␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn before_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let contract_state = self.get_contract();␊ contract_state.pausable.assert_not_paused();␊ }␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable<ContractState> {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` ## erc20 burnable pausable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn before_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let contract_state = self.get_contract();␊ contract_state.pausable.assert_not_paused();␊ }␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.unpause();␊ }␊ ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ self.erc20.burn(get_caller_address(), value);␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 preminted > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ ␊ self.erc20.mint(recipient, 1000000000000000000000);␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 premint of 0 > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 votes, custom decimals > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ impl ERC20ImmutableConfig of ERC20Component::ImmutableConfig {␊ const DECIMALS: u8 = 6;␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 mintable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.ownable.assert_only_owner();␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 mintable with roles > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::token::erc20::{␊ DefaultConfig as ERC20DefaultConfig, ERC20Component, ERC20HooksEmptyImpl␊ };␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use starknet::{ClassHash, ContractAddress};␊ use super::{MINTER_ROLE, UPGRADER_ROLE};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl AccessControlMixinImpl = AccessControlComponent::AccessControlMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ accesscontrol: AccessControlComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ AccessControlEvent: AccessControlComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ default_admin: ContractAddress,␊ minter: ContractAddress,␊ upgrader: ContractAddress,␊ ) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.accesscontrol.initializer();␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable<ContractState> {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ ` ## erc20 votes > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl VotesInternalImpl = VotesComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn after_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let mut contract_state = self.get_contract_mut();␊ contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ //␊ // SNIP12 Metadata␊ //␊ ␊ impl SNIP12MetadataImpl of SNIP12Metadata {␊ fn name() -> felt252 {␊ 'MY_DAPP_NAME'␊ }␊ ␊ fn version() -> felt252 {␊ 'v1'␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 votes, version > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl VotesInternalImpl = VotesComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn after_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let mut contract_state = self.get_contract_mut();␊ contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ //␊ // SNIP12 Metadata␊ //␊ ␊ impl SNIP12MetadataImpl of SNIP12Metadata {␊ fn name() -> felt252 {␊ 'MY_DAPP_NAME'␊ }␊ ␊ fn version() -> felt252 {␊ 'MY_DAPP_VERSION'␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 votes, non-upgradeable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::ContractAddress;␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl VotesInternalImpl = VotesComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ self.erc20.initializer("MyToken", "MTK");␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn after_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let mut contract_state = self.get_contract_mut();␊ contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ //␊ // SNIP12 Metadata␊ //␊ ␊ impl SNIP12MetadataImpl of SNIP12Metadata {␊ fn name() -> felt252 {␊ 'MY_DAPP_NAME'␊ }␊ ␊ fn version() -> felt252 {␊ 'v1'␊ }␊ }␊ }␊ ` ## erc20 full, non-upgradeable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ContractAddress, get_caller_address};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ impl VotesInternalImpl = VotesComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ ␊ self.erc20.mint(recipient, 2000000000000000000000);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn before_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let contract_state = self.get_contract();␊ contract_state.pausable.assert_not_paused();␊ }␊ ␊ fn after_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let mut contract_state = self.get_contract_mut();␊ contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.unpause();␊ }␊ ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ self.erc20.burn(get_caller_address(), value);␊ }␊ ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.ownable.assert_only_owner();␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ ␊ //␊ // SNIP12 Metadata␊ //␊ ␊ impl SNIP12MetadataImpl of SNIP12Metadata {␊ fn name() -> felt252 {␊ 'MY_DAPP_NAME'␊ }␊ ␊ fn version() -> felt252 {␊ 'MY_DAPP_VERSION'␊ }␊ }␊ }␊ ` ## erc20 full upgradeable > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::ownable::OwnableComponent;␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;␊ impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;␊ impl VotesInternalImpl = VotesComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ ownable: OwnableComponent::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ OwnableEvent: OwnableComponent::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ ␊ self.erc20.mint(recipient, 2000000000000000000000);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn before_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let contract_state = self.get_contract();␊ contract_state.pausable.assert_not_paused();␊ }␊ ␊ fn after_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let mut contract_state = self.get_contract_mut();␊ contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ self.ownable.assert_only_owner();␊ self.pausable.unpause();␊ }␊ ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ self.erc20.burn(get_caller_address(), value);␊ }␊ ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.ownable.assert_only_owner();␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ ␊ //␊ // SNIP12 Metadata␊ //␊ ␊ impl SNIP12MetadataImpl of SNIP12Metadata {␊ fn name() -> felt252 {␊ 'MY_DAPP_NAME'␊ }␊ ␊ fn version() -> felt252 {␊ 'MY_DAPP_VERSION'␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[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);␊ }␊ }␊ }␊ ` ## erc20 full upgradeable with roles > Snapshot 1 `// SPDX-License-Identifier: MIT␊ // Compatible with OpenZeppelin Contracts for Cairo ^2.0.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE");␊ ␊ #[starknet::contract]␊ mod MyToken {␊ use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};␊ use openzeppelin::governance::votes::VotesComponent;␊ use openzeppelin::introspection::src5::SRC5Component;␊ use openzeppelin::security::pausable::PausableComponent;␊ use openzeppelin::token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20Component};␊ use openzeppelin::upgrades::interface::IUpgradeable;␊ use openzeppelin::upgrades::UpgradeableComponent;␊ use openzeppelin::utils::cryptography::nonces::NoncesComponent;␊ use openzeppelin::utils::cryptography::snip12::SNIP12Metadata;␊ use starknet::{ClassHash, ContractAddress, get_caller_address};␊ use super::{MINTER_ROLE, PAUSER_ROLE, UPGRADER_ROLE};␊ ␊ component!(path: ERC20Component, storage: erc20, event: ERC20Event);␊ component!(path: PausableComponent, storage: pausable, event: PausableEvent);␊ component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);␊ component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);␊ component!(path: VotesComponent, storage: votes, event: VotesEvent);␊ component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);␊ ␊ // External␊ #[abi(embed_v0)]␊ impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl PausableImpl = PausableComponent::PausableImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl AccessControlMixinImpl = AccessControlComponent::AccessControlMixinImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl NoncesImpl = NoncesComponent::NoncesImpl<ContractState>;␊ #[abi(embed_v0)]␊ impl VotesImpl = VotesComponent::VotesImpl<ContractState>;␊ ␊ // Internal␊ impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;␊ impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;␊ impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;␊ impl VotesInternalImpl = VotesComponent::InternalImpl<ContractState>;␊ impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;␊ ␊ #[storage]␊ struct Storage {␊ #[substorage(v0)]␊ erc20: ERC20Component::Storage,␊ #[substorage(v0)]␊ pausable: PausableComponent::Storage,␊ #[substorage(v0)]␊ accesscontrol: AccessControlComponent::Storage,␊ #[substorage(v0)]␊ src5: SRC5Component::Storage,␊ #[substorage(v0)]␊ nonces: NoncesComponent::Storage,␊ #[substorage(v0)]␊ votes: VotesComponent::Storage,␊ #[substorage(v0)]␊ upgradeable: UpgradeableComponent::Storage,␊ }␊ ␊ #[event]␊ #[derive(Drop, starknet::Event)]␊ enum Event {␊ #[flat]␊ ERC20Event: ERC20Component::Event,␊ #[flat]␊ PausableEvent: PausableComponent::Event,␊ #[flat]␊ AccessControlEvent: AccessControlComponent::Event,␊ #[flat]␊ SRC5Event: SRC5Component::Event,␊ #[flat]␊ NoncesEvent: NoncesComponent::Event,␊ #[flat]␊ VotesEvent: VotesComponent::Event,␊ #[flat]␊ UpgradeableEvent: UpgradeableComponent::Event,␊ }␊ ␊ #[constructor]␊ fn constructor(␊ ref self: ContractState,␊ recipient: ContractAddress,␊ default_admin: ContractAddress,␊ pauser: ContractAddress,␊ minter: ContractAddress,␊ upgrader: ContractAddress,␊ ) {␊ self.erc20.initializer("MyToken", "MTK");␊ self.accesscontrol.initializer();␊ ␊ self.erc20.mint(recipient, 2000000000000000000000);␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ self.accesscontrol._grant_role(PAUSER_ROLE, pauser);␊ self.accesscontrol._grant_role(MINTER_ROLE, minter);␊ self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader);␊ }␊ ␊ impl ERC20HooksImpl of ERC20Component::ERC20HooksTrait<ContractState> {␊ fn before_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let contract_state = self.get_contract();␊ contract_state.pausable.assert_not_paused();␊ }␊ ␊ fn after_update(␊ ref self: ERC20Component::ComponentState<ContractState>,␊ from: ContractAddress,␊ recipient: ContractAddress,␊ amount: u256,␊ ) {␊ let mut contract_state = self.get_contract_mut();␊ contract_state.votes.transfer_voting_units(from, recipient, amount);␊ }␊ }␊ ␊ #[generate_trait]␊ #[abi(per_item)]␊ impl ExternalImpl of ExternalTrait {␊ #[external(v0)]␊ fn pause(ref self: ContractState) {␊ self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ self.pausable.pause();␊ }␊ ␊ #[external(v0)]␊ fn unpause(ref self: ContractState) {␊ self.accesscontrol.assert_only_role(PAUSER_ROLE);␊ self.pausable.unpause();␊ }␊ ␊ #[external(v0)]␊ fn burn(ref self: ContractState, value: u256) {␊ self.erc20.burn(get_caller_address(), value);␊ }␊ ␊ #[external(v0)]␊ fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ self.erc20.mint(recipient, amount);␊ }␊ }␊ ␊ //␊ // SNIP12 Metadata␊ //␊ ␊ impl SNIP12MetadataImpl of SNIP12Metadata {␊ fn name() -> felt252 {␊ 'MY_DAPP_NAME'␊ }␊ ␊ fn version() -> felt252 {␊ 'MY_DAPP_VERSION'␊ }␊ }␊ ␊ //␊ // Upgradeable␊ //␊ ␊ #[abi(embed_v0)]␊ impl UpgradeableImpl of IUpgradeable<ContractState> {␊ fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {␊ self.accesscontrol.assert_only_role(UPGRADER_ROLE);␊ self.upgradeable.upgrade(new_class_hash);␊ }␊ }␊ }␊ `

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/OpenZeppelin/contracts-wizard'

If you have feedback or need assistance with the MCP directory API, please join our Discord server