Announcing OpenZeppelin Contracts for Cairo v0.2.0 

cairo-1

We’ve published v0.2.0, the second release of OpenZeppelin Contracts for Cairo, and updated Wizard to be compatible with this version. On top of supporting the latest Cairo v0.9.0, this release also comes with a lot of changes and additions:

Improved extensibility (i.e. namespaces support 🎉)

We iterated our extensibility pattern leveraging Cairo namespaces, allowing us to drastically simplify imports and coming up with simpler and easier rules.

Short story is: there are contracts and there are libraries. Libraries define behavior and storage while contracts build on top of libraries. Contracts can be deployed – libraries cannot.

Namespaces allow us to better distinguish between four types of library functions and how to approach each of them for secure development:

  • private: private to a library implementation, not meant to be imported by contracts
  • public: part of the public API of a library
  • external: subset of public that is ready to be exported as-is by contracts
  • storage: storage variable functions, should not be directly exposed

To illustrate the improvement, this is how it looks before and after using namespaces:

 

In practice, this is how the new extensibility looks:

%lang starknet

from starkware.cairo.common.cairo_builtins import HashBuiltin
from openzeppelin.security.initializable import Initializable

@view
func initialized{ 

        syscall_ptr : felt*, 
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }() -> (res: felt):
    let (res) = Initializable.initialized()
    return (res=res)
end

@external
func initialize{
        syscall_ptr : felt*, 
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }():
    Initializable.initialize()
    return ()
end

Read more about extensibility in our docs.

 

New Accounts

On top of improving our implementation of the standard Account contract in joint collaboration with the Argent team, we also implemented the first version of an Ethereum-compatible Account contract, the EthAccount.cairo preset.

Moreover, this endeavor pushed us to develop an extensible version of the Account library, allowing you to write your own custom Account contracts. Read more about how to use the Account library in our docs.

⚠️ Note that if you deployed an unreleased version of our Account contract (specifically between commits 574bc03 and fa42ab3), your contract could be vulnerable to a reentrancy attack if deployed to goerli (not mainnet since it requires a custom attacker contract being deployed, which is forbidden by the mainnet whitelist). Migrate your accounts or assets to the latest Account contract version as soon as possible.

AccessControl

This new release comes with an AccessControl library analogous to the one present in OpenZeppelin Contracts for Solidity. Together with Ownable, AccessControl is a fundamental building block for secure access and privileges management.

This is an abridged version of whatAccessControl looks like when trying to restrict a mint method for a MINTER role only:

 

from openzeppelin.access.accesscontrol import AccessControl

# constants
const MINTER_ROLE = 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956

@external
func mint{
        syscall_ptr: felt*,
        pedersen_ptr: HashBuiltin*,
        range_check_ptr
    }(to: felt, amount: Uint256):
    AccessControl.assert_only_role(MINTER)
    ERC20._mint(to, amount)
    return ()
end

You can read more about AccessControl in our docs.

ReentrancyGuard

Another new feature is the well known ReentrancyGuard, a utility to protect functions against reentrancy attacks. Since Cairo does not support modifiers like Solidity, this library exposes two methods, like this:

 

from openzeppelin.security.reentrancy_guard import ReentrancyGuard

func test_function{
        syscall_ptr : felt*,
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }():
   ReentrancyGuard._start()
   # function body
   ReentrancyGuard._end()
   return ()

end

 

You can read more about ReentrancyGuard in our docs.

Other changes

Additional changes include the incorporation of Nile’s Signer to sync implementations with Nile, adding ERC165’s interface IDs to the constants module, and deprecating our own boolean constants in favor of Cairo’s native ones.

We also performed some housekeeping tasks such as adding CONTRIBUTING, RELEASING, and SECURITY files, improving testing performance, and added Cairo syntax highlighting support.

Wizard

Contracts Wizard for Cairo is an interface to interactively build a contract out of components from Contracts for Cairo. It has been updated to be compatible with this release, including support for the improved extensibility pattern mentioned above.

With Wizard, you can select the kind of contract that you want, set your parameters and desired features, and it will generate all of the code necessary. The resulting code is ready to be compiled and deployed, or it can serve as a starting point and be customized further with application specific logic.

Use the Wizard interface to generate a contract and learn more about how different libraries can be used together. You can also use the Wizard API to generate contracts programmatically.

Contributors

Big thank you to all of our contributors including @andrew-fleming, @juniset, @amxx, and @martriay but especially to @milancermak, @JulissaDantes, @ericglau, @0xSidius, @rootulp, @koloz193, @spalladino, @pscott, @jonasalexander, and @nikitastupin for their first contributions.