Starknet Smart Contract Model & Native AA

Intermediate3/19/2024, 6:02:11 AM
Starknet supports native-level AA account abstraction, allowing highly customizable transaction processing solutions, and implements multiple countermeasures to ensure security. These features create necessary conditions for Starknet to support functions like storage layering and garbage contract detection, despite some functionalities not yet implemented, providing an important foundation for the AA ecosystem.

Forward the Original Title:解读Starknet智能合约模型与原生AA:特立独行的技术巨匠

Original Authors: Shew & Faust, Web3 Advisors: CryptoNerdCn, Starknet Core Developer, Browser-Side Cairo Development Platform WASM Cairo Founder

Abstract:

The main technological features of Starknet include the Cairo language, which is conducive to generating ZK proofs, native-level AA, and a smart contract model where business logic is independent of state storage. Cairo is a versatile ZK language that can be used to implement smart contracts on Starknet as well as develop applications with traditional leanings. Its compilation process introduces Sierra as an intermediate language, enabling frequent iterations of Cairo without changing the underlying bytecode directly. Moreover, Cairo’s standard library includes many basic data structures required for account abstraction. Starknet smart contracts separate business logic from state data storage, unlike EVM chains. The deployment of Cairo contracts involves three stages: compilation, declaration, and deployment, where business logic is declared in a Contract class. Instances of contracts containing state data can be associated with the class and call the code it contains.

The above-mentioned smart contract model of Starknet is conducive to code reuse, contract state reuse, storage layering, and detection of junk contracts. It is also conducive to the realization of storage leasing and transaction parallelization. Although the latter two have not yet been implemented, the structure of Cairo smart contracts has created “necessary conditions” for them. ·There are only smart contract accounts on the Starknet chain and no EOA accounts. It supports native-level AA account abstraction from the start. Its AA plan incorporates the ideas of ERC-4337 to a certain extent, allowing users to choose highly customized transaction processing solutions. In order to prevent potential attack scenarios, Starknet has taken many countermeasures and made important explorations into the AA ecosystem.

text: Following the issuance of tokens on Starknet, STRK gradually became an indispensable element in the eyes of Ethereum observers. This Ethereum Layer 2 star, known for its “independent” and “disregarding user experience” attitude, quietly carved out its own territory in the flourishing Layer 2 ecosystem compatible with EVM. Due to its excessive neglect of users, and even openly setting up an “electronic beggar” channel on Discord, Starknet was once criticized by the community. Amidst accusations of being “inhuman”, its profound technical expertise seemed instantly devalued, as if only UX and wealth creation were everything. The line from “The Temple of the Golden Pavilion” - “the fact of not being understood by others had been my sole source of pride” - is almost a self-portrait of Starknet. However, setting aside these trivial matters of the world, purely based on the technical taste of code geeks, Starknet and StarkEx, as pioneers of ZK Rollup, are almost treasures in the eyes of Cairo enthusiasts. In the minds of some blockchain game developers, Starknet and Cairo are simply everything in Web3, surpassing Solidity and Move. The biggest gap between “technical geeks” and “users” today is actually largely attributed to people’s lack of understanding of Starknet. Driven by an interest in blockchain technology and the exploration of Starknet’s value, the author of this article starts from Starknet’s smart contract model and native AA to briefly outline its technical solutions and mechanism designs, aiming to showcase Starknet’s technical features to more people, while also hoping to help people understand this “misunderstood lone ranger”. Following a brief introduction to the Cairo language in the subsequent section, we will focus on discussing Starknet’s smart contract model and native account abstraction, explaining how Starknet achieves native AA. After reading this article, readers will also understand why mnemonic phrases from different wallets cannot be mixed in Starknet. But before introducing native account abstraction, let’s first understand the innovative Cairo language created by Starknet. In the development process of Cairo, there were early versions called Cairo0, followed by the modern version. The overall syntax of Cairo’s modern version is similar to Rust and is actually a versatile ZK language. Besides being used to write smart contracts on Starknet, it can also be used for the development of general applications. For example, we can develop a ZK identity verification system using the Cairo language, and this program can run on our own server without depending on the StarkNet network. It can be said that any program requiring verifiable computational properties can be implemented using the Cairo language. And Cairo may currently be the programming language most conducive to generating ZK proofs.

From the perspective of the compilation process, Cairo uses an intermediate language-based compilation method, as shown in the figure below. Sierra in the picture is an intermediate representation (IR) in the Cairo language compilation process, and Sierra will be compiled into a lower-level binary code representation, named CASM, which runs directly on the Starknet node device.

Introducing Sierra as an intermediate representation makes it easier for the Cairo language to add new features. In many cases, it is only necessary to manipulate the Sierra intermediate language without directly changing the underlying CASM code. This saves a lot of trouble, and Starknet’s node client does not need to be updated frequently. In this way, frequent iterations of the Cairo language can be achieved without changing the underlying logic of StarkNet. Cairo’s standard library also includes many basic data structures required for account abstraction. Cairo’s other innovations include a theoretical solution called Cairo Native, which plans to compile Cairo into low-level machine code that can adapt to different hardware devices. Starknet nodes will not have to rely on the CairoVM virtual machine when running smart contracts. This can greatly improve the code execution speed [it is still in the theoretical stage and has not yet been implemented].

Starknet smart contract model: stripping code logic and state storage

Unlike Ethereum-compatible chains, Starknet has made groundbreaking innovations in the design of its smart contract system, largely in preparation for native AA and upcoming features like parallel transaction processing. Here, it’s important to understand that, unlike traditional public chains like Ethereum, smart contract deployment on Starknet follows a different process. Let’s take the example of deploying an Ethereum smart contract:

  1. Developers write the smart contract code locally and compile the Solidity program into EVM bytecode using an editor. This bytecode can then be understood and processed directly by the EVM.
  1. The developer initiates a transaction to deploy the smart contract, deploying the compiled EVM bytecode onto the Ethereum chain.

