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.8.4.
Name Sierra Class Hash

AccountUpgradeable

0x04a444ef8caf8fa0db05da60bf0ad9bae264c73fa7e32c61d245406f5523174b

ERC20Upgradeable

0x044491e887497a0dec63a0f3e02bab88abb8cc7594eb9317baa6b847c8c79233

ERC721Upgradeable

0x03ee93221a8ca78ffca36eefcbe9eb8a601e854ce5e68086cdcf30d631090e7e

ERC1155Upgradeable

0x032e3666516e3c138011121baaf898e372f9b23eaae313ad8a401c9b9620d5ae

EthAccountUpgradeable

0x04bc5fe3c036a449c3e2302581aaf3c863d49a3911aa80765cf7c33886114154

UniversalDeployer

0x04cc44533e6a2f0612ba6b7c6cabfebf13e0d5f294504fffc2403ec0a4d1cf9d

VestingWallet

0x02f9206089b6256db631acef1f8ca9f60da133a363600f89b4219f6d92632afa

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 0x044491e887497a0dec63a0f3e02bab88abb8cc7594eb9317baa6b847c8c79233 \
  <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"