<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.3 20210610//EN" "JATS-journalpublishing1-3-mathml3.dtd">
<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ali="http://www.niso.org/schemas/ali/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" article-type="research-article" dtd-version="1.3" xml:lang="EN">
<front>
<journal-meta>
<journal-id journal-id-type="publisher-id">Front. Comput. Sci.</journal-id>
<journal-title-group>
<journal-title>Frontiers in Computer Science</journal-title>
<abbrev-journal-title abbrev-type="pubmed">Front. Comput. Sci.</abbrev-journal-title>
</journal-title-group>
<issn pub-type="epub">2624-9898</issn>
<publisher>
<publisher-name>Frontiers Media S.A.</publisher-name>
</publisher>
</journal-meta>
<article-meta>
<article-id pub-id-type="doi">10.3389/fcomp.2025.1596804</article-id>
<article-version article-version-type="Version of Record" vocab="NISO-RP-8-2008"/>
<article-categories>
<subj-group subj-group-type="heading">
<subject>Original Research</subject>
</subj-group>
</article-categories>
<title-group>
<article-title>An application layer with protocol-based java smart contract verification</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name><surname>Olivieri</surname> <given-names>Luca</given-names></name>
<xref ref-type="aff" rid="aff1"><sup>1</sup></xref>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Data curation" vocab-term-identifier="https://credit.niso.org/contributor-roles/data-curation/">Data curation</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="validation" vocab-term-identifier="https://credit.niso.org/contributor-roles/validation/">Validation</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Writing &#x2013; original draft" vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-original-draft/">Writing &#x2013; original draft</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Writing &#x2013; review &amp; editing" vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-review-editing/">Writing &#x2013; review &#x0026; editing</role>
<uri xlink:href="https://loop.frontiersin.org/people/3011057"/>
</contrib>
<contrib contrib-type="author" corresp="yes">
<name><surname>Spoto</surname> <given-names>Fausto</given-names></name>
<xref ref-type="aff" rid="aff2"><sup>2</sup></xref>
<xref ref-type="corresp" rid="c001"><sup>&#x0002A;</sup></xref>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="conceptualization" vocab-term-identifier="https://credit.niso.org/contributor-roles/conceptualization/">Conceptualization</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Data curation" vocab-term-identifier="https://credit.niso.org/contributor-roles/data-curation/">Data curation</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="software" vocab-term-identifier="https://credit.niso.org/contributor-roles/software/">Software</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="supervision" vocab-term-identifier="https://credit.niso.org/contributor-roles/supervision/">Supervision</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Writing &#x2013; original draft" vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-original-draft/">Writing &#x2013; original draft</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Writing &#x2013; review &amp; editing" vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-review-editing/">Writing &#x2013; review &#x0026; editing</role>
<uri xlink:href="https://loop.frontiersin.org/people/2940346"/>
</contrib>
<contrib contrib-type="author">
<name><surname>Tagliaferro</surname> <given-names>Fabio</given-names></name>
<xref ref-type="aff" rid="aff3"><sup>3</sup></xref>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Data curation" vocab-term-identifier="https://credit.niso.org/contributor-roles/data-curation/">Data curation</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="validation" vocab-term-identifier="https://credit.niso.org/contributor-roles/validation/">Validation</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Writing &#x2013; original draft" vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-original-draft/">Writing &#x2013; original draft</role>
<role vocab="credit" vocab-identifier="https://credit.niso.org/" vocab-term="Writing &#x2013; review &amp; editing" vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-review-editing/">Writing &#x2013; review &#x0026; editing</role>
</contrib>
</contrib-group>
<aff id="aff1"><label>1</label><institution>Department of Environmental Sciences, Informatics and Statistics (DAIS), Ca&#x00027; Foscari University of Venice</institution>, <city>Venice</city>, <country country="it">Italy</country></aff>
<aff id="aff2"><label>2</label><institution>Department of Computer Science, University of Verona</institution>, <city>Verona</city>, <country country="it">Italy</country></aff>
<aff id="aff3"><label>3</label><institution>Equixly Srl</institution>, <city>Florence</city>, <country country="it">Italy</country></aff>
<author-notes>
<corresp id="c001"><label>&#x0002A;</label>Correspondence: Fausto Spoto, <email xlink:href="mailto:fausto.spoto@univr.it">fausto.spoto@univr.it</email></corresp>
</author-notes>
<pub-date publication-format="electronic" date-type="pub" iso-8601-date="2025-09-04">
<day>04</day>
<month>09</month>
<year>2025</year>
</pub-date>
<pub-date publication-format="electronic" date-type="collection">
<year>2025</year>
</pub-date>
<volume>7</volume>
<elocation-id>1596804</elocation-id>
<history>
<date date-type="received">
<day>20</day>
<month>03</month>
<year>2025</year>
</date>
<date date-type="accepted">
<day>18</day>
<month>08</month>
<year>2025</year>
</date>
</history>
<permissions>
<copyright-statement>Copyright &#x000A9; 2025 Olivieri, Spoto and Tagliaferro.</copyright-statement>
<copyright-year>2025</copyright-year>
<copyright-holder>Olivieri, Spoto and Tagliaferro</copyright-holder>
<license>
<ali:license_ref start_date="2025-09-04">https://creativecommons.org/licenses/by/4.0/</ali:license_ref>
<license-p>This is an open-access article distributed under the terms of the <ext-link ext-link-type="uri" xlink:href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution License (CC BY)</ext-link>. The use, distribution or reproduction in other forums is permitted, provided the original author(s) and the copyright owner(s) are credited and that the original publication in this journal is cited, in accordance with accepted academic practice. No use, distribution or reproduction is permitted which does not comply with these terms.</license-p>
</license>
</permissions>
<abstract>
<p>Smart contracts are software that runs in blockchain and expresses the rules of an agreement between parties. An incorrect smart contract might allow blockchain users to violate its rules and even jeopardize its expected security. Smart contracts cannot be easily replaced to patch a bug since the nature of contracts requires them to be immutable. More problems occur when a smart contract is written in a general-purpose language, such as Java, whose executions, in a blockchain, could hang the network, break consensus or violate data encapsulation. To limit these problems, there exist automatic static analyzers that find bugs before smart contracts are installed in the blockchain. This so-called <italic>off-chain</italic> verification is <italic>optional</italic> because programmers are not forced to use it. This paper presents a general framework for the verification of smart contracts, instead, that is part of the protocol of the nodes and applies when the code of the smart contracts gets installed. It is a <italic>mandatory</italic> entry filter that bans code that does not abide by the verification rules. Consequently, such rules become part of the consensus rules of the blockchain. Therefore, an improvement in the verification protocol entails a consensus update of the network. This paper describes an implementation of a smart contracts application layer with protocol-based verification for smart contracts written in the Takamaka subset of Java, that filters only those smart contracts whose execution in blockchain is not dangerous. This application layer runs on top of a consensus engine such as Tendermint and its derivatives Ignite and CometBFT (proof of stake), or Mokamint (proof of space). This paper provides examples of actual implementations of verification rules that check if the smart contracts satisfy some constraints required by the Takamaka language. This paper shows that protocol-based verification works and reports how consensus updates are implemented. It shows actual experiments as well as limits to its use, mainly related to the fact that protocol-based verification must be fast and its complexity must never explode, or otherwise, it would compromise the performance of the blockchain network.</p></abstract>
<kwd-group>
<kwd>smart contract</kwd>
<kwd>software verification</kwd>
<kwd>program analysis</kwd>
<kwd>blockchain</kwd>
<kwd>distributed ledger technology</kwd>
<kwd>Tendermint</kwd>
<kwd>Ignite</kwd>
<kwd>Mokamint</kwd>
</kwd-group>
<funding-group>
<award-group id="gs1">
<funding-source id="sp1">
<institution-wrap>
<institution>NextGenerationEU</institution>
<institution-id institution-id-type="doi" vocab="open-funder-registry" vocab-identifier="10.13039/open_funder_registry">10.13039/100031478</institution-id>
</institution-wrap>
</funding-source>
</award-group>
<funding-statement>The author(s) declare that financial support was received for the research and/or publication of this article. This work partially supported by SERICS (PE00000014 -CUP H73C2200089001) and iNEST (ECS00000043 -CUP H43C22000540006) projects funded by PNRR NextGeneration EU.</funding-statement>
</funding-group>
<counts>
<fig-count count="14"/>
<table-count count="0"/>
<equation-count count="0"/>
<ref-count count="35"/>
<page-count count="0"/>
<word-count count="13309"/>
</counts>
<custom-meta-group>
<custom-meta>
<meta-name>section-at-acceptance</meta-name>
<meta-value>Software</meta-value>
</custom-meta>
</custom-meta-group>
</article-meta>
</front>
<body>
<sec sec-type="intro" id="s1">
<label>1</label>
<title>Introduction</title>
<p>Blockchain is a distributed ledger that replicates data in a peer-to-peer network of nodes. Transactions are ledger updates digitally signed by the account requiring their execution. The nodes of the network collect broadcasted transactions into a growing cryptographically-linked chain of blocks. A set of consensus rules specifies constraints on the way the blockchain grows, which normally amounts to expected security guarantees for the state of the blockchain: money cannot be spent twice, and, in general, the evolution of the state must be consistent with the semantics of the transactions. Once consensus is achieved, it is hard, or impossible, to withdraw transactions from the blockchain. In this sense, blockchains are <italic>immutable</italic> data structures.</p>
<p><italic>Smart contracts</italic> specify rules and effects of transactions and can be either built-in, as a fixed module of the blockchain software, or given as code dynamically deployed inside the same blockchain. In the second case, users who deploy the code identify themselves by signing a code install transaction request. The typical applications of smart contracts are related to finance and cryptocurrencies, tokens, coordination of purchases, electronic elections, and law. The critical nature of such applications and the fact that smart contracts cannot be replaced after being installed require a high level of code quality. That is, smart contracts are expected to be flawless, as much as possible, and to not harm the network.</p>
<p>Smart contracts can be written in a variety of programming languages, either specific for them or general-purpose. Most such languages are Turing-complete, with the notable exception of Bitcoin&#x00027;s. Not surprisingly, Turing-completeness for smart contracts introduces the risk of many kinds of bugs (<xref ref-type="bibr" rid="B6">Atzei et al., 2017</xref>; <xref ref-type="bibr" rid="B27">Popper, 2016</xref>). An extensive review for the specific case of Ethereum is in <xref ref-type="bibr" rid="B3">Antonopoulos and Wood (2018)</xref> and includes the reentrancy issue, arithmetic under/overflows, incorrect use of low-level calls, weak encapsulation, ineffective randomization, logical bugs in the code of contracts, fund locking, wrong identification of the transaction originator. Such vulnerabilities have actually been exploited in practice. Because of this, there exist many analyzers that verify smart contracts before they get installed in the blockchain (<xref ref-type="bibr" rid="B17">Hejazi and Lashkari, 2025</xref>; <xref ref-type="bibr" rid="B18">Kushwaha et al., 2022</xref>; <xref ref-type="bibr" rid="B29">Ressi et al., 2024</xref>). Furthermore, there are companies that provide code audit services, using both automatic tools and human investigation (<xref ref-type="bibr" rid="B9">Certik, 2025</xref>; <xref ref-type="bibr" rid="B25">OpenZeppelin, 2025</xref>; <xref ref-type="bibr" rid="B11">Consensys Diligence, 2025</xref>). A limit of these tools and procedures is that they are <italic>optional</italic> and <italic>external</italic> to the blockchain (hence <italic>off-chain</italic>): the latter does not actively protect itself against the deployment of incorrect or dangerous code. Moreover, they mostly apply to Solidity rather than to general-purpose languages used for writing smart contracts.</p>
<p>This paper makes the following contributions:</p>
<list list-type="bullet">
<list-item><p>It defines <italic>protocol-based</italic> code verification, where the nodes of the blockchain verify the code being deployed. That is, the same network, <italic>internally</italic>, runs a <italic>mandatory</italic> code verification step and rejects code that does not pass it. As a consequence, protocol-based verification is a defensive, proactive technique that guarantees that all code executed in the blockchain has been successfully verified.</p></list-item>
<list-item><p>It describes an actual implementation of a blockchain with protocol-based verification for filtering smart contracts written in the Takamaka subset of Java (<xref ref-type="bibr" rid="B32">Spoto, 2019</xref>). This implementation is a software layer called Hotmoka, which runs as an application on top of Tendermint (<xref ref-type="bibr" rid="B19">Kwon, 2014</xref>) (also its derivatives such as Ignite<xref ref-type="fn" rid="fn0001"><sup>1</sup></xref> and CometBFT<xref ref-type="fn" rid="fn0002"><sup>2</sup></xref>), a third-party tool for implementing blockchains based on Byzantine fault tolerance and proof of stake. Hotmoka is a runtime for smart contracts written in the Takamaka subset of Java that users can install dynamically, as in Solidity over Ethereum. Hotmoka also runs on top of Mokamint,<xref ref-type="fn" rid="fn0003"><sup>3</sup></xref> a similar tool based on a proof of space consensus. Hotmoka includes 21 verification checks that mostly verify the correct use of Takamaka&#x00027;s primitives and code annotations and the use of a deterministic subset of Java. That is, such checks <italic>filter</italic> the smart contracts installed in blockchain to avoid those that would crash the blockchain peers, hang their execution, make consensus impossible or violate data encapsulation. Therefore, they are relevant security checks, although we acknowledge that they are relatively simple. As shown later (Section 7) the goal is to have quick checks that do not delay the creation of the blocks, since the blockchain peers must perform such checks during the same creation of the new blocks. In general, our technique is best suited for the safe use of general-purpose languages (such as Java, in our case) for writing smart contracts for a permissionless blockchain, instead of using a new specific language such as Solidity.</p></list-item>
<list-item><p>It describes the coordination of an update to the verification protocol of a blockchain and a lazy re-verification approach that copes with the evolution of the code verification rules. Namely, protocol-based verification is run as part of code installation transactions. Hence, its rules are part of the network consensus rules, and their evolution requires a network update. Moreover, code previously successfully verified with old verification rules might fail to pass the new verification rules.</p></list-item>
</list>
<p>This paper is organized as follows.</p>
<p>Section 2 provides the background of this paper. Section 3 presents related work. Section 4 describes the Takamaka subset of Java for smart contracts and its Hotmoka runtime. Section 5 defines a general architecture for protocol-based code verification. Section 6 describes our implementation of protocol-based verification, over Tendermint and Mokamint, and shows two examples of protocol-based checks. Section 7 reports experiments with our implementation and describes how readers and reviewers can validate them. Section 8 shows how the blockchain can cope with the evolution of code verification rules. Section 9 concludes the paper and discusses limitations.</p>
<p>This paper is an extended version of <xref ref-type="bibr" rid="B24">Olivieri et al. (2021)</xref>. The main differences with that conference paper are: a more extended related work section; an extended description of Takamaka and Hotmoka; a second example of verification rule implementation; the description of the implementation of the verification module update; the implementation over Mokamint, not just over Tendermint, which gives more relevance to the results; a simplification of the execution of the experiments; a global revision and extension of the article.</p>
</sec>
<sec id="s2">
<label>2</label>
<title>Background</title>
<p>Bitcoin (<xref ref-type="bibr" rid="B22">Nakamoto, 2008</xref>; <xref ref-type="bibr" rid="B2">Antonopoulos, 2017</xref>) was the first popular blockchain implementation. It is a peer-to-peer electronic cash system that stores and transmits value in a currency called <italic>bitcoin</italic>, by using a <italic>Proof of Work</italic> (PoW) consensus algorithm: each block contains a proof that some heavy work has been performed to create the block, which makes double-spending attacks expensive. A Turing-incomplete low-level Script language specifies the effects of Bitcoin&#x00027;s transactions. Script can be seen as a limited scripting language for smart contracts.</p>
<p><italic>Ethereum</italic> (<xref ref-type="bibr" rid="B8">Buterin, 2013</xref>; <xref ref-type="bibr" rid="B3">Antonopoulos and Wood, 2018</xref>) later introduced a Turing-complete bytecode for executing actual fully-fledged smart contracts, with the goal of developing decentralized applications. Ethereum smart contracts can be programmed in various high-level languages, with Solidity being the most popular one, but all run on the Ethereum virtual machine. Ethereum used PoW previously to switch to <italic>Proof of Stake</italic> (PoS). Solidity embeds some features specific to the development of smart contracts, such as a notion of gas, charged for code execution, that allows to meter the amount of code execution and avoids the risk of non-termination; and a strict deterministic execution.</p>
<p>PoS is a consensus algorithm with reduced resource consumption (<xref ref-type="bibr" rid="B31">Sedlmeir et al., 2020</xref>). It limits the right to propose a next block to a small set of nodes called <italic>validators</italic>. This set can be static or dynamic, exclusive or delegatable: in any case, this limitation allows the network to scale better and avoid the computational cost of PoW. Network participants that want to become validators freeze a certain amount of <italic>stake</italic>, which acts as an economic incentive that dissuades from validating or creating fraudulent transactions. If the validator does its job correctly, it will be remunerated for every confirmed transaction. If, instead, the network detects a fraudulent transaction, the culprit loses part of its stake and possibly the right to act as a validator. The Tendermint protocol (<xref ref-type="bibr" rid="B19">Kwon, 2014</xref>) provides a generic and customizable infrastructure for networking and consensus through PoS, with a pseudo-random election of the validator for the next block. This protocol tolerates up to <inline-formula><mml:math id="M1"><mml:mfrac><mml:mrow><mml:mn>1</mml:mn></mml:mrow><mml:mrow><mml:mn>3</mml:mn></mml:mrow></mml:mfrac></mml:math></inline-formula> of misbehaving validators. The Tendermint&#x00027;s architecture is shown in <xref ref-type="fig" rid="F1">Figure 1</xref> and consists of three software layers:</p>
<list list-type="bullet">
<list-item><p>Networking: discovers and connects nodes (<italic>peers</italic>) with each other, propagates requests for transactions, propagates blocks to and from the peers.</p></list-item>
<list-item><p>Consensus: approves or rejects the blocks received from the peers, adding them to the blockchain if they are approved.</p></list-item>
<list-item><p>Application: specifies which transaction requests are valid, how their responses are computed and how the application&#x00027;s state consequently evolves.</p></list-item>
</list>
<fig position="float" id="F1">
<label>Figure 1</label>
<caption><p>High-level architecture of an application running on a generic blockchain engine and performing protocol-based verification. This is the architecture of both Tendermint and of Mokamint.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0001.tif">
<alt-text content-type="machine-generated">Block diagram illustrating a system architecture with three layers. The top layer is labeled &#x0201C;Application&#x0201D; with a sub-layer &#x0201C;Verification.&#x0201D; Below, &#x0201C;Consensus&#x0201D; is connected with an arrow to &#x0201C;Application.&#x0201D; The bottom layer is labeled &#x0201C;Networking.&#x0201D; An &#x0201C;Application Layer Interface&#x0201D; arrow points from &#x0201C;Consensus&#x0201D; to &#x0201C;Application.&#x0201D; Arrows on the left and right sides indicate &#x0201C;Input&#x0201D; and &#x0201C;Output,&#x0201D; respectively.</alt-text>
</graphic>
</fig>
<p>Tendermint is a <italic>generic</italic> blockchain engine since it is not a monolithic software application for a specific set of blockchain transactions (like Bitcoin or Ethereum and most of all other blockchains), but it leaves the notion of transaction unspecified: programmers can develop an application layer that runs on top of Tendermint (<xref ref-type="fig" rid="F1">Figure 1</xref>) and specifies which transactions exist and which is their semantics. This application layer can be written in any programming language and can even be an actual software layer that executes Turing-complete smart contracts, as it will be in our case, as long as it connects with the blockchain engine through its Application BlockChain Interface (ABCI). The blockchain engine replicates the application state on each machine of the network.</p>
<p><italic>Proof of Stake</italic> (PoS) is often criticized for being based on a restricted club of validators that should be trusted because they are rich and, by acting as validators, become even richer. But another problem is that, to start a new network, it is difficult to convince independent entities to run, maintain and update the validators node since the cryptocurrency of a new network has initially no economic value. Therefore, another alternative has been developed, called <italic>proof of space</italic> (PoSp) (<xref ref-type="bibr" rid="B5">Ateniese et al., 2014</xref>; <xref ref-type="bibr" rid="B14">Dziembowski et al., 2015</xref>; <xref ref-type="bibr" rid="B1">Abusalah et al., 2017</xref>), where miners must dedicate a large amount of disk memory in order to be able to propose a new block. The idea is that the proposal of a new block requires to solve a <italic>challenge</italic> whose solution can be computed easily in terms of computational power but requires one to allocate a large amount of disk space. Moreover, the quality of the solution determines if the block will be preferred to other blocks proposed concurrently by other miners, and this quality is proportional to the amount of disk memory committed to the task. The energy consumption of PoSp is negligeable, and no special hardware helps for mining; currently, the technology is both cheap and democratic. Moreover, PoSp allows one to capitalize on unused memory, for free, while PoW always has an inherent electricity cost. There are a few implementations of PoSp networks that can execute Turing-complete smart contracts, namely, Chia<xref ref-type="fn" rid="fn0004"><sup>4</sup></xref> and Signum.<xref ref-type="fn" rid="fn0005"><sup>5</sup></xref> Mokamint is a generic engine for running applications over the PoSp protocol of Signum, as formalized in <xref ref-type="bibr" rid="B33">Spoto (2025)</xref>. Therefore, Mokamint is the equivalent of Tendermint but for PoSp, and its architecture is identical to that of Tendermint (see <xref ref-type="fig" rid="F1">Figure 1</xref>): the only difference is that the Mokamint&#x00027;s consensus layer is based on PoSp. The same ABCI of Mokamint is almost identical to that of Tendermint.</p>
</sec>
<sec id="s3">
<label>3</label>
<title>Related work</title>
<p>Smart contract verification is challenging and most of the available solutions are for Ethereum-based blockchains, mainly for economic reasons: Ethereum-based blockchains currently lock the highest amount of economic value.<xref ref-type="fn" rid="fn0006"><sup>6</sup></xref> Static analysis techniques can detect issues without executing the code before the contract gets deployed and becomes immutable. Specifically, these techniques examine the syntax, structure, and in some cases also the semantics of the contract at different stages of development. An intuitive example of static analysis is the compiler. For instance, in Ethereum smart contracts, the Solidity compiler (e.g., <monospace>solc</monospace>) performs basic checks on syntax and grammar. It issues alerts during the compilation process, ensuring that the source code is well-formed before being translated into EVM bytecode. It applies a static analysis because the checked code is the high-level source code (typically, Solidity), and it is static because the executable code (that is, the EVM bytecode) has not been generated yet. However, since the compiler focuses primarily on code correctness rather than on performing security checks, additional tools are necessary for more comprehensive verification. In the early stages of software development, <italic>linters</italic> may help maintain coding standards and best practices by identifying code smells, minor bugs, and stylistic inconsistencies. Popular solutions for Ethereum include Ethlint (formerly Solium) (<xref ref-type="bibr" rid="B13">Dua, 2025</xref>) and Solhint (<xref ref-type="bibr" rid="B28">Protofire, 2025</xref>). Beyond linters, also advanced static analysis tools can be applied for deeper code investigation, to detect complex security vulnerabilities and logic errors. Compared to linters, they offer more detailed and precise results by analyzing the semantics of the instructions, though they may require significant computational resources and extended processing time. Notable examples are Oyente (<xref ref-type="bibr" rid="B20">Loi et al., 2016</xref>), SmartCheck (<xref ref-type="bibr" rid="B35">Tikhomirov et al., 2018</xref>), Slither (<xref ref-type="bibr" rid="B15">Feist et al., 2019</xref>), eThor (<xref ref-type="bibr" rid="B30">Schneidewind et al., 2020</xref>), Echidna (<xref ref-type="bibr" rid="B16">Grieco et al., 2020</xref>), EtherSolve (<xref ref-type="bibr" rid="B26">Pasqua et al., 2023</xref>), and EVMLiSA (<xref ref-type="bibr" rid="B4">Arceri et al., 2024</xref>). Advanced tools are also delivered <italic>as a service</italic>, such as <ext-link ext-link-type="uri" xlink:href="https://mythx.io">https://mythx.io</ext-link>. Furthermore, there are companies that provide code audit services by using both automatic tools and human investigation. However, a limit of these <italic>off-chain</italic> tools and procedures is that they are optional: users are not required to analyze their code before it gets deployed in the blockchain.</p>
<p>To the best of our knowledge, this paper defines and implements the first protocol-based code verification for smart contracts that allows the same blockchain to reject the code that does not pass a set of verification rules. From this point of view, the technique is related to continuous integration, that builds and deploys code only if it passes all compilation and testing requirements. The main difference is that smart contracts cannot be replaced or debugged once installed in blockchain.</p>
<p>Some blockchains, such as Ethereum, apply a notion of <italic>transparency</italic> (<xref ref-type="bibr" rid="B23">Oliva et al., 2020</xref>), that lets one store in blockchain the source code of the smart contracts to guarantee that it actually compiles into their bytecode. But this is only an optional technique that ensures that bytecode and source code match and no code verification is applied.</p>
<p>The specific technique for updating the consensus rules of a network, after a change in the verification rules (Section 8), is orthogonal to our work. In Cosmos, the government module supports such an update, with (dis-)incentives to minimize misconduct within the participants. Polkadot delegates updates to periodic referendums among stakeholders. Algorand (<xref ref-type="bibr" rid="B10">Chen and Micali, 2019</xref>) triggers an update if a large majority of block proposers declare to be ready for that.</p>
</sec>
<sec id="s4">
<label>4</label>
<title>Takamaka and Hotmoka</title>
<p>This section introduces the Takamaka smart contract language and its Hotmoka runtime. The goal of this section is to provide knowledge about the specific language that we analyze, with examples that clarify the difference with Solidity (use of a general-purpose language, use of generic types, access to the keys of a map, checked casts). These examples show correct uses of Takamaka, so that subsequent static analyses become clear. Moreover, the voting example in this section is also used to coordinate the update of the verification module (Section 8).</p>
<p>Solidity is probably the most used programming language for smart contracts. Despite its success, it has limits that make its use complex and error-prone. The first problem is that it lacks support for runtime type introspection and dynamic dispatch: types used in the code can be violated at runtime since casts cannot be checked. Objects cannot even be checked at runtime for their actual type (no <monospace>instanceof</monospace> operator exists in Solidity). Lack of runtime type checks and certain safety features have contributed to bugs and vulnerabilities in many Solidity smart contracts (<xref ref-type="bibr" rid="B3">Antonopoulos and Wood, 2018</xref>). Moreover, Solidity does not feature modern programming patterns such as generic types. Smart contracts use maps extensively but, in Solidity, these are not real data structures and miss basic functionalities, such as the ability to iterate over their set of keys and values.</p>
<p>On the contrary, modern programming languages such as Java provide strong types, generic types and complex data structures (including actual and flexible maps). However, they miss some features that are specific to smart contracts: Java does not allow one to access the caller of a method, nor to sign method calls; Java does not natively include a gas mechanism to limit resource consumption, a feature that smart contract platforms typically use to enforce predictable execution and prevent infinite loops. Finally, Java is not deterministic, which is a problem in blockchain, whose consensus requires to reach the same state in all nodes of the network, impossible in the case of non-determinism.</p>
<p>For this reason, Java (and other general-purpose languages) has been used for writing blockchain code, statically installed in the blockchain at deployment time or only in the context of permissioned blockchains. But a free dynamic deployment model in a permissionless blockchain, in the style of Solidity, has never been possible with Java and other general-purpose languages, since they allow many <italic>dangerous</italic> executions in blockchain and contain a large library that allows programmers to perform actions that, in blockchain, are both meaningless and dangerous, such as file access, reflection and non-deterministic object finalization.</p>
<p>The goal of the Takamaka project was exactly to enable the use of Java as a smart contract language, analogous to how Solidity is used in Ethereum. The use of a well-known programming language such as Java leverages expertise and existing mature development tools. The application layer of Takamaka is a state machine (the <italic>application</italic> in <xref ref-type="fig" rid="F2">Figure 2</xref>) that executes transactions from request to response. Requests can specify the addition of a jar in the permanent state of the application, or the execution of a constructor, or of an instance or static method of code previously installed in the state. Responses include the effects of the transaction as a set of field updates. Updates can be computed since the jar of the Java code is instrumented before being installed in the blockchain, with extra code that keeps track of the affected fields of objects (<xref ref-type="bibr" rid="B32">Spoto, 2019</xref>). Determinism is ensured by a static analysis that ensures that only a deterministic subset of Java is used, restricted to a minimal deterministic and non-dangerous API of the Java library. The state machine (runtime) of Takamaka is called Hotmoka<xref ref-type="fn" rid="fn0007"><sup>7</sup></xref> and is implemented itself in Java. It runs on a standard Java virtual machine. The state is kept in a Merkle-Patricia trie that implements a map from the hash of requests to their corresponding response. This trie is kept in the Xodus transactional database by JetBrains.<xref ref-type="fn" rid="fn0008"><sup>8</sup></xref></p>
<fig position="float" id="F2">
<label>Figure 2</label>
<caption><p>The interface of a poll smart contract. The complete code is available at: <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/dao/Poll.java">https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/dao/Poll.java</ext-link>.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0002.tif">
<alt-text content-type="machine-generated">Interface code snippet for a voting system contract. It includes methods to get eligible voters, view current poll participants, cast votes, check if the poll is over, and close the poll. Comments describe each method&#x00027;s purpose.</alt-text>
</graphic>
</fig>
<p>An important difference between Takamaka and Solidity is that smart contracts are deployed in Solidity, together with their compiled code: every deployed instance of the contract carries its own copy of the code. In Takamaka, instead, the standard Java approach is used: the code of the smart contract is installed in the database of the blockchain, once and for all; later, smart contracts are instantiated from that single code instance by calling their respective constructors. Because of this, this paper refers to the <italic>installation</italic> of the code of a smart contract and to the subsequent <italic>instantiation</italic> of specific smart contract instances, rather than to the <italic>deployment</italic> of a smart contract, which is the usual terminology in Solidity. This difference is important for the scalability of our technique, as Section 7 will show later.</p>
<p>Another significant difference is that externally-owned accounts are just a special case of smart contracts in Takamaka, while they are different concepts in Solidity. Namely, in Takamaka, an externally-owned account is a smart contract that embeds a public key and that has the right to originate a transaction, as long as that transaction is signed with the matching private key. Externally-owned accounts, in Takamaka, have an actual type (a class), that extends <monospace>Contract</monospace> and can be redefined and specialized.<xref ref-type="fn" rid="fn0009"><sup>9</sup></xref> It follows that externally-owned accounts are objects in Takamaka (in the sense of object-oriented programming) and that two distinct objects might even contain the same public key and therefore be controllable with the same, corresponding private key. It is even possible to rotate the key of an externally-owned account, and still keep the identity of that object. None of this is possible in Solidity. As in Solidity, also in Takamaka both smart contracts and externally-owned accounts have a balance.</p>
<p>In Takamaka, bytecode instrumentation is also used to add features that are needed for smart contracts but that are not available in standard Java: for instance, in Takamaka the caller of a method can be identified as <monospace>caller()</monospace>; cryptocurrency can be used to pay for code execution; the latter is metered through gas and stops if gas expires. Instrumentation is run by each node when smart contracts get installed (<xref ref-type="bibr" rid="B32">Spoto, 2019</xref>); the correct use of <monospace>caller()</monospace> and payments are enforced by a set of static analyses (see Section 6). All such analyses are implemented at the protocol level, as mandatory steps for the installation of new smart contracts and could be improved/expanded in the future, as this paper will show. A specific Takamaka library includes typical data structures used in smart contracts, such as very flexible maps. Takamaka has been proven to be able to implement non-trivial smart contracts for tokens and data snapshots (<xref ref-type="bibr" rid="B12">Crosara et al., 2023</xref>) and to support smart contracts with generic types (<xref ref-type="bibr" rid="B34">Spoto et al., 2023</xref>).</p>
<p>Let us see an example of a Takamaka smart contract for the implementation of a poll. Its interface is given in <xref ref-type="fig" rid="F2">Figure 2</xref>. It is a generic interface parametric <italic>w.r.t</italic>. the type <monospace>Voter</monospace> of the voters allowed to vote. A poll is similar to the vote of the shareholders of a company. Each of them has a <italic>power</italic>, that is, a maximal number of votes that it can cast. This information is returned by method <monospace>getEligibleVoters()</monospace>. Note that this method returns a map from each eligible voter to its power. Maps are real data structures in Takamaka. Therefore, clients can find the keys and the values of a map and iterate over them. Shareholders vote by calling one of the <monospace>vote()</monospace> methods: they cannot vote twice, or otherwise, these methods will throw an exception. The votes cast up to now are returned by <monospace>getVotersUpToNow()</monospace>. Method <monospace>isOver()</monospace> checks if the poll is over (that is, if a majority of the votes have been cast or all voters have voted). Method <monospace>close()</monospace> closes the poll if it is over and runs an action if a majority has been reached. This method cannot be called twice.</p>
<p><xref ref-type="fig" rid="F2">Figure 2</xref> shows the use of specific Takamaka annotations: these are a Java mechanism for adding metadata information to source and compiled code. They are irrelevant for the code executor but can be used by code analysis and instrumentation tools. Namely, <monospace>&#x00040;FromContract</monospace> states that a method or constructor can only be called from the code of a contract, which, as said before, in Takamaka includes externally-owned accounts as well. Such annotation allows the programmer to refer to the caller of the method as <monospace>caller()</monospace>. This is important, for instance, for the <monospace>vote()</monospace> methods, which need to be sure of the actual intent of the caller to cast its vote. This explains why the generic type <monospace>Voter</monospace> is bound to be a <monospace>Contract</monospace>: <monospace>Voter extends</monospace> <monospace>Contract</monospace>. If a method or constructor is annotated as <monospace>&#x00040;FromContract</monospace>, then it can be additionally annotated with <monospace>&#x00040;Payable</monospace>, which states that the caller can send cryptocurrency when calling the method or constructor. The fact that <monospace>&#x00040;Payable</monospace> only works together with <monospace>&#x00040;FromContract</monospace> is to guarantee that the caller is a contract and, therefore, that it has a balance to pay with. Moreover, <monospace>&#x00040;Payable</monospace> only works in contracts, to guarantee that the callee has a balance and can receive cryptocurrency.</p>
<p>The annotation <monospace>&#x00040;View</monospace> states that a method has no side-effect and, consequently, can be run without modifying the state of the blockchain. This allows to call <monospace>&#x00040;View</monospace> methods without paying for their execution since they do not give rise to transactions stored in blockchain but simply read its persistent state.</p>
<p>A possible concrete implementation of a poll is given in <xref ref-type="fig" rid="F3">Figure 3</xref>. It is a class that implements the <monospace>Poll</monospace> interface and extends <monospace>Storage</monospace>. The latter is a class of Takamaka&#x00027;s runtime whose instances can be created, kept and shared in blockchain: without <monospace>extends</monospace> <monospace>Storage</monospace>, instances of class <monospace>Poll</monospace> could only be used as temporary objects in methods. A <monospace>Contract</monospace> is a <monospace>Storage</monospace> with a balance. <monospace>SimplePoll</monospace> is not a <monospace>Contract</monospace> since it does not need a balance, and indeed none of its methods receive cryptocurrency at call-time (none is <monospace>&#x00040;Payable</monospace>).</p>
<fig position="float" id="F3">
<label>Figure 3</label>
<caption><p>An implementation of the <monospace>Poll</monospace> interface from <xref ref-type="fig" rid="F2">Figure 2</xref>. The complete code is available at: <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/dao/SimplePoll.java">https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/dao/SimplePoll.java</ext-link>.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0003.tif">
<alt-text content-type="machine-generated">Java code for a class &#x0201C;SimplePoll&#x0201D; extending &#x0201C;Contract,&#x0201D; implementing voting functionality. The code defines data structures, constructors, and methods like &#x0201C;vote,&#x0201D; &#x0201C;close,&#x0201D; and &#x0201C;isOver.&#x0201D; It includes checks for voter eligibility and poll status, and uses &#x0201C;StorageMapView&#x0201D; and &#x0201C;StorageTreeMap&#x0201D; for managing voters and votes. Error messages are provided for unauthorized actions.</alt-text>
</graphic>
</fig>
<p>The constructor of <monospace>SimplePoll</monospace> receives a map that states who the voters are and how many votes each of them can cast. This is not necessarily a modifiable map but just a map <italic>view</italic>: it is possible to read its mappings but not necessarily to modify them. The constructor iterates on the voters to compute the sum of all votes that can be cast. As said before, this iteration would be impossible in Solidity. The addition of two Java&#x00027;s <monospace>BigInteger</monospace>s is not performed through their <monospace>add()</monospace> method, which would be rejected by the static verifier of Takamaka&#x00027;s code since its complexity is not constant; hence, its gas consumption is not constant either. Instead, the support class <monospace>BigIntegerSupport</monospace> is used, which charges a variable amount of gas, depending on the size of the <monospace>BigInteger</monospace>s. The constructor terminates by computing an immutable snapshot of the (currently empty) map of votes cast that will be returned to clients by the <monospace>getVotersUpToNow()</monospace> method. The constructor receives a second argument <monospace>action</monospace>, that implements the local class <monospace>Action</monospace> and that it stores in the poll. This action will be used later, to run its <monospace>run()</monospace> method if the poll reaches its goal.</p>
<p>The <monospace>vote()</monospace> methods modify the <monospace>votersUpToNow</monospace> map. Since these are <monospace>&#x00040;FromContract</monospace> methods, they are allowed to refer to the <monospace>caller()</monospace> contract, the one that signed the transaction for calling the method. Method <monospace>vote()</monospace> delegates to <monospace>vote(BigInteger votes)</monospace> by passing the total amount of votes that the caller can cast. The latter method checks if the caller is allowed to cast <monospace>votes</monospace> votes. That is, if the caller is actually a potential voter, if it did not already vote, if <monospace>votes</monospace> is non-negative and if <monospace>votes</monospace> is not larger than the maximal amount of votes that the caller can cast (see the auxiliary method <monospace>checkIfCanVote()</monospace>). Note the use of <monospace>containsKey()</monospace> inside it, which would be impossible in Solidity. Moreover, note that <monospace>vote()</monospace> recreates the <monospace>snapshotOfVotersUpToNow</monospace>, since the votes have changed.</p>
<p>Method <monospace>close()</monospace> checks if the poll has been closed already. Otherwise, it checks if the poll is over (a majority has been reached or all voters have cast their vote). If a majority has been reached (<monospace>goalReached()</monospace>) the action gets run, that was provided to the constructor of the poll.</p>
<p>Hotmoka is the runtime that instruments the bytecode of Takamaka smart contracts, interprets their annotations and runs their constructors and methods inside database transactions. Instrumentation is needed since annotations such as <monospace>&#x00040;FromContract</monospace> and the access to the <monospace>caller()</monospace> are not available in Java, hence they must be provided by code instrumentation. A full description of Hotmoka is beyond the scope of this paper, therefore no more details are provided here. The interested reader can find more information in <xref ref-type="bibr" rid="B32">Spoto (2019)</xref>. Here, we just say that the state of all smart contracts installed in blockchain, and their bytecode, is stored inside a persistent database. The bytecode instrumentation allows Hotmoka to infer the set of fields of objects modified by a transaction. This set is stored in the database, as the result of a transaction. The database implements a Merkle-Patricia trie, exactly as in Ethereum. Therefore, it is possible to revert to previous states. This is important if Hotmoka runs on top of a consensus engine that requires history changes, such as Mokamint.</p>
</sec>
<sec id="s5">
<label>5</label>
<title>Protocol-based code verification</title>
<p>This section presents protocol-based code verification in the context of a generic blockchain engine, such as Tendermint or Mokamint. This allows one to understand where it runs and which software architecture can be used to support its execution.</p>
<p><xref ref-type="fig" rid="F4">Figure 4</xref> shows a more detailed picture of a generic blockchain engine and of an application connected through its application layer interface, such as ABCI. It shows that the engine keeps the blocks of the blockchain in its own database, that does not need to be the same used to hold the application&#x00027;s <italic>state</italic>. The latter holds, for instance, the code of the smart contracts installed in blockchain and the value of their state variables. The engine needs only the hash of the application state, for consensus, to ensure that all nodes have reached the same application state.</p>
<fig position="float" id="F4">
<label>Figure 4</label>
<caption><p>A generic blockchain engine and an application, with their respective databases.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0004.tif">
<alt-text content-type="machine-generated">Diagram showing a system architecture with two main components: Application and Blockchain Engine. The Application layer interacts with the State database via an Application Layer Interface using TCP. The Blockchain Engine processes messages and connects to a Database of blocks. It communicates with other blockchain nodes via TCP. Arrows indicate data flow between components.</alt-text>
</graphic>
</fig>
<p>One can define the application state as a map &#x003C3; from the hash of the requests that the blockchain has executed to the responses that have been computed for them. Therefore, the responses are contained in the application state; instead, the requests are not contained in the application state: only their hash is used and mapped into the corresponding response. Since the state is a map, it can be implemented as a Merkle-Patricia trie from hashes of requests to responses. The full requests are contained in the database of blocks of the engine since they are needed to replay the transactions in all nodes of the network.</p>
<p>Protocol-based code verification requires a code verification module (<xref ref-type="fig" rid="F1">Figure 1</xref>). This is part of the application layer since it contributes to the execution of the application-specific requests to install code (for instance, smart contracts) in blockchain. Assume that a <italic>request</italic>, whose hash is <italic>request</italic><sub><italic>h</italic></sub>, reaches the blockchain, requiring to install, in blockchain, the code of some smart contracts, reported inside <italic>request</italic>.</p>
<p><xref ref-type="fig" rid="F5">Figure 5</xref> shows the sequence diagram for the execution of <italic>request</italic>. Namely, the generic blockchain engine routes <italic>request</italic> through networking and consensus up to the application, which uses its verification module to either approve or reject the code. If approved, the application packs the installed code in a <italic>response</italic> and updates its state &#x003C3; with a new binding: &#x003C3;(<italic>request</italic><sub><italic>h</italic></sub>) &#x0003D; <italic>response</italic>. The hash <italic>request</italic><sub><italic>h</italic></sub> is an immutable, machine-independent reference to this code, used later to instantiate and execute smart contracts. If the code is rejected, instead, the application state is expanded with a failure response; this kind of response does not contain any installed code since failure prevented the installation of any code in blockchain.</p>
<fig position="float" id="F5">
<label>Figure 5</label>
<caption><p>Sequence diagram for code verification and installation in blockchain.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0005.tif">
<alt-text content-type="machine-generated">Sequence diagram illustrating a blockchain process. It involves a User, Blockchain Engine, Application Layer Interface, Request Handler, Verification, State, and Smart Contract Executor. The process starts with the user calling a method request, which is processed through the blockchain engine and application layer. It undergoes jar check and code approval or rejection in verification. The state updates accordingly, and a response with consensus is sent back to the user.</alt-text>
</graphic>
</fig>
<p><xref ref-type="fig" rid="F6">Figure 6</xref> reports an example of application state evolution. It reports the requests in full for readability, but we stress that only the hash of the requests is kept in the application state. <xref ref-type="fig" rid="F6">Figure 6a</xref> shows the application state after the execution of a code installation request for which verification succeeds. In this example, the code is Java bytecode because it is the target of the compilation of Takamaka, packaged into a <italic>jar</italic>, i.e., a zipped container of Java bytecode. The response contains the instrumented jar. In terms of Java, the hash of the request can be used as the <italic>classpath</italic> of subsequent code executions. <xref ref-type="fig" rid="F6">Figure 6b</xref> reports, instead, a request whose code fails to verify. The response does not include any instrumented code to install in the blockchain. This shows that the verification rules are part of the consensus rules that determine which code installation request is valid and which must be rejected instead (<xref ref-type="fig" rid="F6">Figures 6a</xref>, <xref ref-type="fig" rid="F6">b</xref>). Hence, they must be the same in every node of the network and must be deterministic.</p>
<fig position="float" id="F6">
<label>Figure 6</label>
<caption><p>The evolution of the application state during a sequence of requests. <bold>(a)</bold> Successful verification. <bold>(b)</bold> Failed verification. <bold>(c)</bold> Instantiation of a smart contract. <bold>(d)</bold> Call a method of a contract instance.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0006.tif">
<alt-text content-type="machine-generated">&#x0201C;Four diagrams labeled a to d illustrate different states of a jar request process. (a) Successful verification: The diagram shows a &#x0201C;jar install request&#x0201D; with &#x0201C;bytes of jar&#x0201D; leading to a successful &#x0201C;response&#x0201D; with &#x0201C;bytes of jar.&#x0201D; (b) Failed verification: Similar to a, but includes a failure with &#x0201C;failure message&#x0201D; instead of &#x0201C;bytes of jar.&#x0201D; (c) Instantiation of a smart contract: Displays multiple requests, ending in &#x0201C;object updates.&#x0201D; (d) Call a method of a contract instance: Similar to c, with the addition of a &#x0201C;method call request&#x0201D; resulting in &#x0201C;object updates and result.&#x0201D;</alt-text>
</graphic>
</fig>
<p>Protocol-based verification performs code verification statically, only once, when the code is installed in the blockchain. For instance, <xref ref-type="fig" rid="F6">Figure 6c</xref> shows a subsequent request that asks to instantiate a smart contract whose code has been installed by the request in <xref ref-type="fig" rid="F6">Figure 6a</xref>. The request in <xref ref-type="fig" rid="F6">Figure 6c</xref> uses the hash of the request in <xref ref-type="fig" rid="F6">Figure 6a</xref> as its classpath and contains the parameters for calling the constructor of the smart contract. The execution of the request runs that constructor without code verification: the latter has already been performed in <xref ref-type="fig" rid="F6">Figure 6a</xref>. The immutable reference <italic>hash of request&#x00023;0</italic> is used later to refer to the new smart contract: the index <italic>&#x00023;0</italic> is used in the implementation of Takamaka to refer to the first object created during the execution of a request. In general, a request can instantiate many objects, depending on the code that it executes (for simplicity, this example assumes that only one has been instantiated). The state of the new smart contract is reported in the response as a set of <italic>updates</italic>, that is, instance fields modified during the execution of the request, including those of the smart contract instance <italic>hash of request&#x00023;0</italic> that has been created in blockchain. Finally, <xref ref-type="fig" rid="F6">Figure 6d</xref> shows the execution of a request asking to call a method on the instance of the smart contract <italic>hash of request&#x00023;0</italic>. This last request refers to both the classpath and the target instance smart contract. Its execution, in general, modifies some instance fields of some objects in the blockchain that are reported as <italic>updates</italic> in its response. This last request does not verify the code either since it is not a code installation request.</p>
<p>The fact that code verification is run only once, at code installation time, is important for efficiency since the installation of new code in the blockchain is a relatively rare event in comparison to the instantiation of new smart contracts and the execution of their methods. This is particularly the case for Hotmoka, where the code of a smart contract is installed once and then recycled for all instances of the smart contract that get subsequently created. This is different from Ethereum, where each instance of the smart contract reinstalls the code, although it is identical to that of the other instances. Therefore, Hotmoka installs (and verifies) the code of a smart contract only once, independently from how many instances of that smart contract will be created later. This is at the basis of the efficiency results that will be described in Section 7.</p>
<p>The rules of protocol-based verification are part of the consensus rules of the blockchain, since they determine if the response of a request to install code in blockchain is successful or fails. Therefore, they determine the evolution of the state of the application layer and its hash, which is reported in the blocks of the underlying blockchain engine and used for consensus. This means that all nodes must use the same verification rules, or otherwise, the network nodes will never agree on a common state: nodes that use different rules will automatically exclude each other.</p>
</sec>
<sec id="s6">
<label>6</label>
<title>Implementation</title>
<p>We have implemented protocol-based verification inside the Hotmoka runtime for executing smart contracts written in the Takamaka subset of Java. Hotmoka is an application with an interface to the ABCI. Hence, it can therefore run on top of both Tendermint and Mokamint (<xref ref-type="fig" rid="F4">Figure 4</xref>). Hence, our protocol-based verification is currently available for both PoS and PoSp blockchains.</p>
<p>The verification module is implemented as a sequence of <italic>checks</italic> performed on methods and classes. Since a request to install new code in blockchain contains the compiled bytecode only, such checks run at Java bytecode level, by using the BCEL library for Java bytecode manipulation.<xref ref-type="fn" rid="fn0010"><sup>10</sup></xref> The source code is simply not available in blockchain. Currently, Takamaka&#x00027;s protocol-based verification performs 21 checks on every jar that gets installed in blockchain. They must all pass, or otherwise the jar will be rejected. <xref ref-type="fig" rid="F7">Figure 7</xref> describes some of them.</p>
<fig position="float" id="F7">
<label>Figure 7</label>
<caption><p>Some of the 21 protocol-based verifications currently performed by Hotmoka on Takamaka smart contracts, when they get installed in blockchain.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0007.tif">
<alt-text content-type="machine-generated">Table displaying guidelines for applying specific annotations and practices in Java programming related to blockchain. It includes correct contexts for &#x0201C;&#x00040;FromContract,&#x0201D; &#x0201C;&#x00040;Payable,&#x0201D; and &#x0201C;caller(),&#x0201D; along with restrictions on finalizers and the need to use only approved Java APIs. The explanations emphasize ensuring deterministic behavior and proper usage in blockchain contexts.</alt-text>
</graphic>
</fig>
<p>The checks in <xref ref-type="fig" rid="F7">Figure 7</xref> filter out smart contracts whose installation would compromize the security and the functionality of the blockchain. As already discussed in the introduction, they are specific of a general-purpose language that must be used for writing smart contracts. For instance, the correct type for the storage fields is already enforced by the compiler of Solidity, while a specific check is needed for Java, that was not devised for smart contracts, originally. Determinism comes out-of-the-box in Solidity, that was designed for being deterministic, while that is not true in general-purpose languages. The rule that enforces a white-listed API is needed in Java also to avoid library calls to the file system, for instance, that are not useful for smart contracts and dangerous in blockchain, while Solidity has almost no library support and the little that exists is meant for smart contracts. Note that this same rule forbids calls to Java reflection, that is, to low-level calls that might bypass most security checks, and correspond to the dangerous <monospace>delegatecall()</monospace> of Solidity.</p>
<p>The rest of this section shows, in detail, the implementation of the last two checks from <xref ref-type="fig" rid="F7">Figure 7</xref>.</p>
<sec>
<label>6.1</label>
<title>Correct context for <monospace>caller()</monospace></title>
<p>This check verifies that the method <monospace>caller()</monospace> is used in the right context. That method corresponds to <monospace>msg.sender</monospace> in Solidity: it allows programmers to get a reference to the <italic>contract</italic> that called a method or constructor <italic>X</italic>. Namely, the method <monospace>caller()</monospace> can be used inside the code of <italic>X</italic> only if <italic>X</italic> satisfies two constraints:</p>
<list list-type="order">
<list-item><p><italic>X</italic> is annotated as <monospace>&#x00040;FromContract(class)</monospace>, for some <monospace>class</monospace>;</p></list-item>
<list-item><p>the invocation of <monospace>caller()</monospace> occurs on <monospace>this</monospace>.</p></list-item>
</list>
<p>The rationale of constraint 1 is that <monospace>&#x00040;FromContract(class)</monospace> guarantees that <italic>X</italic> can <italic>only</italic> be called from a contract (hence, also from an externally-owned account, in Takamaka) of type <monospace>class</monospace>, or subclass.<xref ref-type="fn" rid="fn0011"><sup>11</sup></xref> Therefore, the caller actually exists. For instance, methods <monospace>vote()</monospace> in <xref ref-type="fig" rid="F3">Figure 3</xref> can use <monospace>caller()</monospace> since they are annotated as <monospace>&#x00040;FromContract</monospace>. Instead, the use of <monospace>caller()</monospace> would be illegal in the constructor of <monospace>SimplePoll</monospace>, since it is not annotated as <monospace>&#x00040;FromContract</monospace>: that constructor could be called from any piece of code, not necessarily from a contract.</p>
<p>As another example, the following contract stores its creator in field <monospace>owner</monospace>. The use of <monospace>caller()</monospace> is correct here, since it occurs inside a <monospace>&#x00040;FromContract</monospace> constructor, and is a typical pattern in smart contracts, to identify the creator contract of another contract:</p>
<preformat>
&#x000A0;
public class C1 extends Contract {
  private C1 owner;