Source: not-satoshi.com

Although Starknet’s smart contracts also follow the idea of ​​”compile first and then deploy”, Smart contracts are deployed on the chain in the form of CASM bytecode supported by CairoVM. However, there are huge differences between Starknet and EVM-compatible chains in the calling method and state storage mode of smart contracts. Exactly, Ethereum smart contract = business logic + status information. For example, the USDT contract not only implements common functions such as Transfer and Approval, but also stores the asset status of all USDT holders. Code and state are coupled together, which brings a lot of trouble. First of all, it is not conducive to DAPP contract upgrade and state migration, nor conducive to parallel processing of transactions. It is a heavy technical burden.

In response to this, Starknet has improved the way state is stored. In its smart contract implementation solution, the business logic of DApps is completely decoupled from asset states and stored separately. The benefits of this approach are evident: firstly, it allows the system to quickly distinguish whether there are duplicate or redundant code deployments. Here’s how it works: in Ethereum, a smart contract comprises both business logic and state data. If multiple contracts have identical business logic but different state data, their hashes will also differ, making it difficult for the system to determine whether “garbage contracts” exist. However, in Starknet’s solution, the code and state data are separated, making it easier for the system to detect whether the same code has been deployed multiple times based on the hash of the code portion. This helps prevent duplicate code deployment and saves storage space on Starknet nodes.

In Starknet’s smart contract system, the deployment and usage of contracts are divided into three stages: “compile, declare, and deploy.” If an asset issuer wants to deploy a Cairo contract, they first compile the written Cairo code into Sierra and lower-level bytecode CASM forms on their local device. Then, the contract deployer publishes a “declare” transaction, deploying the contract’s CASM bytecode and Sierra intermediate code onto the chain, named as the Contract Class.

(Source: Starknet official website)

Later, if you want to utilize the function capabilities defined in the asset contract, you can initiate a “deploy” transaction through the DApp frontend to deploy a Contract instance associated with the Contract Class. This instance will hold the asset state. Subsequently, users can call the functions within the Contract Class to modify the state of the Contract instance. In fact, anyone familiar with object-oriented programming should easily understand what Class and Instance represent in Starknet. The Contract Class declared by developers only contains the business logic of the smart contract, comprising functions that anyone can call, but it does not have actual asset state, thus not directly implementing “asset entities,” having only the “soul” without the “body.” However, when users deploy specific Contract instances, the assets are “materialized.” If you need to modify the state of the asset “entity,” such as transferring your tokens to someone else, you can directly call the functions written in the Contract Class. The above process is somewhat similar to “instantiation” in traditional object-oriented programming languages (although not entirely identical).

After smart contracts are separated into classes and instances, business logic and status data are decoupled, bringing the following features to Starknet:

  1. Conducive to the realization of storage tiering and “storage leasing system”

The so-called storage layering means that developers can place data in customized locations according to their own needs, such as under the Starknet chain. StarkNet is ready to be compatible with DA layers such as Celestia, and DAPP developers can store data in these third-party DA layers. For example, a game can store its most important asset data on the Starknet mainnet, and store other data in off-chain DA layers such as Celestia.This solution of customizing the DA layer according to security requirements was named “Volition” by Starknet.

The so-called storage rental system means that everyone should continue to pay for the storage space they occupy. As much space on the chain as you occupy, you should theoretically continue to pay rent.

In the Ethereum smart contract model, the ownership of the contract is unclear, and it is difficult to distinguish whether the deployer or the asset holder should pay “rent” for an ERC-20 contract. The storage leasing function has not been launched for a long time, and the deployer is only charged a fee when the contract is deployed. This storage fee model is unreasonable.

Under the smart contract models of Starknet, Sui, CKB, and Solana, the ownership of smart contracts is more clearly divided, making it easier to collect storage funds [Currently, Starknet does not directly launch a storage leasing system, but it will be implemented in the future]

  1. Achieve true code reuse and reduce the deployment of junk contracts

We can declare a general token contract to be stored on the chain as a class, and then everyone can call the functions in this class to deploy their token instances. Moreover, the contract can also directly call the code in the class, which achieves an effect similar to the Library function library in Solidity. At the same time, Starknet’s smart contract model helps identify “junk contracts”. This was explained earlier. After supporting code reuse and junk contract detection, Starknet can significantly reduce the amount of data uploaded to the chain and reduce the storage pressure on nodes as much as possible.

  1. Reuse of real contract “state”

Contract upgrades on the blockchain mainly involve changes to business logic. In the Starknet scenario, the business logic of smart contracts is inherently separated from the asset status. If the contract instance changes the associated contract type class, the business logic upgrade can be completed. There is no need to migrate the asset status to a new place. This form of contract upgrade is more thorough and native than Ethereum’s.

To change the business logic of an Ethereum contract, it is often necessary to “outsource” the business logic to an agency contract, and change the business logic of the main contract by changing the dependent agency contract. However, this method is not concise enough and is not “native”.

Source: wtf Academy

In some scenarios, if the old Ethereum contract is completely abandoned, the asset status inside cannot be directly migrated to the new place, which is very troublesome; the Cairo contract does not need to migrate the status and can directly “reuse” the old status.

  1. Conducive to parallel processing of transactions

To maximize the parallelism of different trading instructions, a necessary step is to store the asset status of different people in separate locations, as can be seen in Bitcoin, CKB and Sui. The prerequisite for the above goal is to separate the business logic of smart contracts from asset status data. Although Starknet has not yet carried out in-depth technical implementation of parallel transactions, it will regard parallel transactions as an important goal in the future.

Starknet’s native AA and account contract deployment

In fact, the concept of account abstraction (AA) and EOA (externally owned accounts) was invented by the Ethereum community as a unique concept. In many new public chains, there is no distinction between EOA accounts and smart contract accounts, avoiding the pitfalls of the Ethereum-style account system from the beginning. For example, under the setting of Ethereum, the EOA account controller must have ETH on the chain before he can initiate a transaction. There is no way to directly choose a variety of authentication methods, and it is extremely troublesome to add some customized payment logic. Some people even think that the account design of Ethereum is simply anti-human.

