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, our code-generation tool.

Available presets

List of available presets and their corresponding Sierra class hashes.

Class hashes were computed using cairo 2.6.3.
Name Sierra Class Hash

AccountUpgradeable

0x01e60c8722677cfb7dd8dbea5be86c09265db02cdfe77113e77da7d44c017388

ERC20Upgradeable

0x040b9e69e14ddc34a98ec8133c80807c144b818bc6cbf5a119d8f62535258142

ERC721Upgradeable

0x04bb176e91b55c87c6e6b1eafd725cebe4514a48f1eec34870c65081de214ef4

ERC1155Upgradeable

0x017baa69866decbb1ac5e6d5ef2e69b7d5dd7113111a8cc51a48f01854df571f

EthAccountUpgradeable

0x042ac0903af3356a92bf61d63a46bb8db7e5f449ad7f8f4e3f1a604223f9c963

UniversalDeployer

0x0536e18e3e9820b48e0477e83e0a4d6d923ccddc06deb61585dfd7402dd40733

starkli class-hash command can be used to compute the class hash from a Sierra artifact.

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, 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 and installing the Contracts for Cairo library. Copy the target preset contract from the presets directory 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"