The Key Differences Between Cairo and EVM Execution From Marc Egli ChainSecurity
Ethereum Denver·Thu, Oct 9, 2025, 12:00 AM
This talk explores the key differences between Cairo/StarkNet and Ethereum's Execution Virtual Machine (EVM). Cairo, designed for StarkNet, brings a novel approach with its STARK-based, verifiable computation that significantly diverges from Ethereum's traditional EVM model. We will delve into the subtleties and less obvious nuances that define their differences, highlighting the security caveats the developers may easily overlook in practice.
Transcript
[Music] uh hello everyone so I'm Mark and I'm going to talk to you about key differences between Cairo and evm execution uh this talk is mainly focused for developers that already develop on solidity and are interested in uh exploring uh building on Stark net using Caro so I work at the chain security U I'm doing smart contract audit actually we are working with many big players in the space and we uh sometimes have to audit also like Ciro smart contracts that's that so that's where actually most our knowledge uh will be from today uh okay about me um as I said I'm doing the audits I audited like Oiler vome poly Market worked on many more the project I initially come for from a more like traditional background uh doing ctfs and I previously worked on baseband uh so yeah so first of all um here are some like nice resources that I would recommend to everyone uh to explore to have a look because um those are your main go-tos if you want to start building actually on Cairo so there's a Kyo Cairo language book The Stark net book of course to understand what chain you're building on how like all the properties of that chain and then of of course the Stark net Foundry book which is the environment you can use to to actually write uh smart contracts uh yeah so let's get started what's the main differences between solidity and G and Cyro on the high level so uh solidity is this object oriented statically typed C++ style language so it's very close to a traditional programming language but really focused towards smart contracts um on the other side Cairo is can be also used for uh general computing but main benefit is that it's designed for verifiable computing which means from a program you can generate a proof very easily a St proof actually uh Cairo is a rust style language so it will also uh inherit from from a lot of the properties that rust has um for the memory model so solidity I guess you must be familiar with it uh each slot in memory is a byes uh 32 the memory is mutable completely uh there free access right you can do what you want uh you can write a contract and uh have some mule assembly changing the free memory pointer you can do whatever right like no one will tell you you cannot overwrite this part of memory uh for Cairo it's a bit different so each slot is a felt 252 which is 252 bytes large and the felt is actually um the basic data type in Kyu which stands for a field element uh which which which is actually the underlying type used to highly optimize cairo's ZK proof system and uh something interesting is that the memory is completely immutable for Cairo which means you cannot overwrite a memory slot once you have written to it uh however on the language level uh mutability is implemented through shadowing so you can use the mute key word and the compiler will handle it for you and let you reuse the same same the same variable but under the hood it will allocate a new memor memory slot there's also something called snapshots which is an immutable view of the memory at a certain certain point in time time and uh Cyro memory also has the ownership concept uh as rust uh having immutable memory um leads to less flexibility but also less chance to actually mess up memory and for example uh arrays in Cyro are actually just cues because you can only remove uh ele Ms from the front and append new elements to to the tail as this only involves pointer updates and not I mean memory updates as you cannot uh override a slot uh for the storage layout um in solidity so as we know uh the order in which we declare our storage variables will influence which slots those variables are assigned to so from zero incrementing by one um we know that for D arrays the array will start at the katak 256 of the slot for map uh each value will be at the catar 256 of the padded key appended to the slot of the mapping um there's no size limitation of single objects and there is by default uh storage variable packing uh for people who don't know what the storage variable packing is is uh if a type is smaller than a by 30 to it can be possible that multiple such uh storage values are actually written in the same slot um and shattering storage variable does not compile actually so if you have a contract b and a contract a that extends B if they declare the same storage variable using the the same name it won't compile on the other side uh Cairo has um in storage are Just Two Types so non- mappings and mappings uh non- mappings actually are are stored at the SN catak of the variable name so that's something very important to keep in mind here because the name of the variable influences where your variable will be stored in storage uh and the SN cat shock is the lower 250 bits of ketar 256 and for mappings it's very similar to the solidity case just that we also use this variable name instead of the slot um there is no default storage packing in Caro however it's possible for structs uh that implement the store packing trait and there is actually a warning if you uh have shadowing storage variables so if you have two components that have the the same storage variable name it will give give you a warning but it will still compile so as we can see here on the Cairo side if we have the component a and the contract B embeds A they both both have the same storage value which will actually point to point to the same storage slot so that's something to keep in mind when uh using libraries for example that you might change values that you don't want to change due to the variable name being uh the same um yeah now let's discuss a small uh difference between solidity and Caro in terms of operator precedence um in solidity the equality operators have less precedence have less priority than the inequality ones however in Cairo uh they have the same so this is not a big issue because usually um because in Cairo the type Checker will catch uh some bugs due to the fact that booleans are not like integers by default but if you start to do operator overloading this might be something that you want to keep in mind due to the uh operator precedence difference in this case um yeah so let's have a quick look on like transaction cost in terms of I mean it's written solidity Cairo here but it's mostly like ethereum and Stark net so sorry about that um you know on solidity ethereum you pay actually for the resources you use cold data size op codes memory sech accesses blobs uh on Kyo you have multiple components right so you have the da call data cost which is the fee to actually push the the state diffs to L1 um it is a lower cost if you use Blobs of course but if you use cold data it will be more expensive then there is the message called dat data cost if you want to send a message from L2 to L1 so L2 being starnet in this case uh there's also the storage right cost which is the fee for writing on to the ethereum storage and since uh since darket 0.3.1 there's also this L2 the data cost which is a per bite cost for uh cold data events en code and there is computation cost cost of course um which is non noner Mystic because it depends on the amount of builtins used in the same block I will not go too deep into this because it it getting it gets quite intricate but I recommend you to uh look up the gas estima uh docks um so now something more interesting that you might have heard since a few years you know like re-entrancy the big uh issues in smart contract usually usually not anymore I mean not too much anymore but still always uh relevant um in solidity uh view functions actually are usually called by a static call so you cannot actually do any storage changes right you cannot write storage and if you try it won't compile however there's equivalent in Cyro for view functions where you pass the self the contract State and it will make sure that you don't try to modify the contract State using self however you can still do lowlevel contract system call that allows you to actually change the contract state so view functions don't guarantee uh no direct re-entrancy due to the fact that uh those low level calls can be performed hence developers should not have the assumptions that calling a view function on an other contract cannot modify state so that's an assumption you have to keep in mind when when also integrating with uh smart contracts on Stark net um now a small note about like Bridges so the star net token Bridge from L1 to L2 the interface on L1 expects u56 array of payload however the array must be a must be actually an array of felt two 25502 represented by U into 256 due to the fact that the basic type is different for uh for starnet which is felt 252 only having two 252 bits which means if you actually um exceed the felt 252 max value the message will get stuck in the bridge and you have to cancel it and I mean it will lead lead to some trouble so you have to keep in mind that the types are not 100% compatible and you should always make sure that you use the correct series serialization scheme uh defined in the Cairo documentation um yeah proxy and clones on Stark net are actually uh natively supported um so for example when you uh deploy a contract you would uh have a two steps first you would declare the contract which is registering its class hash on starnet the class hash is computed from the compiled contract bite code um but when you declare it it does not deploy a contract you have to do to actually do a second step which is a deploy transaction that actually links the deployed contract which links the contract address to actually one one of the class hashes and this means that if you want to upgrade a contract you can simply use the replace class CIS which would replace the class hash of that specific contract you have to of course Implement a function in that contract to call it uh make sure of course that the access control is uh is Set uh and when you upgrade make sure that the variable names much right because as we saw earlier the variable names actually influence where they are stored in in storage and of course when you upgrade you should always check the compatibility with other contracts you you are integrating with um yeah uh account abstraction is actually also natively supported uh on Stark net uh through the starnet uh improval proposal six so you can implement this uh s i Sr C6 interface and uh what will happen is when a a transaction will be executed the sequencer will will will actually first call into validate and to verify if the cont if the transaction is valid and then it will call once again validate right before this uh execution and uh there are some caveats here of course um you should make sure that validate can only be called by address zero which is the address of the sequencer and uh the time stamps and the block numbers are actually rounded so the time stamp is rounded to the hour and the block number to the um lowest multiple of 100 and this is because the validate step step should not be too precise as we we don't want the first validation to pass and the second to fail which would which which uh means we are actually using resources for nothing as the exe execution will fail um yeah um for uh testing just a quick side note uh so if you plan to develop on Cairo you can use SN Foundry which provides a very good uh testing environment I mean I'm sure you all know foundary that is used to develop solidity contracts so there's an equalent here for Cairo um it supports cheat code um fuzzing parallel test execution so that's what I recommend to use also uh so here we have some conclusions about what we just discussed right so there's a different memory and storage model between solidity and Cairo there is slightly different operator preds that could lead lead in the theory to some issues um the most important part here is also that it's possible to have re-entrance on view functions in cyu um and the proxies and clones are supported natively which is also very nice as a developer um very good tasting Frameworks and of course CYO is great also for defi composability So yeah thank you very much this was my first talk I hope it wasn't too bad and hi Mom
Automatic transcript — names and jargon may be misspelled.