If we look at flagship products such as Starknet or zkSyncEra “Native AA” chain, obviously differences can be observed: first, Starknet and zkSyncEra have unified account types. There are only smart contract accounts on the chain. There is no such thing as an EOA account from the beginning. (zkSync Era will deploy a set of contract codes by default on the user’s newly created account to simulate the characteristics of the Ethereum EOA account, so that it is compatible with Metamask).

However, Starknet does not consider directly compatibility with Ethereum peripherals such as Metamask. When users use the Starknet wallet for the first time, a dedicated contract account is automatically deployed. In other words, the previously mentioned contract instance is deployed, and this instance is associated with the contract class deployed in advance by the wallet project. Users can directly call some of the functionalities written in the class. Now, let’s delve into an interesting topic: when claiming STRK airdrops, many people found that the Argent and Braavos wallets were not compatible with each other. Importing the mnemonic from Argent to Braavos did not allow exporting the corresponding account, mainly due to the different account generation algorithms used by Argent and Braavos, resulting in different account addresses generated from the same mnemonic. Specifically, in Starknet, the newly deployed contract address can be derived through a deterministic algorithm, as follows:

The ‘pedersen()’ function mentioned above is a hash algorithm that is easy to use in ZK systems. The process of generating the account involves providing several special parameters to the pedersen function to generate the corresponding hash, which is the generated account address. The image above shows the parameters used by Starknet to generate the “new contract address”. The ‘deployer_address’ represents the address of the “contract deployer”. This parameter can be empty, meaning that even if you do not have a Starknet contract account in advance, you can still deploy a new contract. The ‘salt’ is the salt value used to calculate the contract address, which is essentially a random number introduced to avoid duplicate contract addresses. The ‘class_hash’ corresponds to the hash value of the class mentioned earlier, which the contract instance is associated with. The ‘constructor_calldata_hash’ represents the hash of the contract’s initialization parameters.

Based on the above formula, users can calculate the generated contract address before deploying the contract to the chain. Starknet allows users to deploy contracts directly without having a Starknet account in advance, as follows:

  1. Users first determine the contract instance they want to deploy and which contract class to associate it with, using the hash of the class as one of the initialization parameters, and calculate the salt to determine the generated contract address.
  2. After knowing where they will deploy the contract, users first transfer a certain amount of ETH to that address as the contract deployment fee. Generally, this ETH needs to be transferred from L1 to the Starknet network via a cross-chain bridge.
  3. Users initiate the transaction request for contract deployment.

In fact, all Starknet accounts are deployed through the above process, but most wallets shield the details, and users do not perceive the process as their contract account being deployed as soon as they transfer ETH.

The above solution has brought about some compatibility issues, because when different wallets generate account addresses, the results generated are inconsistent. Only wallets that meet the following conditions can be mixed:

  1. The private key derived public key used by the wallet is the same as the signature algorithm;
  2. The wallet’s salt calculation process is the same;
  3. The wallet’s smart contract classes are not fundamentally different in implementation details; \

In the case mentioned earlier, both Argent and Braavos used the ECDSA signature algorithm, but the calculation methods for the salt were different between the two, resulting in inconsistent account addresses generated from the same mnemonic.

Now, let’s revisit the topic of account abstraction. Starknet and zkSync Era have moved a series of processes involved in transaction processing, such as identity verification (verifying digital signatures) and gas fee payment, outside of the “chain layer.” Users can customize the implementation details of the above logic in their own accounts. For example, you can deploy a dedicated digital signature verification function in your Starknet smart contract account. When a Starknet node receives a transaction initiated by you, it will call a series of transaction processing logic customized by you on the chain.

This approach clearly offers more flexibility. In Ethereum’s design, however, logic such as identity verification (digital signatures) is hardcoded into the node client code and cannot natively support customizable account features.

Schematic diagram of the native AA solution specified by the Starknet architect. Transaction verification and gas fee qualification verification are transferred to the on-chain contract for processing. The underlying virtual machine of the chain can call these functions customized or specified by the user.

According to zkSyncEra and Starknet officials, this modular approach to account functionality is inspired by EIP-4337. However, what sets them apart is that zkSync and Starknet merged account types from the outset, unified transaction types, and utilized a single entry point to receive and process all transactions. In contrast, Ethereum, due to historical baggage and the foundation’s desire to avoid aggressive iteration strategies such as hard forks as much as possible, supported the EIP-4337, using a different way to solve the problem. However, the result is that EOA accounts and EIP-4337 solutions each have independent transaction processing workflows, which appear awkward and cumbersome, unlike the agility of native AAs.

Source: ArgentWallet

However, the native account abstraction in Starknet has not yet reached full maturity. From a practical standpoint, while Starknet’s AA accounts have implemented custom signature verification algorithms, they currently only support paying gas fees in ETH and STRK, and do not yet support third-party gas payment. Therefore, the progress of Starknet in native AAs can be described as “the theoretical framework is mostly mature, while the practical implementation is still in progress”. Since Starknet only has smart contract accounts internally, the entire process of its transactions takes into account the influence of account smart contracts. First, after a transaction is received by the Starknet node’s memory pool (Mempool), it undergoes verification, which includes:

  1. Checking if the transaction’s digital signature is correct, at which point the signer’s account’s custom verification function is called;
  2. Verifying if the initiator’s account balance can cover the gas fee. \

It should be noted here that using the customized signature verification function in the account smart contract means that there is an attack scenario. Because the memory pool does not charge gas fees when verifying the signature of new transactions. (If gas fees are charged directly, more serious attack scenarios will occur). Malicious users can first customize a super complex signature verification function in their account contract, and then initiate a large number of transactions. When these transactions are verified, they will call the customized complex signature verification function, which can directly exhaust the node’s computing resources. In order to avoid this situation, StarkNet imposes the following restrictions on transactions:

  1. There is an upper limit on the number of transactions that a single user can initiate within a unit time;
  2. The custom signature verification function in the Starknet account contract has complexity limitations, and overly complex signature verification functions will not be executed. Starknet limits the gas consumption limit of the signature verification function. If the amount of gas consumed by the signature verification function is too high, the transaction will be directly rejected. At the same time, the signature verification function in the account contract is not allowed to call other contracts.