  public @FromContract(C1.class) C1() {
    owner = (C1) caller(); // ok
  }
}
&#x000A0;
</preformat>
<p>Instead, it is incorrect to invoke <monospace>caller()</monospace> in a method or constructor not annotated as <monospace>&#x00040;FromContract</monospace>, since its caller is not necessarily a contract and <monospace>caller()</monospace> would be meaningless in that case:</p>
<preformat>
&#x000A0;
public class C2 extends Contract {
  public void m() {
    ... = caller(); // error at installation time
  }
}
&#x000A0;
</preformat>
<p>The reason for constraint 2 is that <monospace>this.caller()</monospace> allows a method or constructor to access its caller during its current execution, which is sensible and useful, while other calls not on <monospace>this</monospace> would let one access the caller of the last invoked method or constructor of other contracts, with possible logical inconsistencies and privacy issues. For the same reason, the use of <monospace>tx.origin</monospace> is normally an antipattern in Solidity [see <italic>Tx.origin Authentication</italic> in (<xref ref-type="bibr" rid="B3">Antonopoulos and Wood 2018</xref>)]. Constraint 2 holds in every use of <monospace>caller()</monospace> in <xref ref-type="fig" rid="F3">Figure 3</xref>, as well as in classes <monospace>C1</monospace> and <monospace>C2</monospace> above, while it is violated for instance below:</p>
<preformat>
&#x000A0;
public class C3 extends Contract {
  private C3 owner;

