SNIP XXX: get_class_hash_at syscall

Taking here the conversation about a new syscall for getting the class hash of a deployed contract, from within a contract execution environment.

Simple Summary

Introduce a new syscall get_class_hash_at, aimed to get a contract class hash at a certain address.

Abstract

Starknet adopted a system of contract classes to reduce duplication of deployed bytecode. It works in the following way: to deploy a piece of code that has never been deployed before, you must first declare it. You are effectively “declaring” a class to the Starknet network. From this point onward, one may instantiate this class by requesting the sequencer to deploy it at a certain address. The simple usecase goes: you declare a fungible token contract, the sequencer stores the code once; then, any number of deployments of the exact same smart contract will not further bloat the chain’s storage. This is different from the way Ethereum and the Ethereum Virtual Machine (EVM) works. In EVM world, if you deploy a hundred times an ERC20 contract, the chain will store a copy of the code a hundred times. More information: https://docs.starknet.io/architecture-and-concepts/smart-contracts/contract-classes/

While there is a way for one to check the class hash of a deployed contract at the RPC level (starknet_getClassHashAt method), there is no way to perform this at the smart contract level. In EVM world, this is achieved using the EXTCODEHASH opcode. The purpose is for a contract to check on-chain whether another contract is an instantiation of a particular class. This is more precise/powerful (and more costly?) than SNIP-5 (inspired by ERC-165).

Motivation

At Kakarot, we utilize replace_class_hash syscall for upgrades at the contract level, as well as use class hashes as mediums of checking a contract’s version. We need the ability to check a contract’s class hash. We currently achieve this by enforcing every Kakarot Account to store its own class hash in a storage variable.

We would benefit from a syscall that would enable a contract to check a particular class hash at an address.

Simple use-case for Kakarot: enable the contract-level orchestration of versioning and auto-upgrade of our swarm of Kakarot Account Contracts

How?

  1. Set the new version (a class hash) in the Core EVM Kakarot Contract
  2. Every contract is now able to compare their class hash with the current correct version (situated in Kakarot Core EVM) and decide to self upgrade
  3. Before calling a contract, one may check that it is in the correct version.

Specification

One might want to name the syscall in the same way as the corresponding RPC method.

extern fn get_class_hash_at_syscall(
    contract_address: ContractAddress
) -> SyscallResult<ClassHash> implicits(GasBuiltin, System) nopanic;

Alternative API:

extern fn class_hash_syscall(
    contract_address: ContractAddress
) -> SyscallResult<ClassHash> implicits(GasBuiltin, System) nopanic;

Arguments

contract_address: The contract address one wants to know the class hash of.

Returns

Returns the ClassHash if the contract is deployed, an Result::Error if the contract is not deployed. Note that the syscall should never panic. Calling get_class_hash_at_syscall on an address where no contract is deployed will result in a catchable error (equivalent to returning a sentinel value null), not a CairoVM error.

Implementation

We will require help from the Starkware team to define precisely the implementation.

Copyright

Copyright and related rights waived via MIT.

Just signaling my support for this proposal. Having the syscall would be beneficial :pray:

This could be truly beneficial, really precise and well crafted Proposal

Edit: renaming the SNIP to XXX since SNIP-18 was taken by staking.