The flow chart of Starknet transactions is as follows:

It is worth noting that, to further expedite the transaction verification process, the Starknet node client has directly implemented the signature verification algorithms of Braavos and Argent wallets. When a node detects transactions generated from these two major mainstream Starknet wallets, it will call the built-in Braavos/Argent signature algorithms in the client. Through this caching-like approach, Starknet can shorten the transaction verification time. After the transaction data is validated by the sequencer (the sequencer’s verification steps are much more thorough than those of the memory pool), the sequencer will package and submit the transactions from the memory pool to the ZK proof generator. Transactions entering this stage will be charged gas fees even if they fail. However, if readers are familiar with Starknet’s history, they will notice that earlier versions of Starknet did not charge fees for failed transactions. The most common scenario for transaction failure is when a user has only 1 ETH but attempts to transfer 10 ETH externally, which clearly indicates a logic error and will inevitably fail, but no one knows the outcome before execution. However, in the past, StarkNet did not charge fees for such failed transactions. These cost-free erroneous transactions waste Starknet node computational resources and can lead to DDoS attack scenarios. On the surface, charging fees for erroneous transactions seems straightforward, but in reality, it is quite complex. Starknet introduced a new version of the Cairo1 language largely to address the issue of gas charges for failed transactions. As we all know, a ZK proof is a proof of validity, and the result of a failed transaction is invalid and cannot leave an output result on the chain. Attempting to use a validity proof to prove that a certain instruction execution is invalid and cannot produce output results sounds strange and is actually unworkable. Therefore, in the past, Starknet excluded failed transactions that could not produce output results when generating proofs. The Starknet team later adopted a smarter solution and built a new contract language, Cairo1, which ensures that “all transaction instructions can produce output results and be on-chain.” At first glance, the fact that all transactions can produce output results means that logical errors never occur. However, most of the time, transactions fail because they encounter bugs that interrupt instruction execution. Ensuring that transactions never interrupt and successfully produce output results is difficult to achieve, but there is actually a simple alternative solution, which is to allow transactions to produce output results when encountering logic errors that lead to interruptions, albeit returning a False value indicating that the execution of the transaction was not smooth. It is important to note that returning a False value also returns an output result, meaning that in Cairo1, regardless of whether an instruction encounters a logic error or is temporarily interrupted, it can produce output results and be on-chain. This output result can be correct or a False error message. For example, consider the following code snippet:

At this point, _balances::read(from) - amount may cause an underflow error, resulting in the corresponding transaction instruction being interrupted and halted without leaving a transaction result on the chain. However, if it is rewritten in the following form, it still returns an output result when the transaction fails, leaving it on the chain. Purely from an aesthetic standpoint, it appears as though all transactions can smoothly leave transaction outputs on the chain, making uniform fee collection seem particularly reasonable.

StarknetAA Contract Overview

Considering that some readers of this article may have a programming background, here is a brief demonstration of the interface of the account abstract contract in Starknet:

The validate_declare interface mentioned above is used for validating declare transactions initiated by users, while validate is used for general transaction validation, primarily verifying the correctness of the user’s signature. On the other hand, execute is used for transaction execution. Notably, Starknet contract accounts inherently support multicall, enabling multiple calls to be made. Multicall functionality can facilitate various interesting features, such as bundling the following three transactions when interacting with certain DeFi protocols:

  1. Authorizing tokens to the DeFi contract in the first transaction.
  2. Triggering the logic of the DeFi contract in the second transaction.
  3. Revoking authorization to the DeFi contract in the third transaction.

Of course, due to the atomicity of multicall, there are more complex use cases, such as executing arbitrage trades.

Summary

Starknet’s main technological features include the Cairo language optimized for ZK proof generation, native-level account abstraction, and the smart contract model separating business logic from state storage.

Cairo is a versatile ZK language that can be used for smart contracts on Starknet as well as for developing more traditional applications. Its compilation process introduces Sierra as an intermediate language, allowing Cairo to iterate frequently without changing the underlying bytecode, only propagating changes to the intermediate language. The Cairo standard library also includes many basic data structures necessary for account abstraction.

Starknet’s smart contracts separate business logic from state data storage, unlike EVM chains. Cairo contract deployment involves three stages: compilation, declaration, and deployment. Business logic is declared in Contract classes, and Contract instances containing state data can be associated with a class and call the code it contains.

Starknet’s smart contract model facilitates code reuse, contract state reuse, storage layering, and garbage contract detection. It also facilitates the implementation of storage leasing and transaction parallelization, although these features have not yet been fully implemented. The architecture of Cairo smart contracts creates necessary conditions for these features.

Starknet has only smart contract accounts, with no EOA accounts, and supports native-level AA account abstraction from the beginning. Its AA solution partially absorbs the ideas of ERC-4337, allowing users to choose highly customized transaction processing solutions. To prevent potential attack scenarios, Starknet has implemented various countermeasures, making important explorations for the AA ecosystem.

Disclaimer:

  1. This article is reprinted from [极客 Web3]. *Forward the Original Title‘解读Starknet智能合约模型与原生AA:特立独行的技术巨匠’.All copyrights belong to the original author [Shew & Faust]. If there are objections to this reprint, please contact the Gate Learn team, and they will handle it promptly.
  2. Liability Disclaimer: The views and opinions expressed in this article are solely those of the author and do not constitute any investment advice.
  3. Translations of the article into other languages are done by the Gate Learn team. Unless mentioned, copying, distributing, or plagiarizing the translated articles is prohibited.

Starknet Smart Contract Model & Native AA