  public @FromContract(C3.class) C3() {
    owner = (C3) caller(); // ok
  }

  public @FromContract void m() {
    ... owner.caller() ...; // error at deployment-time
  }
}
&#x000A0;
</preformat>
<p><xref ref-type="fig" rid="F8">Figure 8</xref> reports our implementation of a check that verifies if a method satisfies constraints 1 and 2 above. The code has been simplified for readability. Full understanding of the code in <xref ref-type="fig" rid="F8">Figure 8</xref> requires knowledge about Java bytecode and BCEL, which is outside the scope of this paper. Nevertheless, it is possible to understand its structure at the pseudocode level: the constructor of the check scans the Java bytecode instructions of the method, filters those that call a the method <monospace>caller()</monospace> of a Takamaka&#x00027;s storage object and checks two conditions for each of them (with the two nested <monospace>if</monospace>&#x00027;s inside the more external <monospace>if</monospace>): the method must be annotated as <monospace>FromContract</monospace> (constraint 1 above), and the invocation must be immediately preceded by a bytecode instruction that pushes <monospace>this</monospace> on the stack, as the receiver of the call to <monospace>caller()</monospace> (constraint 2 above). If any of the <monospace>if</monospace>&#x00027;s is satisfied, an issue is generated. The presence of an issue is enough to reject, later, the installation of the code in blockchain.</p>
<fig position="float" id="F8">
<label>Figure 8</label>
<caption><p>Pseudocode of the protocol-based check for the correct use of <monospace>caller()</monospace> in a given method. The actual full Java code is available at: <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/hotmoka/blob/master/io-hotmoka-verification/src/main/java/io/hotmoka/verification/internal/checksOnMethods/CallerIsUsedOnThisAndInFromContractCheck.java">https://github.com/Hotmoka/hotmoka/blob/master/io-hotmoka-verification/src/main/java/io/hotmoka/verification/internal/checksOnMethods/CallerIsUsedOnThisAndInFromContractCheck.java</ext-link>.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0008.tif">
<alt-text content-type="machine-generated">Code snippet with a logic flow for validating &#x0201C;Storage.caller()&#x0201D; method invocations. It checks if methods are annotated with &#x0201C;&#x00040;FromContract&#x0201D; and ensures &#x0201C;caller()&#x0201D; is called on &#x02018;this&#x02018;. Errors are issued if conditions are not met.</alt-text>
</graphic>
</fig>
</sec>
<sec>
<label>6.2</label>
<title>Correct fields in storage classes</title>
<p>As said above, storage objects, in Takamaka, are those that can be stored in blockchain and therefore get duplicated in each node that holds a copy of the blockchain. Therefore, they cannot hold machine-dependent fields, or otherwise consensus would be lost. In particular, they cannot hold RAM memory addresses, since these would be different in each node of the blockchain, that runs the code in its own JVM. Because of this requirement, the classes <italic>C</italic> that define storage objects, in Takamaka, are allowed to define fields only if such fields hold storage objects themselves: since storage objects are represented by machine-independent hashes, they can be shared without any risk of losing consensus. But this would not be flexible enough. Namely, Takamaka allows such classes <italic>C</italic> to define also fields of primitive (often called <italic>basic</italic>) type (the eight Java types <monospace>boolean</monospace>, <monospace>char</monospace>, <monospace>byte</monospace>, <monospace>short</monospace>, <monospace>int</monospace>, <monospace>long</monospace>, <monospace>float</monospace>, and <monospace>double</monospace>). These have a fixed, machine-independent representation in Java. Hence, they are represented identically in each node of the blockchain. Furthermore, Takamaka allows <italic>C</italic> to define fields whose type is <monospace>BigInteger</monospace>, that is a Java way to perform infinite arithmetic and replaces Solidity&#x00027;s <monospace>uint256</monospace>; or <monospace>String</monospace>, that is paramount in every programming language. Both <monospace>BigInteger</monospace> and <monospace>String</monospace> can be represented as machine-independent byte arrays and stored in blockchain.</p>
<p><xref ref-type="fig" rid="F9">Figure 9</xref> reports a simplified code of the implementation of this protocol-based check. The constructor of the check scans the fields of the class under verification and checks if their type is allowed in Takamaka. Otherwise, an issue is generated. As described above, the pseudocode checks if the type of the field is a storage type itself (that is, it is not an array and it extends <monospace>Storage</monospace>); or a primitive type of Java; or <monospace>BigInteger</monospace> or <monospace>String</monospace>. If this check passes, then the strongly-typed guarantee of Java bytecode allows one to run the code without checking what is actually written into the fields, since it can only be one of these types, statically checked once and for all at code installation time.</p>
<fig position="float" id="F9">
<label>Figure 9</label>
<caption><p>Pseudocode of the protocol-based check for the correct type of the fields of a given storage class. The actual full Java code is available at: <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/hotmoka/blob/master/io-hotmoka-verification/src/main/java/io/hotmoka/verification/internal/checksOnClass/StorageClassesHaveFieldsOfStorageTypeCheck.java">https://github.com/Hotmoka/hotmoka/blob/master/io-hotmoka-verification/src/main/java/io/hotmoka/verification/internal/checksOnClass/StorageClassesHaveFieldsOfStorageTypeCheck.java</ext-link>.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0009.tif">
<alt-text content-type="machine-generated">Code snippet with syntax highlighting. It includes a conditional checking if a field type in a class is neither a storage class, a primitive type, nor BigInteger, String, Object, or an interface. If not, it issues an error about an illegal type for the field.</alt-text>
</graphic>
</fig>
<p>For extra flexibility, Takamaka allows fields to have <monospace>Object</monospace> type and to have an interface type (see <xref ref-type="fig" rid="F9">Figure 9</xref>). The reason for this is that interfaces are largely used in modern programming languages and they would be strongly missed in Takamaka. For instance, <monospace>StorageMapView</monospace> in <xref ref-type="fig" rid="F3">Figure 3</xref> is an interface and field <monospace>snapshotOfVotersUpToNow</monospace> has an interface type. If interfaces would be banned in Takamaka, then the smart contract in <xref ref-type="fig" rid="F3">Figure 3</xref> would be rejected by the protocol-based verification of Takamaka. The reason for allowing <monospace>Object</monospace>, instead, is that generic types, in Java, are compiled by <italic>erasure</italic> into Java bytecode (<xref ref-type="bibr" rid="B21">Naftalin and Wadler, 2006</xref>), that is, replaced by <monospace>Object</monospace> and checked at run time through casts added by the compiler. If storage classes would ban fields of type <monospace>Object</monospace> then, for instance, it would become impossible to write generic storage classes such as <monospace>StorageMap</monospace> in <xref ref-type="fig" rid="F3">Figure 3</xref>, since that class uses two generic type parameters that are compiled in bytecode through fields of type <monospace>Object</monospace>. Therefore, <monospace>StorageMap</monospace> (and, by transitivity, the <monospace>SimplePoll</monospace> class itself) would be rejected by the protocol-based verification of Takamaka.</p>
<p>This justifies why <monospace>Object</monospace> and interfaces are allowed in <xref ref-type="fig" rid="F9">Figure 9</xref>. As a consequence, code instrumentation of Takamaka smart contracts adds checks to all write operations to fields of type <monospace>Object</monospace> or interface, to verify that, at run time, only values of storage type or <monospace>BigInteger</monospace>s or <monospace>String</monospace>s are stored into such fields (primitive types are not subtypes of <monospace>Object</monospace> or interfaces in Java, thus there is no need to check for them). That is, only for fields of type <monospace>Object</monospace> or of interface type, the check has been moved from static to dynamic.</p>
</sec>
</sec>
<sec id="s7">
<label>7</label>
<title>Experiments</title>
<p>This section reports experiments with protocol-based verification. The goal is twofold:</p>
<list list-type="order">
<list-item><p>to show that its implementation is possible (Section 7.1);</p></list-item>
<list-item><p>to show that its cost can be extremely low, so that it does not increase the actual execution time of the transactions in blockchain (Section 7.2).</p></list-item>
</list>
<p>The evaluation metric, in the second case, is the extra time required for the protocol-based verification, in comparison with the same blockchain without protocol-based verification. This will of course depend on the complexity of the analyses that one wants to perform. Therefore, the context of this paper are the 21 analyses for Takamaka, in part reported in <xref ref-type="fig" rid="F7">Figure 7</xref>.</p>
<sec>
<label>7.1</label>
<title>Implementation</title>
<p>We have implemented our protocol-based verification for the Takamaka subset of Java, inside its Hotmoka runtime that works as a Tendermint and as a Mokamint application. Therefore, it is an actual blockchain, based on PoS (Tendermint) or PoSp (Mokamint) consensus, that can be programmed with smart contracts written in Java. We have created testcases that start a blockchain and request to install in blockchain the examples from Section 6. We have also created a test that installs a smart contract that runs many transactions, to check the scalability of the technique and evaluate the effect of turning protocol-based verification on and off. Readers who want to run the experiments and inspect the results need a Linux machine with Java version 21 or later, and the standard development tools Git and Maven. In order to run tests against a Tendermint blockchain, that software (version 0.34.15) must be downloaded from <ext-link ext-link-type="uri" xlink:href="https://github.com/tendermint/tendermint/releases/tag/v0.34.15">https://github.com/tendermint/tendermint/releases/tag/v0.34.15</ext-link> and added to the command-line path.</p>
<p>The source code of Hotmoka can be downloaded with</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;git&#x000A0;clone&#x000A0;<ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/hotmoka.git">https://github.com/Hotmoka/hotmoka.git</ext-link>
&#x000A0;
</preformat>
<p>That repository also contains the code of the 21 checks of protocol-based verification (including those in <xref ref-type="fig" rid="F8">Figures 8</xref>, <xref ref-type="fig" rid="F9">9</xref>). After download, one can enter the new <monospace>hotmoka</monospace> directory:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;cd&#x000A0;hotmoka
&#x000A0;
</preformat>
<p>and compile the project with</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;mvn&#x000A0;clean&#x000A0;install
&#x000A0;
</preformat>
<p>After a successful compilation, enter the test subproject:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;cd&#x000A0;io-hotmoka-tests
&#x000A0;
</preformat>
<p>The first JUnit testcase that we show starts a blockchain of a single node, connects to the node and requests a transaction that installs a jar containing class <monospace>C1</monospace> from Section 6:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;mvn&#x000A0;test&#x000A0;-Dtest=io.hotmoka.tests.SSVMT2025_C1
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;-Dverbose=true&#x000A0;-DnodeType=tendermint
&#x000A0;
</preformat>
<p>The result is successful, since <monospace>C1</monospace> passes all verification checks:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;Test&#x000A0;io.hotmoka.tests.SSVMT2025_C1:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;the&#x000A0;jar&#x000A0;has&#x000A0;been&#x000A0;installed&#x000A0;in&#x000A0;the&#x000A0;node&#x000A0;without
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;exception
&#x000A0;&#x000A0;&#x000A0;
&#x000A0;
</preformat>
<p>It is possible to run the test on a PoSp blockchain as well, by turning on a Mokamint node instead of a Tendermint node (Mokamint&#x00027;s start-up will be slower, since it initializes a big disk file for its proof of space consensus):</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;mvn&#x000A0;test&#x000A0;-Dtest=io.hotmoka.tests.SSVMT2025_C1
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;-Dverbose=true&#x000A0;-DnodeType=mokamint
&#x000A0;
</preformat>
<p>The result will be the same.</p>
<p>The subsequent experiment tries to install <monospace>C2</monospace> instead:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;mvn&#x000A0;test&#x000A0;-Dtest=io.hotmoka.tests.SSVMT2025_C2
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;-Dverbose=true&#x000A0;-DnodeType=mokamint
&#x000A0;
</preformat>
<p>This attempt will fail since protocol-based verification fails for <monospace>C2</monospace>, as expected:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;Test&#x000A0;io.hotmoka.tests.SSVMT2025_C2:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;the&#x000A0;installation&#x000A0;of&#x000A0;the&#x000A0;jar&#x000A0;threw&#x000A0;exception:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;io.hotmoka.verification.VerificationException:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;io/hotmoka/examples/ssvmt2025/c2/C2.java:10:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;caller()&#x000A0;can&#x000A0;only&#x000A0;be&#x000A0;used&#x000A0;inside&#x000A0;a&#x000A0;&#x00040;FromContract
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;method&#x000A0;or&#x000A0;constructor
&#x000A0;&#x000A0;&#x000A0;&#x000A0;
&#x000A0;
</preformat>
<p>The third experiment tries to install <monospace>C3</monospace> in blockchain, which does not pass the protocol-based verification, as expected:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;mvn&#x000A0;test&#x000A0;-Dtest=io.hotmoka.tests.SSVMT2025_C3
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;-Dverbose=true&#x000A0;-DnodeType=mokamint
&#x000A0;
</preformat>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;Test&#x000A0;io.hotmoka.tests.SSVMT2025_C3:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;the&#x000A0;installation&#x000A0;of&#x000A0;the&#x000A0;jar&#x000A0;threw&#x000A0;exception:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;io.hotmoka.verification.VerificationException:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;io/hotmoka/examples/ssvmt2025/c3/C3.java:16:
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;caller()&#x000A0;can&#x000A0;only&#x000A0;be&#x000A0;called&#x000A0;on&#x000A0;&#x02018;&#x02018;this&#x00027;&#x00027;
&#x000A0;
</preformat>
</sec>
<sec>
<label>7.2</label>
<title>Scalability</title>
<p>In order to evaluate the scalability of our technique, we have created a JUnit testcase that installs in blockchain a smart contract that creates and funds 500 externally-owned accounts. The test subsequently performs 1, 000 random transfers of cryptocurrency among the accounts and finally determines which, at the end, is the <italic>richest</italic> among them (which one has the highest balance). The whole process is repeated ten times. The testcase can be run with:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;mvn&#x000A0;test&#x000A0;-Dtest=io.hotmoka.tests.SSVMT2025
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;-Dverbose=true&#x000A0;-DnodeType=tendermint
&#x000A0;
</preformat>
<p>We prefer to use Tendermint above because the execution time information is stable: Tendermint has a <italic>fixed</italic> block creation rate, while the PoSp of Mokamint can have significant random fluctuations around an <italic>average</italic> block creation rate. The result of the execution of the testcase is something like:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;1/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;bf8ed9dd...5efed998b78eb7&#x00023;2f8
&#x000A0;&#x000A0;2/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;f3382128...9f7961f04e9d7e&#x00023;77a
&#x000A0;&#x000A0;3/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;2d8438af...af6e501216339a&#x00023;1e08
&#x000A0;&#x000A0;4/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;869b1973...ad04698cff35a9&#x00023;1da
&#x000A0;&#x000A0;5/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;e47bc238...d6a922828428b8&#x00023;184b
&#x000A0;&#x000A0;6/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;37c4b4c6...008fa79db22096&#x00023;10c7
&#x000A0;&#x000A0;7/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;233c59e4...007b58930368cc&#x00023;88a
&#x000A0;&#x000A0;8/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;11334c64...08cf5ca24305bb&#x00023;10c7
&#x000A0;&#x000A0;9/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;55b2cbbe...d55943a4022f89&#x00023;c74
&#x000A0;&#x000A0;10/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;7f5740c...9c80096b760743&#x00023;116c
&#x000A0;&#x000A0;10000&#x000A0;money&#x000A0;transfers,&#x000A0;10011&#x000A0;transactions&#x000A0;in&#x000A0;88445&#x000A0;ms
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;[113&#x000A0;tx/s]
&#x000A0;&#x000A0;
&#x000A0;
</preformat>
<p>The execution time of this testcase is 88.445 seconds and it does not change from machine to machine: it is determined by the block creation rate of Tendermint and by the fact that a limited number of transactions can fit in a block, since a transaction for an account must wait for the completion of the previous transaction for the same account or otherwise the transaction nonce would be incorrect and the newer transaction would be rejected. This is a typical limitation of all blockchains, starting from Ethereum. In total (including code installation and account creation) the test runs 10, 011 transactions, that is, it performs around 113 transactions per second. Let us turn code verification off now<xref ref-type="fn" rid="fn0012"><sup>12</sup></xref>:</p>
<preformat>
&#x000A0;
&#x000A0;&#x000A0;1/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;bf8ed9dd...5efed998b78eb7&#x00023;1e87
&#x000A0;&#x000A0;2/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;f3382128...9f7961f04e9d7e&#x00023;92f
&#x000A0;&#x000A0;3/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;2d8438af...af6e501216339a&#x00023;f65
&#x000A0;&#x000A0;4/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;869b1973...ad04698cff35a9&#x00023;1bd2
&#x000A0;&#x000A0;5/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;e47bc238...d6a922828428b8&#x00023;2877
&#x000A0;&#x000A0;6/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;37c4b4c6...008fa79db22096&#x00023;f3
&#x000A0;&#x000A0;7/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;233c59e4...007b58930368cc&#x00023;ea8
&#x000A0;&#x000A0;8/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;11334c64...08cf5ca24305bb&#x00023;15fb
&#x000A0;&#x000A0;9/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;55b2cbbe...d55943a4022f89&#x00023;df1
&#x000A0;&#x000A0;10/10,&#x000A0;the&#x000A0;richest&#x000A0;is&#x000A0;7f5740c...9c80096b760743&#x00023;c5f
&#x000A0;&#x000A0;10000&#x000A0;money&#x000A0;transfers,&#x000A0;10011&#x000A0;transactions&#x000A0;in&#x000A0;88356&#x000A0;ms
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;[113&#x000A0;tx/s]
&#x000A0;
</preformat>
<p>As shown above, by turning protocol-based verification off, the same testcase runs in almost the same time, with the same number of transactions per second. That is, there is no evidence that protocol-based code verification affects the execution time of the test (<xref ref-type="fig" rid="F10">Figure 10</xref>). This is not surprising:</p>
<list list-type="bullet">
<list-item><p>protocol-based code verification is performed only once, in the unique transaction that installs the smart contract&#x00027;s code (see Section 4). The other 10, 010 transactions run without any code verification, since they are not code installation transactions but rather object creation transactions or method execution transactions for money transfer.</p></list-item>
<list-item><p>The code of the installed smart contract is just a few lines of code, hence its verification is very quick.</p></list-item>
<list-item><p>The 21 code verifications that Takamaka performs are relatively simple and run quite fast.</p></list-item>
</list>
<fig position="float" id="F10">
<label>Figure 10</label>
<caption><p>Comparison of the execution time (in milliseconds) of the test smart contract with and without protocol-based verification.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0010.tif">
<alt-text content-type="machine-generated">Bar chart showing two horizontal bars comparing values with and without protocol-based verification. Without protocol-based verification: 88,356. With protocol-based verification: 88,445.</alt-text>
</graphic>
</fig>
<p>This last experiment shows that protocol-based verification, if limited to simple analyses, does not affect the execution time of a blockchain application. The latter is, instead, largely dependent on the block creation rate of the blockchain and on the ability of the application (in our example, of the testcase) to pack as many independent transactions as possible into the same block. Which is completely unrelated with protocol-based verification. This does not mean that protocol-based verification does not cost anything, but only that its cost disappears inside the much larger amount of time during which a blockchain sits idle, waiting for the next block to be minted. In particular, we have measured the cost of each of the 21 static analyses performed by our tool. We computed this measure twice: once for the installation of the jar containing the Takamaka run-time library (which occurs only once at blockchain start-up time) (<xref ref-type="fig" rid="F11">Figure 11</xref>) and once for the installation of the jar containing our test smart contract used above (which occurs only once, the first time that that smart contract is installed in blockchain) (<xref ref-type="fig" rid="F12">Figure 12</xref>). In the former case, the most expensive analysis requires less than 250 milliseconds. In the latter case, it requires less than 2.5 milliseconds. Such time disappears inside the default 4 seconds block rate of Tendermint: the analyses are performed while the blockchain sits idle waiting to mint the next block.</p>
<fig position="float" id="F11">
<label>Figure 11</label>
<caption><p>The time (in nanoseconds) for the execution of each of the 21 static analyses performed by our tool, on the jar file containing the run-time of Takamaka.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0011.tif">
<alt-text content-type="machine-generated">Horizontal bar chart showing various code-related metrics and their values. Key metrics include &#x0201C;&#x00040;FromContract is called in correct context&#x0201D; with the highest value of 21,570,617 and &#x0201C;Library calls are white-listed&#x0201D; at 11,043,460. Other notable metrics include &#x0201C;&#x00040;Payable is consistent along class hierarchy&#x0201D; at 8,557,645 and &#x0201C;&#x00040;ThrowsException is consistent along class hierarchy&#x0201D; at 8,254,645. The chart visualizes metrics related to code compliance, exceptions, and contract annotations.</alt-text>
</graphic>
</fig>
<fig position="float" id="F12">
<label>Figure 12</label>
<caption><p>The time (in nanoseconds) for the execution of each of the 21 static analyses performed by our tool, on the jar file containing the test smart contract used in Section 7.2.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0012.tif">
<alt-text content-type="machine-generated">Bar chart displaying various criteria related to software contracts. &#x0201C;Library calls are white-listed&#x0201D; and &#x0201C;packages are legal&#x0201D; have the highest frequencies, with counts of 2,305,294 and 2,221,811 respectively. Other criteria show significantly lower frequencies.</alt-text>
</graphic>
</fig>
<p>As an example of a limitation of our technique, consider the check for numerical overflows and underflows. The standard approach is to use some abstract domain for numerical approximations, such as polyhedra (<xref ref-type="bibr" rid="B7">Bagnara et al., 2008</xref>), to bound the possible values of the numerical variables. This becomes more complicated when variables are not just local variables but also fields of objects, whose number is not statically bound. Experience with such analyses shows that they immediately become very expensive, in time and memory, and do not allow to easily and deterministically bound the resources needed for their execution. The results are currently suboptimal, at least for the analysis of Java, as our experience with the Julia static analyzer has shown in the past. Such analyses are currently out of reach for a protocol-based verification technique.</p>
<p>We conclude by observing that the above 113 transactions per second is not the maximal throughput of Hotmoka. The latter can well process thousands of transactions per second, as long as they are independent, that is, if they do not origin from the same externally-owned account. Otherwise, the nonces of the transactions would be inconsistent and some of such transactions would end up being rejected by the blockchain.</p>
</sec>
</sec>
<sec id="s8">
<label>8</label>
<title>Evolution of code verification</title>
<p>This section shows how to deal with updates to the verification module of a blockchain that applies protocol-based code verification. There are many reasons for an update: the verification module might need to be updated in order to include new verification rules or to improve the precision of the already existing rules or even to patch some bugs in the module itself. When a new version is deployed, it becomes necessary to update all nodes to that version (or at least all validators), or otherwise consensus might be lost. A change in the verification rules, if deployed on a subset of the network only, entails that the updated nodes might accept a request that the non-updated nodes might reject instead, or vice versa. Moreover, there must be a way to coordinate the moment when the update must be considered activated.</p>
<sec>
<label>8.1</label>
<title>Coordinating an update to the verification module</title>
<p>In order to decide if and when to update to a newer version of the verification module, Hotmoka uses a technique purely based on a set of smart contracts installed in blockchain at deployment time. Namely:</p>
<list list-type="bullet">
<list-item><p>A Hotmoka blockchain publishes a non-replaceable smart contract, called the <italic>manifest</italic> of the blockchain, that knows about the current set of <italic>validators</italic>; these might coincide with the consensus validators if PoS is used, or might just be a set of accounts allowed to vote on system updates, according to some governance agreement of the network.</p></list-item>
<list-item><p>The manifest also publishes a non-replaceable <monospace>Versions</monospace> smart contract that keeps track of the current version of the verification module; this smart contract allows each validator to start a poll among all validators, whose final action is to increase the verification version.</p></list-item>
</list>
<p>The typical scenario for passing from version &#x003C4; of the verification module to version &#x003C4; &#x0002B; 1 of the same module is the following:</p>
<list list-type="order">
<list-item><p>Version &#x003C4; &#x0002B; 1 of the verification module is advertized on social channels, for instance web pages, social networks, or blogs of the blockchain communities, suggesting all nodes to update the the latest Hotmoka software that provides version &#x003C4; &#x0002B; 1 of the verification module.</p></list-item>
<list-item><p>During the update, the verification version of the blockchain, contained in the <monospace>Versions</monospace> smart contract, remains &#x003C4; and therefore the new updated nodes still keep working according to the rules of version &#x003C4;.</p></list-item>
<list-item><p>Eventually, a validator account decides that it is time to bump the verification version to &#x003C4; &#x0002B; 1 and starts a poll among all validators, that allows them to vote in favor of the switch to version &#x003C4; &#x0002B; 1.</p></list-item>
<list-item><p>The poll is an object of class <monospace>SimplePoll</monospace> (<xref ref-type="fig" rid="F3">Figure 3</xref>) whose <monospace>Voter</monospace>s are the validators of the blockchain; their power might be equal among them, or it might coincide with their stakes (in PoS) or it might be based on another governance-specific algorithm.</p></list-item>
<list-item><p>If the poll reaches its goal (that is, if enough validators voted in favor) then some validator can call method <monospace>close()</monospace> of the poll (<xref ref-type="fig" rid="F3">Figure 3</xref>), that will run an action that increases the verification version in <monospace>Versions</monospace> to &#x003C4; &#x0002B; 1.</p></list-item>
<list-item><p>From that moment, the updated nodes will see version &#x003C4; &#x0002B; 1 in the <monospace>Versions</monospace> smart contract and will use version &#x003C4; &#x0002B; 1 of their verification module to verify new code to install in the blockchain.</p></list-item>
</list>
<p>It is also possible to use a poll with a maximal duration, that allows validators to vote only inside a given time window. An implementation of such a poll is available in the library of Takamaka, but it is not discussed here further.</p>
<p><xref ref-type="fig" rid="F13">Figure 13</xref> reports the simplified code of the <monospace>Versions</monospace> smart contract. This smart contract is typically created and installed when the blockchain starts, together with the creation of the manifest. It is a class generic <italic>w.r.t</italic>. the type of the validators of the blockchain. Its creation requires to specify the manifest of the node and the current verification version. When a validator wants to propose a poll about the switch to version &#x003C4; &#x0002B; 1 of the verification module, it calls method <monospace>newIncreasePoll</monospace>, that creates a poll among the validators of the blockchain, recovered from the manifest of the blockchain. That poll, if it reaches its goal, will trigger an action that increases the verification version contained in the <monospace>Versions</monospace> object.</p>
<fig position="float" id="F13">
<label>Figure 13</label>
<caption><p>The smart contract that keeps track of the current verification version and of its updates. The complete code is available at <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/governance/Versions.java">https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/governance/Versions.java</ext-link>.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0013.tif">
<alt-text content-type="machine-generated">Java code snippet for a class called &#x0201C;Versions&#x0201D; extending &#x0201C;Contract&#x0201D; and a private class &#x0201C;IncreaseVerificationVersion.&#x0201D; The &#x0201C;Versions&#x0201D; class includes private fields, a constructor, and methods for version control. A method &#x0201C;newIncreasePoll&#x0201D; checks validator and ticket conditions before returning a new poll. The &#x0201C;IncreaseVerificationVersion&#x0201D; class extends &#x0201C;Action&#x0201D; and updates &#x0201C;verificationVersion.&#x0201D; Comments and annotations are present for guidance.</alt-text>
</graphic>
</fig>
<p>Method <monospace>newIncreasePoll</monospace> is <monospace>&#x00040;Payable</monospace>, that is, its caller must pay to call it. There is a minimal <monospace>ticketForNewPoll</monospace> that must be paid, as specified in the manifest, in order to discourage the creation of too many cheap polls, that would just add noise. This amount gets distributed to all validators, as a remuneration for their effort to vote. In any case, only validators are allowed to start a version update poll.</p>
<p>It is interesting to observe, in <xref ref-type="fig" rid="F13">Figure 13</xref>, that the <monospace>newVerificationVersion</monospace> is computed at the time of creating the action, that is, at the time of creating the new poll inside method <monospace>newIncreasePoll()</monospace>. Namely, it is not computed later, when the <monospace>run()</monospace> method of the action runs. This avoids the risk of starting <italic>n</italic> &#x0003E; 1 polls to increase the current verification versions to &#x003C4; &#x0002B; 1, possibly under request of distinct validators, without waiting for their closure, and end up increasing the verification version to &#x003C4; &#x0002B; <italic>n</italic> instead of &#x003C4; &#x0002B; 1. With the code in <xref ref-type="fig" rid="F13">Figure 13</xref>, all such polls would end up increasing the verification version to the same value &#x003C4; &#x0002B; 1, repeatedly, which is what is expected.</p>
</sec>
<sec>
<title>8.2 Deadling with code verified with legacy verification rules</title>
<p>When the verification version in the <monospace>Versions</monospace> smart contract gets updated, the smart contracts existing in blockchain at that moment will still pass the old (<italic>legacy</italic>) verification rules, but not necessarily the new rules implemented by the new verification module. Hence, there must be a mechanism that enforces that the execution of some code in blockchain occurs only if that code passes the <italic>current</italic> verification rules. Conceptually, this means that an update of the verification module triggers a re-verification of all code previously successfully installed in blockchain. In practice, this cannot be performed, since it would be extremely expensive and would hang the nodes for a long time. Hotmoka&#x00027;s solution, that we are going to describe, is to lazily re-verify the code on-demand, when it is asked to run. This amortizes the cost of re-verification. Moreover, only 0.05% of all contracts installed in Ethereum are involved in 80% of the transactions. Hence, a lazy approach avoids the re-verification of code that might actually never run again (<xref ref-type="bibr" rid="B23">Oliva et al., 2020</xref>).</p>
<p>In order to implement this lazy re-verification approach, Hotmoka expands the information in the <italic>response</italic> of a successful code installation <italic>request</italic> (<xref ref-type="fig" rid="F6">Figure 6</xref>). Namely, together with the installed code, <italic>response</italic> is enriched with a numerical tag &#x003C4;(<italic>response</italic>), i.e., the version of the verification module that has been used to verify the code inside <italic>response</italic>. The sequence diagram in <xref ref-type="fig" rid="F14">Figure 14</xref> shows the workflow for lazy code re-verification. Assume that a request arrives, that requires to run code referred with the hash <italic>request</italic><sub><italic>h</italic></sub> of a previous, successful code installation <italic>request</italic> (as in <xref ref-type="fig" rid="F6">Figures 6c</xref>, <xref ref-type="fig" rid="F6">d</xref>). The node finds out that &#x003C3;(<italic>request</italic><sub><italic>h</italic></sub>) &#x0003D; <italic>response</italic> has a verification tag &#x003C4;(<italic>response</italic>) and compares it with the current version &#x003C4; of the verification module. There are two possibilities:</p>
<list list-type="order">
<list-item><p>&#x003C4; &#x0003D; &#x003C4;(<italic>response</italic>): the code was verified with the current version of the verification module, it does not need re-verification and can be run immediately;</p></list-item>
<list-item><p>&#x003C4; &#x0003E; &#x003C4;(<italic>response</italic>): the code was verified with an old version of the verification module; it must be re-verified before being run.</p></list-item>
</list>
<fig position="float" id="F14">
<label>Figure 14</label>
<caption><p>Sequence diagram for lazy code re-verification.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fcomp-07-1596804-g0014.tif">
<alt-text content-type="machine-generated">Sequence diagram showing interactions among User, Blockchain Engine, Application Layer Interface, Request Handler, Verification, State, and Smart Contract Executor. User initiates a request, which moves through each component, performing checks, executing code, updating state, and returning responses, with consensus reached at the end.</alt-text>
</graphic>
</fig>
<p>In the second case, the node verifies the code again, using the current version &#x003C4; of the verification module. This is possible since <italic>response</italic> includes that code (<xref ref-type="fig" rid="F6">Figure 6a</xref>). A new response <italic>response</italic>&#x02032; will be computed (it could be a successful response, having &#x003C4; as verification module version, or a failed response) and the application state is updated as <inline-formula><mml:math id="M2"><mml:mi>&#x003C3;</mml:mi><mml:mrow><mml:mo stretchy="false">(</mml:mo><mml:mrow><mml:msub><mml:mrow><mml:mstyle mathvariant="italic"><mml:mi>r</mml:mi><mml:mi>e</mml:mi><mml:mi>q</mml:mi><mml:mi>u</mml:mi><mml:mi>e</mml:mi><mml:mi>s</mml:mi><mml:mi>t</mml:mi></mml:mstyle></mml:mrow><mml:mrow><mml:mi>h</mml:mi></mml:mrow></mml:msub></mml:mrow><mml:mo stretchy="false">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:msup><mml:mrow><mml:mstyle mathvariant="italic"><mml:mi>r</mml:mi><mml:mi>e</mml:mi><mml:mi>s</mml:mi><mml:mi>p</mml:mi><mml:mi>o</mml:mi><mml:mi>n</mml:mi><mml:mi>s</mml:mi><mml:mi>e</mml:mi></mml:mstyle></mml:mrow><mml:mrow><mml:mi>&#x02032;</mml:mi></mml:mrow></mml:msup></mml:math></inline-formula>. The use of <italic>request</italic><sub><italic>h</italic></sub> in future requests will not re-verify the code anymore, at least not until a yet newer version of the verification module is installed. Note that the update of the response is possible since it occurs in the state, not in the blockchain, whose blocks are immutable.</p>
<p>It is important to note that <italic>response</italic>&#x02032; might state that reverification failed, because the old code passed the previous verification rules but not the new ones. In that case, the execution of the code will fail, since its classpath is not valid anymore. This means that a smart contract might work today, but might stop working tomorrow, if updated verification rules reject its code. In theory, the converse is also possible: the same contract might be reactivated after tomorrow, if another change in the verification rules replaces a failed response with a successful response. However, Hotmoka currently forbids this second scenario, since it might be surprising to most users.</p>
</sec>
</sec>
<sec sec-type="conclusions" id="s9">
<label>9</label>
<title>Conclusion</title>
<p>To the best of our knowledge, this paper presents the first protocol-based verification of blockchain code. The technique is fully implemented inside the Hotmoka runtime for executing smart contracts written in the Takamaka subset of Java. Experiments show that the addition of a code verification layer to the nodes of a blockchain network does not affect its efficiency (Section 7). However, this is true also because the static analyses performed by the verification module of Hotmoka are still quite simple and largely related to checking the correct use of the annotations and primitives of the Takamaka language (<xref ref-type="fig" rid="F7">Figure 7</xref>). The cost of verification might explode, instead, if more complicated static analyses would be considered in the future, such as those already existing for Java.</p>
<p>In comparison with off-chain static analysis, the following considerations are relevant:</p>
<list list-type="bullet">
<list-item><p>An off-chain static analyzer can afford a large execution time, while a protocol-based static analysis must be quick or otherwise it might not terminate in time for the creation of the next block or it might not work timely on the least powerful nodes of the network.</p></list-item>
<list-item><p>An off-chain static analyzer might even afford to diverge and never provide an answer, while, at the protocol level, that would mean that the whole blockchain network would hang, a disaster that must be avoided.</p></list-item>
<list-item><p>An off-chain static analyzer may contain bugs that lead to an undesirable but not disastrous crash; instead, protocol-based analysis should not crash or otherwise all (or most) nodes of the network might stop working.</p></list-item>
<list-item><p>An off-chain static analyzer can afford non-deterministic results, typically due to optimizations such as parallel executions or time-outs; the same cannot be accepted for protocol-based static analysis, since non-deterministic results make it impossible for the network to reach a consensus.</p></list-item>
</list>
<p>Such considerations imply that protocol-based and off-chain static analyses could actually coexist since they address different goals: the former checks the correct use of the language primitives that, if violated, would introduce security holes in the blockchain network itself; while the latter verifies more complicated, global properties of the code, that would not introduce security risks to the network but might be of paramount importance to the programmer. That is, protocol-based verification must be understood as a mandatory, defensive verification technique <italic>for the blockchain</italic>, rather than as a replacement of the off-chain verification that is useful <italic>for the programmer</italic>.</p>
<p>The issue of reverification of legacy code after an update of the verification module has not been studied much up to now. In Section 8.2, it is said that it should trigger the re-verification of code already in blockchain. But this might not be the best choice, since it might disable some smart contracts already in blockchain and lock their funds for ever. Moreover, a large number of users could oppose a change of the verification rules that affects some highly popular contracts. Future work will investigate linguistic primitives and programming patterns that allow funds to be unlocked or specify that some contract should <italic>not</italic> be re-verified after an update of the verification module.</p>
<p>Protocol-based verification has been developed to support the safe use of general-purpose languages in a permissionless blockchain. As such, its applicability is much larger than the case of Java, and spans all general-purpose languages used so far for writing smart contracts (Golang, Python, and Rust, for instance). Its application to Solidity remains limited, since Solidity was meant for writing smart contracts, from its very inception, therefore most of our checks are already performed by the Solidity compiler. Nevertheless, it is possible, in principle, to modify the Ethereum Virtual Machine and trigger code verification of every Solidity smart contract deployed in Ethereum. This would be perfectly possible for simple checks (for instance, for the use of <monospace>msg.sender</monospace> instead of <monospace>tx.origin</monospace> or for unexpected and non-standard uses of <monospace>delegatecall()</monospace>) while we remain skeptical about protocol-based verification of more complicated security issues, such as overflows, underflows and reentrancy, whose computational cost is quite higher. For reentrancy, a more syntactical approach, such as making the default payment method <monospace>final</monospace>, as done in Takamaka, catches most attacks in a much simpler way than a static analysis.</p>
</sec>
</body>
<back>
<sec sec-type="data-availability" id="s10">
<title>Data availability statement</title>
<p>Publicly available datasets were analyzed in this study. This data can be found here: <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/hotmoka">https://github.com/Hotmoka/hotmoka</ext-link>.</p>
</sec>
<sec sec-type="author-contributions" id="s11">
<title>Author contributions</title>
<p>LO: Data curation, Validation, Writing &#x02013; original draft, Writing &#x02013; review &#x00026; editing. FS: Conceptualization, Data curation, Software, Supervision, Writing &#x02013; original draft, Writing &#x02013; review &#x00026; editing. FT: Data curation, Validation, Writing &#x02013; original draft, Writing &#x02013; review &#x00026; editing.</p>
</sec>
<sec sec-type="COI-statement" id="conf1">
<title>Conflict of interest</title>
<p>FT was employed by Equixly Srl. The remaining authors declare that the research was conducted in the absence of any commercial or financial relationships that could be construed as a potential conflict of interest.</p>
</sec>
<sec sec-type="ai-statement" id="s13">
<title>Generative AI statement</title>
<p>The author(s) declare that no Gen AI was used in the creation of this manuscript.</p>
<p>Any alternative text (alt text) provided alongside figures in this article has been generated by Frontiers with the support of artificial intelligence and reasonable efforts have been made to ensure accuracy, including review by the authors wherever possible. If you identify any issues, please contact us.</p>
</sec>
<sec sec-type="disclaimer" id="s14">
<title>Publisher&#x00027;s note</title>
<p>All claims expressed in this article are solely those of the authors and do not necessarily represent those of their affiliated organizations, or those of the publisher, the editors and the reviewers. Any product that may be evaluated in this article, or claim that may be made by its manufacturer, is not guaranteed or endorsed by the publisher.</p>
</sec>
<ref-list>
<title>References</title>
<ref id="B1">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Abusalah</surname> <given-names>H.</given-names></name> <name><surname>Alwen</surname> <given-names>J.</given-names></name> <name><surname>Cohen</surname> <given-names>B.</given-names></name> <name><surname>Khilko</surname> <given-names>D.</given-names></name> <name><surname>Pietrzak</surname> <given-names>K.</given-names></name> <name><surname>Reyzin</surname> <given-names>L.</given-names></name></person-group> (<year>2017</year>). <article-title>&#x0201C;Beyond hellman&#x00027;s time-memory trade-offs with applications to proofs of space,&#x0201D;</article-title> in <source>Proceedings of Advances in Cryptology, the 23rd International Conference on the Theory and Applications of Cryptology and Information Security (ASIACRYPT&#x00027;17), part II</source>, eds. T. Takagi, and T. Peyrin (Hong Kong, China: Springer), <fpage>357</fpage>&#x02013;<lpage>379</lpage>. doi: <pub-id pub-id-type="doi">10.1007/978-3-319-70697-9_13</pub-id></mixed-citation>
</ref>
<ref id="B2">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Antonopoulos</surname> <given-names>A. M.</given-names></name></person-group> (<year>2017</year>). <source>Mastering Bitcoin: Unlocking Digital Cryptocurrencies</source>. <publisher-loc>New York</publisher-loc>: <publisher-name>O&#x00027;Reilly, 2nd edition</publisher-name>.</mixed-citation>
</ref>
<ref id="B3">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Antonopoulos</surname> <given-names>A. M.</given-names></name> <name><surname>Wood</surname> <given-names>G.</given-names></name></person-group> (<year>2018</year>). <source>Mastering Ethereum: Building Smart Contracts and Dapps</source>. <publisher-loc>New York</publisher-loc>: <publisher-name>O&#x00027;Reilly</publisher-name>.</mixed-citation>
</ref>
<ref id="B4">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Arceri</surname> <given-names>V.</given-names></name> <name><surname>Merenda</surname> <given-names>S. M.</given-names></name> <name><surname>Dolcetti</surname> <given-names>G.</given-names></name> <name><surname>Negrini</surname> <given-names>L.</given-names></name> <name><surname>Olivieri</surname> <given-names>L.</given-names></name> <name><surname>Zaffanella</surname> <given-names>E.</given-names></name></person-group> (<year>2024</year>). <article-title>&#x0201C;Towards a sound construction of EVM bytecode control-flow graphs,&#x0201D;</article-title> in <source>Proceedings of the 26th ACM International Workshop on Formal Techniques for Java-like Programs, FTfJP 2024</source> (<publisher-loc>New York, NY, USA</publisher-loc>: <publisher-name>Association for Computing Machinery</publisher-name>), <fpage>11</fpage>&#x02013;<lpage>16</lpage>. doi: <pub-id pub-id-type="doi">10.1145/3678721.3686227</pub-id></mixed-citation>
</ref>
<ref id="B5">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Ateniese</surname> <given-names>G.</given-names></name> <name><surname>Bonacina</surname> <given-names>I.</given-names></name> <name><surname>Faonio</surname> <given-names>A.</given-names></name> <name><surname>Galesi</surname> <given-names>N.</given-names></name></person-group> (<year>2014</year>). <article-title>&#x0201C;Proofs of space: when space is of the essence,&#x0201D;</article-title> in <source>Proceedings of the 9th International Conference on Security and Cryptography for Networks (SCN&#x00027;14)</source>, eds. M. Abdalla, and R. De Prisco (Amalfi, Italy: Springer), <fpage>538</fpage>&#x02013;<lpage>557</lpage>. doi: <pub-id pub-id-type="doi">10.1007/978-3-319-10879-7_31</pub-id></mixed-citation>
</ref>
<ref id="B6">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Atzei</surname> <given-names>N.</given-names></name> <name><surname>Bartoletti</surname> <given-names>M.</given-names></name> <name><surname>Cimoli</surname> <given-names>T.</given-names></name></person-group> (<year>2017</year>). <article-title>&#x0201C;A survey of attacks on ethereum smart contracts (SoK),&#x0201D;</article-title> in <source>6th International Conference on Principles of Security and Trust (POST&#x00027;17)</source> (<publisher-loc>Uppsala, Sweden</publisher-loc>: <publisher-name>Springer</publisher-name>), <fpage>164</fpage>&#x02013;<lpage>186</lpage>. doi: <pub-id pub-id-type="doi">10.1007/978-3-662-54455-6_8</pub-id></mixed-citation>
</ref>
<ref id="B7">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Bagnara</surname> <given-names>R.</given-names></name> <name><surname>Hill</surname> <given-names>P. M.</given-names></name> <name><surname>Zaffanella</surname> <given-names>E.</given-names></name></person-group> (<year>2008</year>). <article-title>The parma polyhedra library: toward a complete set of numerical abstractions for the analysis and verification of hardware and software systems</article-title>. <source>Sci. Comput. Progr</source>. <volume>72</volume>, <fpage>3</fpage>&#x02013;<lpage>21</lpage>. doi: <pub-id pub-id-type="doi">10.1016/j.scico.2007.08.001</pub-id></mixed-citation>
</ref>
<ref id="B8">
<mixed-citation publication-type="web"><person-group person-group-type="author"><name><surname>Buterin</surname> <given-names>V.</given-names></name></person-group> (<year>2013</year>). <source>Ethereum Whitepaper</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://ethereum.org/en/whitepaper/">https://ethereum.org/en/whitepaper/</ext-link> (Accessed March 9, 2025).</mixed-citation>
</ref>
<ref id="B9">
<mixed-citation publication-type="web"><person-group person-group-type="author"><collab>Certik</collab></person-group> (<year>2025</year>). Certik. Available online at: <ext-link ext-link-type="uri" xlink:href="https://www.certik.com/">https://www.certik.com/</ext-link> (Accessed August, 2025).</mixed-citation>
</ref>
<ref id="B10">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Chen</surname> <given-names>J.</given-names></name> <name><surname>Micali</surname> <given-names>S.</given-names></name></person-group> (<year>2019</year>). <article-title>Algorand: a secure and efficient distributed ledger</article-title>. <source>Theor. Comput. Sci</source>. <volume>777</volume>, <fpage>155</fpage>&#x02013;<lpage>183</lpage>. doi: <pub-id pub-id-type="doi">10.1016/j.tcs.2019.02.001</pub-id></mixed-citation>
</ref>
<ref id="B11">
<mixed-citation publication-type="web"><person-group person-group-type="author"><collab>Consensys Diligence</collab></person-group> (<year>2025</year>). <source>Blockchain Security &#x00026;Ethereum Smart Contract Audits</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://diligence.consensys.io/">https://diligence.consensys.io/</ext-link> (Accessed August, 2025).</mixed-citation>
</ref>
<ref id="B12">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Crosara</surname> <given-names>M.</given-names></name> <name><surname>Olivieri</surname> <given-names>L.</given-names></name> <name><surname>Spoto</surname> <given-names>F.</given-names></name> <name><surname>Tagliaferro</surname> <given-names>F.</given-names></name></person-group> (<year>2023</year>). <article-title>Fungible and non-fungible tokens with snapshots in java</article-title>. <source>Cluster Comput</source>. <volume>26</volume>, <fpage>2701</fpage>&#x02013;<lpage>2718</lpage>. doi: <pub-id pub-id-type="doi">10.1007/s10586-022-03756-3</pub-id></mixed-citation>
</ref>
<ref id="B13">
<mixed-citation publication-type="web"><person-group person-group-type="author"><name><surname>Dua</surname> <given-names>R.</given-names></name></person-group> (<year>2025</year>). <source>Ethlint &#x02013; Documentation</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://ethlint.readthedocs.io/en/latest/">https://ethlint.readthedocs.io/en/latest/</ext-link> (Accessed March 2025).</mixed-citation>
</ref>
<ref id="B14">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Dziembowski</surname> <given-names>S.</given-names></name> <name><surname>Faust</surname> <given-names>S.</given-names></name> <name><surname>Kolmogorov</surname> <given-names>V.</given-names></name> <name><surname>Pietrzak</surname> <given-names>K.</given-names></name></person-group> (<year>2015</year>). <article-title>&#x0201C;Proofs of space,&#x0201D;</article-title> in <source>Proceedings of Advances in Cryptology (CRYPTO 2015)</source> - <italic>35th Annual Cryptology Conference, part II</italic>, eds. R. Gennaro, and M. Robshaw (Santa Barbara, CA, USA: Springer), <fpage>585</fpage>&#x02013;<lpage>605</lpage>. doi: <pub-id pub-id-type="doi">10.1007/978-3-662-48000-7_29</pub-id></mixed-citation>
</ref>
<ref id="B15">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Feist</surname> <given-names>J.</given-names></name> <name><surname>Grieco</surname> <given-names>G.</given-names></name> <name><surname>Groce</surname> <given-names>A.</given-names></name></person-group> (<year>2019</year>). <article-title>&#x0201C;Slither: a static analysis framework for smart contracts,&#x0201D;</article-title> in <source>2nd International Workshop on Emerging Trends in Software Engineering for Blockchain (WETSEB&#x00040;ICSE&#x00027;19)</source> (<publisher-loc>Montreal, QC, Canada</publisher-loc>: <publisher-name>IEEE/ACM</publisher-name>), <fpage>8</fpage>&#x02013;<lpage>15</lpage>. doi: <pub-id pub-id-type="doi">10.1109/WETSEB.2019.00008</pub-id></mixed-citation>
</ref>
<ref id="B16">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Grieco</surname> <given-names>G.</given-names></name> <name><surname>Song</surname> <given-names>W.</given-names></name> <name><surname>Cygan</surname> <given-names>A.</given-names></name> <name><surname>Feist</surname> <given-names>J.</given-names></name> <name><surname>Groce</surname> <given-names>A.</given-names></name></person-group> (<year>2020</year>). <article-title>&#x0201C;Echidna: effective, usable, and fast fuzzing for smart contracts,&#x0201D;</article-title> in <source>29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA&#x00027;20)</source> (<publisher-loc>USA</publisher-loc>: <publisher-name>ACM</publisher-name>), <fpage>557</fpage>&#x02013;<lpage>560</lpage>. doi: <pub-id pub-id-type="doi">10.1145/3395363.3404366</pub-id></mixed-citation>
</ref>
<ref id="B17">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Hejazi</surname> <given-names>N.</given-names></name> <name><surname>Lashkari</surname> <given-names>A. H.</given-names></name></person-group> (<year>2025</year>). <article-title>A comprehensive survey of smart contracts vulnerability detection tools: techniques and methodologies</article-title>. <source>J. Netw. Comput. Applic</source>. <volume>237</volume>:<fpage>104142</fpage>. doi: <pub-id pub-id-type="doi">10.1016/j.jnca.2025.104142</pub-id></mixed-citation>
</ref>
<ref id="B18">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Kushwaha</surname> <given-names>S. S.</given-names></name> <name><surname>Joshi</surname> <given-names>S.</given-names></name> <name><surname>Singh</surname> <given-names>D.</given-names></name> <name><surname>Kaur</surname> <given-names>M.</given-names></name> <name><surname>Lee</surname> <given-names>H.-N.</given-names></name></person-group> (<year>2022</year>). <article-title>Ethereum smart contract analysis tools: a systematic review</article-title>. <source>IEEE Access</source> <volume>10</volume>, <fpage>57037</fpage>&#x02013;<lpage>57062</lpage>. doi: <pub-id pub-id-type="doi">10.1109/ACCESS.2022.3169902</pub-id></mixed-citation>
</ref>
<ref id="B19">
<mixed-citation publication-type="web"><person-group person-group-type="author"><name><surname>Kwon</surname> <given-names>J.</given-names></name></person-group> (<year>2014</year>). <source>Tendermint: Consensus without Mining</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://www.weusecoins.com/assets/pdf/library/Tendermint%20Consensus%20without%20Mining.pdf">https://www.weusecoins.com/assets/pdf/library/Tendermint%20Consensus%20without%20Mining.pdf</ext-link> (Accessed August 26, 2024).</mixed-citation>
</ref>
<ref id="B20">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Loi</surname> <given-names>L.</given-names></name> <name><surname>Duc-Hiep</surname> <given-names>C.</given-names></name> <name><surname>Hrishi</surname> <given-names>O.</given-names></name> <name><surname>Prateek</surname> <given-names>S.</given-names></name> <name><surname>Aquinas</surname> <given-names>H.</given-names></name></person-group> (<year>2016</year>). <article-title>&#x0201C;Making smart contracts smarter,&#x0201D;</article-title> in Weippl, E. R., Katzenbeisser, S., Kruegel, C., Myers, A. C., and Halevi, S., editors, <italic>Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security, Vienna, Austria, October 24-28, 2016</italic> (ACM), <fpage>254</fpage>&#x02013;<lpage>269</lpage>. doi: <pub-id pub-id-type="doi">10.1145/2976749.2978309</pub-id></mixed-citation>
</ref>
<ref id="B21">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Naftalin</surname> <given-names>M.</given-names></name> <name><surname>Wadler</surname> <given-names>P.</given-names></name></person-group> (<year>2006</year>). <source>Java Generics and Collections: Speed Up the Java Development Process</source>. <publisher-loc>New York</publisher-loc>: <publisher-name>O&#x00027;Reilly</publisher-name>.</mixed-citation>
</ref>
<ref id="B22">
<mixed-citation publication-type="web"><person-group person-group-type="author"><name><surname>Nakamoto</surname> <given-names>S.</given-names></name></person-group> (<year>2008</year>). <source>Bitcoin: A Peer-to-Peer Electronic Cash System</source>. Available at <ext-link ext-link-type="uri" xlink:href="https://bitcoin.org/bitcoin.pdf">https://bitcoin.org/bitcoin.pdf</ext-link> (Accessed August 24, 2025).<pub-id pub-id-type="pmid">34691875</pub-id></mixed-citation></ref>
<ref id="B23">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Oliva</surname> <given-names>G. A.</given-names></name> <name><surname>Hassan</surname> <given-names>A. E.</given-names></name> <name><surname>Jiang</surname> <given-names>Z. M.</given-names></name></person-group> (<year>2020</year>). <article-title>An exploratory study of smart contracts in the ethereum blockchain platform</article-title>. <source>Empir. Softw. Eng</source>. <volume>25</volume>, <fpage>1864</fpage>&#x02013;<lpage>1904</lpage>. doi: <pub-id pub-id-type="doi">10.1007/s10664-019-09796-5</pub-id></mixed-citation>
</ref>
<ref id="B24">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Olivieri</surname> <given-names>L.</given-names></name> <name><surname>Spoto</surname> <given-names>F.</given-names></name> <name><surname>Tagliaferro</surname> <given-names>F.</given-names></name></person-group> (<year>2021</year>). <article-title>&#x0201C;On-chain smart contract verification over tendermint,&#x0201D;</article-title> in <source>Financial Cryptography and Data Security. FC 2021 International Workshops</source>, eds. M. Bernhard, A. Bracciali, L. Gudgeon, T. Haines, A. Klages-Mundt, S. Matsuo, et al. (Berlin, Heidelberg: Springer), <fpage>333</fpage>&#x02013;<lpage>347</lpage>. doi: <pub-id pub-id-type="doi">10.1007/978-3-662-63958-0_28</pub-id></mixed-citation>
</ref>
<ref id="B25">
<mixed-citation publication-type="web"><person-group person-group-type="author"><collab>OpenZeppelin</collab></person-group> (<year>2025</year>). <source>The OpenZeppelin Security Audit</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://www.openzeppelin.com/security-audits">https://www.openzeppelin.com/security-audits</ext-link> (Accessed August 2025).</mixed-citation>
</ref>
<ref id="B26">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Pasqua</surname> <given-names>M.</given-names></name> <name><surname>Benini</surname> <given-names>A.</given-names></name> <name><surname>Contro</surname> <given-names>F.</given-names></name> <name><surname>Crosara</surname> <given-names>M.</given-names></name> <name><surname>Dalla Preda</surname> <given-names>M.</given-names></name> <name><surname>Ceccato</surname> <given-names>M.</given-names></name></person-group> (<year>2023</year>). <article-title>Enhancing ethereum smart-contracts static analysis by computing a precise control-flow graph of ethereum bytecode</article-title>. <source>J. Syst. Softw</source>. <volume>200</volume>:<fpage>111653</fpage>. doi: <pub-id pub-id-type="doi">10.1016/j.jss.2023.111653</pub-id></mixed-citation>
</ref>
<ref id="B27">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Popper</surname> <given-names>N.</given-names></name></person-group> (<year>2016</year>). <source>A Hacking of More than</source> $<italic>50 Million Dashes Hopes in the World of Virtual Currency</italic>. The New York Times, 2016-06-18.</mixed-citation>
</ref>
<ref id="B28">
<mixed-citation publication-type="web"><person-group person-group-type="author"><collab>Protofire</collab></person-group> (<year>2025</year>). <source>Solhint - Official Website</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://protofire.io/projects/solhint">https://protofire.io/projects/solhint</ext-link> (Accessed March 2025).</mixed-citation>
</ref>
<ref id="B29">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Ressi</surname> <given-names>D.</given-names></name> <name><surname>Span&#x000F2;</surname> <given-names>A.</given-names></name> <name><surname>Benetollo</surname> <given-names>L.</given-names></name> <name><surname>Piazza</surname> <given-names>C.</given-names></name> <name><surname>Bugliesi</surname> <given-names>M.</given-names></name> <name><surname>Rossi</surname> <given-names>S.</given-names></name></person-group> (<year>2024</year>). <article-title>Vulnerability detection in ethereum smart contracts via machine learning: a qualitative analysis</article-title>. <source>arXiv preprint arXiv:2407.18639</source>.</mixed-citation>
</ref>
<ref id="B30">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Schneidewind</surname> <given-names>C.</given-names></name> <name><surname>Grishchenko</surname> <given-names>I.</given-names></name> <name><surname>Scherer</surname> <given-names>M.</given-names></name> <name><surname>Maffei</surname> <given-names>M.</given-names></name></person-group> (<year>2020</year>). <article-title>&#x0201C;eThor: practical and provably sound static analysis of ethereum smart contracts,&#x0201D;</article-title> in <source>Proceedings of the 2020 ACM SIGSAC Conference on Computer and Communications Security, CCS &#x00027;20</source> (<publisher-loc>New York, NY, USA</publisher-loc>: <publisher-name>Association for Computing Machinery</publisher-name>), <fpage>621</fpage>&#x02013;<lpage>640</lpage>. doi: <pub-id pub-id-type="doi">10.1145/3372297.3417250</pub-id></mixed-citation>
</ref>
<ref id="B31">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Sedlmeir</surname> <given-names>J.</given-names></name> <name><surname>Buhl</surname> <given-names>H. U.</given-names></name> <name><surname>Fridgen</surname> <given-names>G.</given-names></name> <name><surname>Keller</surname> <given-names>R.</given-names></name></person-group> (<year>2020</year>). <article-title>The energy consumption of blockchain technology: beyond myth</article-title>. <source>Bus. Inf. Syst. Eng</source>. <volume>62</volume>, <fpage>599</fpage>&#x02013;<lpage>608</lpage>. doi: <pub-id pub-id-type="doi">10.1007/s12599-020-00656-x</pub-id></mixed-citation>
</ref>
<ref id="B32">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Spoto</surname> <given-names>F.</given-names></name></person-group> (<year>2019</year>). <article-title>&#x0201C;A java framework for smart contracts,&#x0201D;</article-title> in <source>3rd Workshop on Trusted Smart Contracts (WTSC&#x00027;19)</source> (<publisher-loc>St. Kitts and Nevis</publisher-loc>: <publisher-name>Springer</publisher-name>), <fpage>122</fpage>&#x02013;<lpage>137</lpage>. doi: <pub-id pub-id-type="doi">10.1007/978-3-030-43725-1_10</pub-id></mixed-citation>
</ref>
<ref id="B33">
<mixed-citation publication-type="book"><person-group person-group-type="author"><name><surname>Spoto</surname> <given-names>F.</given-names></name></person-group> (<year>2025</year>). <article-title>&#x0201C;A formalization of signum&#x00027;s consensus,&#x0201D;</article-title> in <source>9th Workshop on Trusted Smart Contracts (WTSC&#x00027;25), Lecture Notes in Computer Science, Miyakojima, Japan</source> (<publisher-loc>Springer</publisher-loc>).</mixed-citation>
</ref>
<ref id="B34">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Spoto</surname> <given-names>F.</given-names></name> <name><surname>Migliorini</surname> <given-names>S.</given-names></name> <name><surname>Gambini</surname> <given-names>M.</given-names></name> <name><surname>Benini</surname> <given-names>A.</given-names></name></person-group> (<year>2023</year>). <article-title>On the use of generic types for smart contracts</article-title>. <source>Cluster Comput</source>. <volume>26</volume>, <fpage>2099</fpage>&#x02013;<lpage>2113</lpage>. doi: <pub-id pub-id-type="doi">10.1007/s10586-022-03688-y</pub-id></mixed-citation>
</ref>
<ref id="B35">
<mixed-citation publication-type="journal"><person-group person-group-type="author"><name><surname>Tikhomirov</surname> <given-names>S.</given-names></name> <name><surname>Voskresenskaya</surname> <given-names>E.</given-names></name> <name><surname>Ivanitskiy</surname> <given-names>I.</given-names></name> <name><surname>Takhaviev</surname> <given-names>R.</given-names></name> <name><surname>Marchenko</surname> <given-names>E.</given-names></name> <name><surname>Alexandrov</surname> <given-names>Y.</given-names></name></person-group> (<year>2018</year>). <article-title>&#x0201C;SmartCheck: static analysis of ethereum smart contracts,&#x0201D;</article-title> in <source>2018 IEEE/ACM 1st International Workshop on Emerging Trends in Software Engineering for Blockchain (WETSEB)</source>, 9&#x02013;16. doi: <pub-id pub-id-type="doi">10.1145/3194113.3194115</pub-id></mixed-citation>
</ref>
</ref-list>
<fn-group>
<fn fn-type="custom" custom-type="edited-by" id="fn00013">
<p>Edited by: <ext-link ext-link-type="uri" xlink:href="https://loop.frontiersin.org/people/2889070/overview">Novarun Deb</ext-link>, University of Calgary, Canada</p>
</fn>
<fn fn-type="custom" custom-type="reviewed-by" id="fn00014">
<p>Reviewed by: <ext-link ext-link-type="uri" xlink:href="https://loop.frontiersin.org/people/277112/overview">John Anthony Rose</ext-link>, Ritsumeikan Asia Pacific University, Japan; <ext-link ext-link-type="uri" xlink:href="https://loop.frontiersin.org/people/613695/overview">Giuseppe Antonio Pierro</ext-link>, University of Cagliari, Italy</p>
</fn>
<fn id="fn0001"><label>1</label><p><ext-link ext-link-type="uri" xlink:href="https://docs.ignite.com/welcome">https://docs.ignite.com/welcome</ext-link> (Accessed June, 2025).</p></fn>
<fn id="fn0002"><label>2</label><p><ext-link ext-link-type="uri" xlink:href="https://docs.cometbft.com/v1.0/">https://docs.cometbft.com/v1.0/</ext-link> (Accessed June, 2025).</p></fn>
<fn id="fn0003"><label>3</label><p><ext-link ext-link-type="uri" xlink:href="https://github.com/Mokamint-chain/mokamint">https://github.com/Mokamint-chain/mokamint</ext-link></p></fn>
<fn id="fn0004"><label>4</label><p><ext-link ext-link-type="uri" xlink:href="https://www.chia.net">https://www.chia.net</ext-link></p></fn>
<fn id="fn0005"><label>5</label><p><ext-link ext-link-type="uri" xlink:href="https://wiki.signum.network">https://wiki.signum.network</ext-link></p></fn>
<fn id="fn0006"><label>6</label><p>Total value locked in the blockchains: &#x0007E;50% Ethereum (main-net),&#x0007E;8% Solana, &#x0007E;6% Bitcoin, &#x0007E;6% BSC (Ethereum-based), &#x0007E;5%Tron (Ethereum-based), &#x0007E;25% others [<ext-link ext-link-type="uri" xlink:href="https://defillama.com/chains">https://defillama.com/chains</ext-link>, Accessed March, 2025].</p></fn>
<fn id="fn0007"><label>7</label><p><ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/hotmoka">https://github.com/Hotmoka/hotmoka</ext-link></p></fn>
<fn id="fn0008"><label>8</label><p><ext-link ext-link-type="uri" xlink:href="https://github.com/JetBrains/xodus">https://github.com/JetBrains/xodus</ext-link></p></fn>
<fn id="fn0009"><label>9</label><p>See <ext-link ext-link-type="uri" xlink:href="https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/lang/ExternallyOwnedAccount.java">https://github.com/Hotmoka/io-takamaka-code/blob/main/io-takamaka-code/src/main/java/io/takamaka/code/lang/ExternallyOwnedAccount.java</ext-link>.</p></fn>
<fn id="fn0010"><label>10</label><p><ext-link ext-link-type="uri" xlink:href="https://commons.apache.org/proper/commons-bcel">https://commons.apache.org/proper/commons-bcel</ext-link></p></fn>
<fn id="fn0011"><label>11</label><p>If <monospace>class</monospace> is not specified, then Takamaka assumes the default class <monospace>Contract</monospace> for it.</p></fn>
<fn id="fn0012"><label>12</label><p>This option is available for testing, but a real Hotmoka blockchain would never be installed without code verification and code verification cannot be turned off after a blockchain has been started.</p></fn>
</fn-group>
</back>
</article>