# Starknet v0.12 Quantum Leap 👉👈 

By [Extropy](https://paragraph.com/@extropy) · 2023-07-05

---

  

Quantum Leap is a game-changer for Starknet, offering reported improvements that are seven times better than previous versions, with an initial estimated throughput of 40 TPS and a latency of 30 seconds. Furthermore, the Cairo syntax has recently undergone a facelift and received further enhancements. It is already available on the testnet and will soon be deployed on the mainnet in the upcoming weeks.

In this article, we will explore some of the changes in the Cairo syntax.

Let’s delve in.

Changes to the Cairo Syntax
---------------------------

The new changes were initially posted on June 11th by [@FeedTheFed](https://twitter.com/FeedTheFed) in the Starknet community forum. You can find the full version of the post [here](https://community.starknet.io/t/cairo-1-contract-syntax-is-evolving/94794).

Two main important things are being addressed, and those are safety and extendibility. This article will focus on the safety side, while we will cover the extendibility in another article.

On the safety side, there are three major changes that we will delve into: contract interface, storage, and events.

But first, let’s examine an example contract with the new syntax:

    #[starknet::interface]
    trait IExternalContract<TContractState> {
        fn subtraction_allowed(self: @TContractState) -> bool;
    }
    
    #[starknet::interface]
    trait iMathContract<TContractState> {
        fn get_total(self: @TContractState) -> u128
        fn addition(ref self: TContractState, amount: u128);
        fn subtraction(ref self: TContractState, amount: u128);
    }
    
    #[starknet::contract]
    mod math_contract{
        use starknet::ContractAddress;
        use super:: {
        IExternalContractDispatcher,
        IExternalContractDispatcherTrait,
        IExternalContractLibraryDispatcher
        };
    
          #[storage]
        struct Storage {
            total: u128,
            external_contract : IExternalContractDispatcher
        }
    
        #[event]
        #[derive(Drop, starknet::Event)]
        enum Event {
            Addition: Addition,
            Subtraction: Subtraction
        }
    
        #[derive(Drop, starknet::Event)]
        struct Addition {
            amount: u128
        }
    
            #[derive(Drop, starknet::Event)]
        struct Subtraction {
            amount: u128
        }
    
        #[constructor]
        fn constructor(ref self: ContractState, _initial_value: u128, _external_contract: ContractAddress){
            self.total.write(_initial_value);
            self.external_contract.write(IExternalContractDispatcher {contract_address: _external_contract})
        }
    
        #[external(v0)]
        impl MathContract of super::iMathContract<ContractState>{
            fn get_total(self: @ContractState) -> u128 {
                self.total.read()
            }
    
                    fn addition(ref self: ContractState, amount: u128){
                let current_total = self.total.read();
                self.total.write(current_total + amount);
                self.emit(Addition { amount });
            }
    
                fn subtraction(ref self: ContractState, amount: u128){
                let allowed = self.external_contract.read().subtraction_allowed();
                if allowed {
                    let current_total = self.total.read();
                    self.total.write(current_total - amount);
                    self.emit(Subtraction { amount });
                }
            }
        }
    }
    

Let’s analyse the contract and examine each individual component more closely.

Contract Interfaces
-------------------

By leveraging `traits` and `impls`, contract interfaces can become more readable, with improved clarity and safety ensured when interacting with the contract.

One noticeable change is that all the Starknet related attributes that are outside the contract module will be defined with the `#[starknet::]` prefix from now on.

For example in the previous version of Cairo (v.1.0.0 for example) we would define an external interface such as:

    #[abi]
    trait IExternalContract {
     fn subtraction_allowed() -> bool;
    }
    

In the new syntax, this is done as:

    #[starknet::interface]
    trait IExternalContract<TContractState> {
     fn subtraction_allowed(self: @TContractState) -> bool;
    }
    

Storage now will require the `#[storage]` attribute when defining the contract’s storage.

    #[storage]
    struct Storage {
        total: u128,
        external_contract : IExternalContractDispatcher
    }
    

Other changes include introduction of new generic types such as `TContractState` and `self`. These new generic types aim to introduce storage safety, better readability and overall avoidance of any side effects when interacting with the contract state and storage variables.

    #[starknet::interface]
    trait iMathContract<TContractState> {
     fn get_total(self: @TContractState) -> u128
     fn addition(ref self: TContractState, amount: u128);
     fn subtraction(ref self: TContractState, amount: u128);
    

In the example above, we define a trait called `iMathContract`, and pass the contract state as `TContractState` . In this trait we defined a view function `get_total()` and two external functions namely `addition()` and `subtraction()`. The `self` parameter in each of these functions refers to contract state.

In the previous version of Cairo the view function was denoted by the `#[view]` attribute, however in the new syntax this has been removed. The reason why is that we define the `get_counter` function “indirectly” by passing a [snapshot](https://cairo-book.github.io/ch03-02-references-and-snapshots.html?highlight=snap#snapshots) of the `@TContractState`, denominated by the argument `@`. This infers that the function has _read-only_ access to the state and cannot be changed.

    fn get_total(self: @TContractState) -> u128
    

For `#[external]` functions, we no longer need to explicitly define the attribute, as our external function will be part of the implementation of the `IMathContract` trait. The signature of the function makes it clear that external functions modify the state by using the `ref` argument, implying that `self` may be modified and at the end of the function, ownership of `self` is implicitly returned to the caller. `rust fn addition(ref self: TContractState, amount: u128);`

#\[external(v0)\]
-----------------

The reason why we need the `(v0)` argument in the `#[external(v0)]` attribute is that future compilers will support multiple `impls` under the same name. Currently, the compiler does not accept multiple `impls`, but this will be possible in the near future. The `(v0)` is added to ensure that current contracts remain compatible with future compilers that allow multiple `impls` even when compiling with a new compiler.

    #[external(v0)]
    impl MathContract of super::iMathContract<ContractState>{
    }
    

Multiple impls
--------------

With the new syntax, it will be possible in future versions to define two `impls` with the same name, allowing us to define different behaviours for the contract. For example, we can have two `impls` with the same name but using different integer types such as `u128` and `u256` :

    #[starknet::interface]
    trait iMathContract<TContractState> {
     fn get_total(self: @TContractState) -> u128
     fn addition(ref self: TContractState, amount: u128);
     fn subtraction(ref self: TContractState, amount: u128);
    
     #[starknet::interface]
    trait iMathContract<TContractState> {
     fn get_total(self: @TContractState) -> u256
     fn addition(ref self: TContractState, amount: u256);
     fn subtraction(ref self: TContractState, amount: u256);
    

Events have undergone changes in their syntax as well. Now, we need to use the #\[event\] attribute to define events and unify them under enum Event{}. Each event must be defined as a struct and derived from starknet::Event.

    #[event]
    #[derive(Drop, starknet::Event)]
    enum Event {
     Addition: Addition,
     Subtraction: Subtraction
    }
    
    #[derive(Drop, starknet::Event)]
    struct Addition {
     amount: u128
    }
    
    #[derive(Drop, starknet::Event)]
    struct Subtraction {
     amount: u128
    }
    

To emit an event, you need to call it within a function that has access to the `ContractState`. You can emit the event by calling `self.emit()` followed by the event name and the corresponding data.

    fn addition(ref self: ContractState, amount: u128){
     self.emit(Addition { amount });
    }
    

New features added:

For a full release note check out the full report [here](https://github.com/starkware-libs/cairo/commits/v2.0.0)

*   introduction of the `||` and `&&` operators
    
*   possibility of short circuiting with logical operators
    
*   `#[generate_trait]` attribute
    
*   `return;` and `break;` support
    
*   support for `pop_log` in testing
    

For more information on the differences between the old syntax and the new syntax check out [Starknet Documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Cairo_on_Starknet/contract-syntax/).

---

*Originally published on [Extropy](https://paragraph.com/@extropy/starknet-v0-12-quantum-leap)*