Intermediate3/19/2024, 6:02:11 AM
Starknet supports native-level AA account abstraction, allowing highly customizable transaction processing solutions, and implements multiple countermeasures to ensure security. These features create necessary conditions for Starknet to support functions like storage layering and garbage contract detection, despite some functionalities not yet implemented, providing an important foundation for the AA ecosystem.

Forward the Original Title:解读Starknet智能合约模型与原生AA:特立独行的技术巨匠

Original Authors: Shew & Faust, Web3 Advisors: CryptoNerdCn, Starknet Core Developer, Browser-Side Cairo Development Platform WASM Cairo Founder

Abstract:

The main technological features of Starknet include the Cairo language, which is conducive to generating ZK proofs, native-level AA, and a smart contract model where business logic is independent of state storage. Cairo is a versatile ZK language that can be used to implement smart contracts on Starknet as well as develop applications with traditional leanings. Its compilation process introduces Sierra as an intermediate language, enabling frequent iterations of Cairo without changing the underlying bytecode directly. Moreover, Cairo’s standard library includes many basic data structures required for account abstraction. Starknet smart contracts separate business logic from state data storage, unlike EVM chains. The deployment of Cairo contracts involves three stages: compilation, declaration, and deployment, where business logic is declared in a Contract class. Instances of contracts containing state data can be associated with the class and call the code it contains.

The above-mentioned smart contract model of Starknet is conducive to code reuse, contract state reuse, storage layering, and detection of junk contracts. It is also conducive to the realization of storage leasing and transaction parallelization. Although the latter two have not yet been implemented, the structure of Cairo smart contracts has created “necessary conditions” for them. ·There are only smart contract accounts on the Starknet chain and no EOA accounts. It supports native-level AA account abstraction from the start. Its AA plan incorporates the ideas of ERC-4337 to a certain extent, allowing users to choose highly customized transaction processing solutions. In order to prevent potential attack scenarios, Starknet has taken many countermeasures and made important explorations into the AA ecosystem.

text: Following the issuance of tokens on Starknet, STRK gradually became an indispensable element in the eyes of Ethereum observers. This Ethereum Layer 2 star, known for its “independent” and “disregarding user experience” attitude, quietly carved out its own territory in the flourishing Layer 2 ecosystem compatible with EVM. Due to its excessive neglect of users, and even openly setting up an “electronic beggar” channel on Discord, Starknet was once criticized by the community. Amidst accusations of being “inhuman”, its profound technical expertise seemed instantly devalued, as if only UX and wealth creation were everything. The line from “The Temple of the Golden Pavilion” - “the fact of not being understood by others had been my sole source of pride” - is almost a self-portrait of Starknet. However, setting aside these trivial matters of the world, purely based on the technical taste of code geeks, Starknet and StarkEx, as pioneers of ZK Rollup, are almost treasures in the eyes of Cairo enthusiasts. In the minds of some blockchain game developers, Starknet and Cairo are simply everything in Web3, surpassing Solidity and Move. The biggest gap between “technical geeks” and “users” today is actually largely attributed to people’s lack of understanding of Starknet. Driven by an interest in blockchain technology and the exploration of Starknet’s value, the author of this article starts from Starknet’s smart contract model and native AA to briefly outline its technical solutions and mechanism designs, aiming to showcase Starknet’s technical features to more people, while also hoping to help people understand this “misunderstood lone ranger”. Following a brief introduction to the Cairo language in the subsequent section, we will focus on discussing Starknet’s smart contract model and native account abstraction, explaining how Starknet achieves native AA. After reading this article, readers will also understand why mnemonic phrases from different wallets cannot be mixed in Starknet. But before introducing native account abstraction, let’s first understand the innovative Cairo language created by Starknet. In the development process of Cairo, there were early versions called Cairo0, followed by the modern version. The overall syntax of Cairo’s modern version is similar to Rust and is actually a versatile ZK language. Besides being used to write smart contracts on Starknet, it can also be used for the development of general applications. For example, we can develop a ZK identity verification system using the Cairo language, and this program can run on our own server without depending on the StarkNet network. It can be said that any program requiring verifiable computational properties can be implemented using the Cairo language. And Cairo may currently be the programming language most conducive to generating ZK proofs.

From the perspective of the compilation process, Cairo uses an intermediate language-based compilation method, as shown in the figure below. Sierra in the picture is an intermediate representation (IR) in the Cairo language compilation process, and Sierra will be compiled into a lower-level binary code representation, named CASM, which runs directly on the Starknet node device.

Introducing Sierra as an intermediate representation makes it easier for the Cairo language to add new features. In many cases, it is only necessary to manipulate the Sierra intermediate language without directly changing the underlying CASM code. This saves a lot of trouble, and Starknet’s node client does not need to be updated frequently. In this way, frequent iterations of the Cairo language can be achieved without changing the underlying logic of StarkNet. Cairo’s standard library also includes many basic data structures required for account abstraction. Cairo’s other innovations include a theoretical solution called Cairo Native, which plans to compile Cairo into low-level machine code that can adapt to different hardware devices. Starknet nodes will not have to rely on the CairoVM virtual machine when running smart contracts. This can greatly improve the code execution speed [it is still in the theoretical stage and has not yet been implemented].

Starknet smart contract model: stripping code logic and state storage

Unlike Ethereum-compatible chains, Starknet has made groundbreaking innovations in the design of its smart contract system, largely in preparation for native AA and upcoming features like parallel transaction processing. Here, it’s important to understand that, unlike traditional public chains like Ethereum, smart contract deployment on Starknet follows a different process. Let’s take the example of deploying an Ethereum smart contract:

  1. Developers write the smart contract code locally and compile the Solidity program into EVM bytecode using an editor. This bytecode can then be understood and processed directly by the EVM.
  1. The developer initiates a transaction to deploy the smart contract, deploying the compiled EVM bytecode onto the Ethereum chain.

Source: not-satoshi.com

