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

AccountUpgradeable

0x05b4b537eaa2399e3aa99c4e2e0208ebd6c71bc1467938cd52c798c601e43564

ERC20Upgradeable

0x035997337274dff77d12521875c8f5eec22a8ce54c7bf84aa42ede007ba404cd

ERC721Upgradeable

0x053608a6efad193181fda4f7a28e1522cae2fe6e94ef842b5918f6b3787f1787

ERC1155Upgradeable

0x030cc9a0d86b692955e3b9039eb9a3ebb93c3c66eee79e359420b52069cfce87

EthAccountUpgradeable

0x05ec5819ed53a6c4415d8d0ddd319985699f5f1c86ac2c6e5f1967187eadd987

UniversalDeployer

0x01955b9b1be65fa2eec4183cd6b0e92ce0a44853138ba7c873e3e14535252bda

VestingWallet

0x04f5502b990444bd73e223b353f79e0139e86c6ebd64ef8d9a3f9efec9ea02d5

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