Although Starknet’s smart contracts also follow the idea of ​​”compile first and then deploy”, Smart contracts are deployed on the chain in the form of CASM bytecode supported by CairoVM. However, there are huge differences between Starknet and EVM-compatible chains in the calling method and state storage mode of smart contracts. Exactly, Ethereum smart contract = business logic + status information. For example, the USDT contract not only implements common functions such as Transfer and Approval, but also stores the asset status of all USDT holders. Code and state are coupled together, which brings a lot of trouble. First of all, it is not conducive to DAPP contract upgrade and state migration, nor conducive to parallel processing of transactions. It is a heavy technical burden.

In response to this, Starknet has improved the way state is stored. In its smart contract implementation solution, the business logic of DApps is completely decoupled from asset states and stored separately. The benefits of this approach are evident: firstly, it allows the system to quickly distinguish whether there are duplicate or redundant code deployments. Here’s how it works: in Ethereum, a smart contract comprises both business logic and state data. If multiple contracts have identical business logic but different state data, their hashes will also differ, making it difficult for the system to determine whether “garbage contracts” exist. However, in Starknet’s solution, the code and state data are separated, making it easier for the system to detect whether the same code has been deployed multiple times based on the hash of the code portion. This helps prevent duplicate code deployment and saves storage space on Starknet nodes.

In Starknet’s smart contract system, the deployment and usage of contracts are divided into three stages: “compile, declare, and deploy.” If an asset issuer wants to deploy a Cairo contract, they first compile the written Cairo code into Sierra and lower-level bytecode CASM forms on their local device. Then, the contract deployer publishes a “declare” transaction, deploying the contract’s CASM bytecode and Sierra intermediate code onto the chain, named as the Contract Class.

(Source: Starknet official website)

Later, if you want to utilize the function capabilities defined in the asset contract, you can initiate a “deploy” transaction through the DApp frontend to deploy a Contract instance associated with the Contract Class. This instance will hold the asset state. Subsequently, users can call the functions within the Contract Class to modify the state of the Contract instance. In fact, anyone familiar with object-oriented programming should easily understand what Class and Instance represent in Starknet. The Contract Class declared by developers only contains the business logic of the smart contract, comprising functions that anyone can call, but it does not have actual asset state, thus not directly implementing “asset entities,” having only the “soul” without the “body.” However, when users deploy specific Contract instances, the assets are “materialized.” If you need to modify the state of the asset “entity,” such as transferring your tokens to someone else, you can directly call the functions written in the Contract Class. The above process is somewhat similar to “instantiation” in traditional object-oriented programming languages (although not entirely identical).

After smart contracts are separated into classes and instances, business logic and status data are decoupled, bringing the following features to Starknet:

  1. Conducive to the realization of storage tiering and “storage leasing system”

The so-called storage layering means that developers can place data in customized locations according to their own needs, such as under the Starknet chain. StarkNet is ready to be compatible with DA layers such as Celestia, and DAPP developers can store data in these third-party DA layers. For example, a game can store its most important asset data on the Starknet mainnet, and store other data in off-chain DA layers such as Celestia.This solution of customizing the DA layer according to security requirements was named “Volition” by Starknet.

The so-called storage rental system means that everyone should continue to pay for the storage space they occupy. As much space on the chain as you occupy, you should theoretically continue to pay rent.

In the Ethereum smart contract model, the ownership of the contract is unclear, and it is difficult to distinguish whether the deployer or the asset holder should pay “rent” for an ERC-20 contract. The storage leasing function has not been launched for a long time, and the deployer is only charged a fee when the contract is deployed. This storage fee model is unreasonable.

Under the smart contract models of Starknet, Sui, CKB, and Solana, the ownership of smart contracts is more clearly divided, making it easier to collect storage funds [Currently, Starknet does not directly launch a storage leasing system, but it will be implemented in the future]

  1. Achieve true code reuse and reduce the deployment of junk contracts

We can declare a general token contract to be stored on the chain as a class, and then everyone can call the functions in this class to deploy their token instances. Moreover, the contract can also directly call the code in the class, which achieves an effect similar to the Library function library in Solidity. At the same time, Starknet’s smart contract model helps identify “junk contracts”. This was explained earlier. After supporting code reuse and junk contract detection, Starknet can significantly reduce the amount of data uploaded to the chain and reduce the storage pressure on nodes as much as possible.

  1. Reuse of real contract “state”

Contract upgrades on the blockchain mainly involve changes to business logic. In the Starknet scenario, the business logic of smart contracts is inherently separated from the asset status. If the contract instance changes the associated contract type class, the business logic upgrade can be completed. There is no need to migrate the asset status to a new place. This form of contract upgrade is more thorough and native than Ethereum’s.

To change the business logic of an Ethereum contract, it is often necessary to “outsource” the business logic to an agency contract, and change the business logic of the main contract by changing the dependent agency contract. However, this method is not concise enough and is not “native”.

Source: wtf Academy

In some scenarios, if the old Ethereum contract is completely abandoned, the asset status inside cannot be directly migrated to the new place, which is very troublesome; the Cairo contract does not need to migrate the status and can directly “reuse” the old status.

  1. Conducive to parallel processing of transactions

To maximize the parallelism of different trading instructions, a necessary step is to store the asset status of different people in separate locations, as can be seen in Bitcoin, CKB and Sui. The prerequisite for the above goal is to separate the business logic of smart contracts from asset status data. Although Starknet has not yet carried out in-depth technical implementation of parallel transactions, it will regard parallel transactions as an important goal in the future.

Starknet’s native AA and account contract deployment

In fact, the concept of account abstraction (AA) and EOA (externally owned accounts) was invented by the Ethereum community as a unique concept. In many new public chains, there is no distinction between EOA accounts and smart contract accounts, avoiding the pitfalls of the Ethereum-style account system from the beginning. For example, under the setting of Ethereum, the EOA account controller must have ETH on the chain before he can initiate a transaction. There is no way to directly choose a variety of authentication methods, and it is extremely troublesome to add some customized payment logic. Some people even think that the account design of Ethereum is simply anti-human.

If we look at flagship products such as Starknet or zkSyncEra “Native AA” chain, obviously differences can be observed: first, Starknet and zkSyncEra have unified account types. There are only smart contract accounts on the chain. There is no such thing as an EOA account from the beginning. (zkSync Era will deploy a set of contract codes by default on the user’s newly created account to simulate the characteristics of the Ethereum EOA account, so that it is compatible with Metamask).

However, Starknet does not consider directly compatibility with Ethereum peripherals such as Metamask. When users use the Starknet wallet for the first time, a dedicated contract account is automatically deployed. In other words, the previously mentioned contract instance is deployed, and this instance is associated with the contract class deployed in advance by the wallet project. Users can directly call some of the functionalities written in the class. Now, let’s delve into an interesting topic: when claiming STRK airdrops, many people found that the Argent and Braavos wallets were not compatible with each other. Importing the mnemonic from Argent to Braavos did not allow exporting the corresponding account, mainly due to the different account generation algorithms used by Argent and Braavos, resulting in different account addresses generated from the same mnemonic. Specifically, in Starknet, the newly deployed contract address can be derived through a deterministic algorithm, as follows:

The ‘pedersen()’ function mentioned above is a hash algorithm that is easy to use in ZK systems. The process of generating the account involves providing several special parameters to the pedersen function to generate the corresponding hash, which is the generated account address. The image above shows the parameters used by Starknet to generate the “new contract address”. The ‘deployer_address’ represents the address of the “contract deployer”. This parameter can be empty, meaning that even if you do not have a Starknet contract account in advance, you can still deploy a new contract. The ‘salt’ is the salt value used to calculate the contract address, which is essentially a random number introduced to avoid duplicate contract addresses. The ‘class_hash’ corresponds to the hash value of the class mentioned earlier, which the contract instance is associated with. The ‘constructor_calldata_hash’ represents the hash of the contract’s initialization parameters.

Based on the above formula, users can calculate the generated contract address before deploying the contract to the chain. Starknet allows users to deploy contracts directly without having a Starknet account in advance, as follows:

  1. Users first determine the contract instance they want to deploy and which contract class to associate it with, using the hash of the class as one of the initialization parameters, and calculate the salt to determine the generated contract address.
  2. After knowing where they will deploy the contract, users first transfer a certain amount of ETH to that address as the contract deployment fee. Generally, this ETH needs to be transferred from L1 to the Starknet network via a cross-chain bridge.
  3. Users initiate the transaction request for contract deployment.

In fact, all Starknet accounts are deployed through the above process, but most wallets shield the details, and users do not perceive the process as their contract account being deployed as soon as they transfer ETH.

The above solution has brought about some compatibility issues, because when different wallets generate account addresses, the results generated are inconsistent. Only wallets that meet the following conditions can be mixed:

  1. The private key derived public key used by the wallet is the same as the signature algorithm;
  2. The wallet’s salt calculation process is the same;
  3. The wallet’s smart contract classes are not fundamentally different in implementation details; \

In the case mentioned earlier, both Argent and Braavos used the ECDSA signature algorithm, but the calculation methods for the salt were different between the two, resulting in inconsistent account addresses generated from the same mnemonic.

Now, let’s revisit the topic of account abstraction. Starknet and zkSync Era have moved a series of processes involved in transaction processing, such as identity verification (verifying digital signatures) and gas fee payment, outside of the “chain layer.” Users can customize the implementation details of the above logic in their own accounts. For example, you can deploy a dedicated digital signature verification function in your Starknet smart contract account. When a Starknet node receives a transaction initiated by you, it will call a series of transaction processing logic customized by you on the chain.

This approach clearly offers more flexibility. In Ethereum’s design, however, logic such as identity verification (digital signatures) is hardcoded into the node client code and cannot natively support customizable account features.

Schematic diagram of the native AA solution specified by the Starknet architect. Transaction verification and gas fee qualification verification are transferred to the on-chain contract for processing. The underlying virtual machine of the chain can call these functions customized or specified by the user.

According to zkSyncEra and Starknet officials, this modular approach to account functionality is inspired by EIP-4337. However, what sets them apart is that zkSync and Starknet merged account types from the outset, unified transaction types, and utilized a single entry point to receive and process all transactions. In contrast, Ethereum, due to historical baggage and the foundation’s desire to avoid aggressive iteration strategies such as hard forks as much as possible, supported the EIP-4337, using a different way to solve the problem. However, the result is that EOA accounts and EIP-4337 solutions each have independent transaction processing workflows, which appear awkward and cumbersome, unlike the agility of native AAs.

Source: ArgentWallet

However, the native account abstraction in Starknet has not yet reached full maturity. From a practical standpoint, while Starknet’s AA accounts have implemented custom signature verification algorithms, they currently only support paying gas fees in ETH and STRK, and do not yet support third-party gas payment. Therefore, the progress of Starknet in native AAs can be described as “the theoretical framework is mostly mature, while the practical implementation is still in progress”. Since Starknet only has smart contract accounts internally, the entire process of its transactions takes into account the influence of account smart contracts. First, after a transaction is received by the Starknet node’s memory pool (Mempool), it undergoes verification, which includes:

  1. Checking if the transaction’s digital signature is correct, at which point the signer’s account’s custom verification function is called;
  2. Verifying if the initiator’s account balance can cover the gas fee. \

It should be noted here that using the customized signature verification function in the account smart contract means that there is an attack scenario. Because the memory pool does not charge gas fees when verifying the signature of new transactions. (If gas fees are charged directly, more serious attack scenarios will occur). Malicious users can first customize a super complex signature verification function in their account contract, and then initiate a large number of transactions. When these transactions are verified, they will call the customized complex signature verification function, which can directly exhaust the node’s computing resources. In order to avoid this situation, StarkNet imposes the following restrictions on transactions:

  1. There is an upper limit on the number of transactions that a single user can initiate within a unit time;
  2. The custom signature verification function in the Starknet account contract has complexity limitations, and overly complex signature verification functions will not be executed. Starknet limits the gas consumption limit of the signature verification function. If the amount of gas consumed by the signature verification function is too high, the transaction will be directly rejected. At the same time, the signature verification function in the account contract is not allowed to call other contracts.

The flow chart of Starknet transactions is as follows:

It is worth noting that, to further expedite the transaction verification process, the Starknet node client has directly implemented the signature verification algorithms of Braavos and Argent wallets. When a node detects transactions generated from these two major mainstream Starknet wallets, it will call the built-in Braavos/Argent signature algorithms in the client. Through this caching-like approach, Starknet can shorten the transaction verification time. After the transaction data is validated by the sequencer (the sequencer’s verification steps are much more thorough than those of the memory pool), the sequencer will package and submit the transactions from the memory pool to the ZK proof generator. Transactions entering this stage will be charged gas fees even if they fail. However, if readers are familiar with Starknet’s history, they will notice that earlier versions of Starknet did not charge fees for failed transactions. The most common scenario for transaction failure is when a user has only 1 ETH but attempts to transfer 10 ETH externally, which clearly indicates a logic error and will inevitably fail, but no one knows the outcome before execution. However, in the past, StarkNet did not charge fees for such failed transactions. These cost-free erroneous transactions waste Starknet node computational resources and can lead to DDoS attack scenarios. On the surface, charging fees for erroneous transactions seems straightforward, but in reality, it is quite complex. Starknet introduced a new version of the Cairo1 language largely to address the issue of gas charges for failed transactions. As we all know, a ZK proof is a proof of validity, and the result of a failed transaction is invalid and cannot leave an output result on the chain. Attempting to use a validity proof to prove that a certain instruction execution is invalid and cannot produce output results sounds strange and is actually unworkable. Therefore, in the past, Starknet excluded failed transactions that could not produce output results when generating proofs. The Starknet team later adopted a smarter solution and built a new contract language, Cairo1, which ensures that “all transaction instructions can produce output results and be on-chain.” At first glance, the fact that all transactions can produce output results means that logical errors never occur. However, most of the time, transactions fail because they encounter bugs that interrupt instruction execution. Ensuring that transactions never interrupt and successfully produce output results is difficult to achieve, but there is actually a simple alternative solution, which is to allow transactions to produce output results when encountering logic errors that lead to interruptions, albeit returning a False value indicating that the execution of the transaction was not smooth. It is important to note that returning a False value also returns an output result, meaning that in Cairo1, regardless of whether an instruction encounters a logic error or is temporarily interrupted, it can produce output results and be on-chain. This output result can be correct or a False error message. For example, consider the following code snippet:

At this point, _balances::read(from) - amount may cause an underflow error, resulting in the corresponding transaction instruction being interrupted and halted without leaving a transaction result on the chain. However, if it is rewritten in the following form, it still returns an output result when the transaction fails, leaving it on the chain. Purely from an aesthetic standpoint, it appears as though all transactions can smoothly leave transaction outputs on the chain, making uniform fee collection seem particularly reasonable.

StarknetAA Contract Overview

Considering that some readers of this article may have a programming background, here is a brief demonstration of the interface of the account abstract contract in Starknet:

The validate_declare interface mentioned above is used for validating declare transactions initiated by users, while validate is used for general transaction validation, primarily verifying the correctness of the user’s signature. On the other hand, execute is used for transaction execution. Notably, Starknet contract accounts inherently support multicall, enabling multiple calls to be made. Multicall functionality can facilitate various interesting features, such as bundling the following three transactions when interacting with certain DeFi protocols:

  1. Authorizing tokens to the DeFi contract in the first transaction.
  2. Triggering the logic of the DeFi contract in the second transaction.
  3. Revoking authorization to the DeFi contract in the third transaction.

Of course, due to the atomicity of multicall, there are more complex use cases, such as executing arbitrage trades.

Summary

Starknet’s main technological features include the Cairo language optimized for ZK proof generation, native-level account abstraction, and the smart contract model separating business logic from state storage.

Cairo is a versatile ZK language that can be used for smart contracts on Starknet as well as for developing more traditional applications. Its compilation process introduces Sierra as an intermediate language, allowing Cairo to iterate frequently without changing the underlying bytecode, only propagating changes to the intermediate language. The Cairo standard library also includes many basic data structures necessary for account abstraction.

Starknet’s smart contracts separate business logic from state data storage, unlike EVM chains. Cairo contract deployment involves three stages: compilation, declaration, and deployment. Business logic is declared in Contract classes, and Contract instances containing state data can be associated with a class and call the code it contains.

Starknet’s smart contract model facilitates code reuse, contract state reuse, storage layering, and garbage contract detection. It also facilitates the implementation of storage leasing and transaction parallelization, although these features have not yet been fully implemented. The architecture of Cairo smart contracts creates necessary conditions for these features.

Starknet has only smart contract accounts, with no EOA accounts, and supports native-level AA account abstraction from the beginning. Its AA solution partially absorbs the ideas of ERC-4337, allowing users to choose highly customized transaction processing solutions. To prevent potential attack scenarios, Starknet has implemented various countermeasures, making important explorations for the AA ecosystem.

Disclaimer:

  1. This article is reprinted from [极客 Web3]. *Forward the Original Title‘解读Starknet智能合约模型与原生AA:特立独行的技术巨匠’.All copyrights belong to the original author [Shew & Faust]. If there are objections to this reprint, please contact the Gate Learn team, and they will handle it promptly.
  2. Liability Disclaimer: The views and opinions expressed in this article are solely those of the author and do not constitute any investment advice.
  3. Translations of the article into other languages are done by the Gate Learn team. Unless mentioned, copying, distributing, or plagiarizing the translated articles is prohibited.
Start Now
Sign up and get a
$100
Voucher!