{'fraction_non_alphanumeric': 0.02670274787591778, 'fraction_numerical': 0.007859601647531687, 'mean_word_length': 5.035547015731956, 'pattern_counts': {'":': 0, '<': 1, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Specification is Law: Safe Creation and Upgrade of Ethereum Smart Contracts

Smart contracts are the building blocks of the"code is law"paradigm: the smart contract's code indisputably describes how its assets are to be managed - once it is created, its code is typically immutable. Faulty smart contracts present the most significant evidence against the practicality of this paradigm; they are well-documented and resulted in assets worth vast sums of money being compromised. To address this issue, the Ethereum community proposed (i) tools and processes to audit/analyse smart contracts, and (ii) design patterns implementing a mechanism to make contract code mutable. Individually, (i) and (ii) only partially address the challenges raised by the"code is law"paradigm. In this paper, we combine elements from (i) and (ii) to create a systematic framework that moves away from"code is law"and gives rise to a new"specification is law"paradigm. It allows contracts to be created and upgraded but only if they meet a corresponding formal specification. The framework is centered around \emph{a trusted deployer}: an off-chain service that formally verifies and enforces this notion of conformance. We have prototyped this framework, and investigated its applicability to contracts implementing two widely used Ethereum standards: the ERC20 Token Standard and ERC1155 Multi Token Standard, with promising results.


Introduction
A smart contract is a stateful reactive program that is stored in and processed by a trusted platform, typically a blockchain, which securely executes such a program and safely stores its persistent state. Smart contracts were created to provide an unambiguous, automated, and secure way to manage digital assets. They are the building blocks of the "code is law" paradigm, indisputably describing how their assets are to be managed. To implement this paradigm, many smart contract platforms -including Ethereum, the platform we focus on -disallow the code of a contract to be changed once deployed, effectively enforcing a notion of code/implementation immutability.
Implementation immutability, however, has two main drawbacks. Firstly, contracts cannot be patched if the implementation is found to be incorrect after being deployed. There are many examples of real-world contract instances with flaws that have been exploited with astonishing sums of cryptocurrencies being taken over [37,44,8]. The ever-increasing valuation of these assets presents a significant long-standing incentive to perpetrators of such attacks. Secondly, contracts cannot be optimised. The execution of a contract function has an explicit cost to be paid by the caller that is calculated based on the contract's implementation. Platform participants would, then, benefit from contracts being updated to a functionally-equivalent but more cost-effective implementation, which is disallowed by this sort of code immutability.
To overcome this limitation, the Ethereum community has adopted the proxy pattern [38] as a mechanism by which one can mimic contract upgrades. The simple application of this pattern, however, presents a number of potential issues. Firstly, the use of this mechanism allows for the patching of smart contracts but it does not address the fundamental underlying problem of correctness. Once an issue is detected, it can be patched but (i) it may be too late, and (ii) what if the patch is faulty too? Secondly, it typically gives an, arguably, unreasonable amount of power to the maintainers of this contract. These special contract users can change the contract's code with little oversight. The main flaw of such an approach is, arguably, the fact that no guarantees are enforced by this updating process; the contract implementations can change rather arbitrarily as long as the right participants have approved the change. In such a context, the "code is law" paradigm is in fact nonexistent.
To address these issues, we propose a systematic deployment framework that requires contracts to be formally verified before they are created and upgraded; we target the Ethereum platform and smart contracts written in Solidity. We propose a verification framework based on the design-by-contract methodology [28]. The specification format that we propose is similar to what the community has used, albeit in an informal way, to specify the behaviour of common Ethereum contracts [43]. Our framework also relies on our own version of the proxy pattern to carry out updates but in a sophisticated and safe way. We rely on a trusted deployer, which is an off-chain service, to vet contract creations and updates. These operations are only allowed if the given implementation meets the expected specification -the contract specification is set at the time of contract creation and remains unchanged during its lifetime. As an off-chain service, our framework can be readily and efficiently integrated into existing blockchain platforms, but the same is not true of an on-chain implementation; we elaborate on this trade-off in Section 3. Participants can also check whether a contract has been deployed via our framework so that they can be certain the contract they want to execute has the expected behaviour.
Our framework promotes a paradigm shift where the specification is immutable instead of the implementation/code. Thus, it moves away from "code is law" and proposes the "specification is law" paradigm -enforced by formal verification. This new paradigm addresses all the concerns that we have highlighted: arbitrary code updates are forbidden as only conforming implementations are allowed, and buggy contracts are prevented from being deployed as they are vetted by a formal verifier. Thus, contracts can be optimised and changed to meet evolving business needs and yet contract stakeholders can rely on the guarantee that the implementations always conform to their corresponding specifications. As specifications are more stable and a necessary element for assessing the correctness of a contract, we believe that a framework that focuses on this key artifact and makes it immutable improves on the current "code is law" paradigm. We further discuss the benefits of this paradigm shift in Section 6.
We have created a prototype of our framework, and conducted a case study that investigates its applicability to real-world smart contracts implementing the widely used ERC20 and ERC1155 Ethereum token standards [43,34]. We analysed specifically how the sort of formal verification that we use fares in handling practical contracts and obtained promising results.
In this paper, we assume the deployer is a trusted third party and focus on the functional aspect of our framework. We are currently working on an implementation of the trusted deployer that relies on a Trusted Execution Environment (TEE) [27], specifically the AMD SEV implementation [36]. Outline. Section 2 introduces the relevant background material. Section 3 introduces our framework, and Section 4 the evaluation that we conducted. Section 5 discusses related work, whereas Section 6 presents our concluding remarks.

Ethereum and Solidity
The Ethereum blockchain is arguably the most popular smart contract platform. A participant in Ethereum controls addresses in the blockchain, each of which has a balance of Ether -Ethereum's cryptocurrency -associated with it. These addresses are akin to account numbers in traditional banking. A participant that controls an address also controls the balance associated to it. Thus, they can send a transaction to Ethereum requesting the transfer of some amount of the balance associated to one of its addresses. Aside from these addresses that are managed by external entities, Ethereum also allows addresses to be managed by a program (a smart contract). In addition to a balance, these smart contract addresses have some code and data associated to them. While the former defines the functions offered by the contract, the latter captures its persistent state. For a detailed presentation of Ethereum, see, for instance, [1,2].
Solidity is arguably the most used language for writing smart contracts. A contract in Solidity is a concept very similar to that of a class in object-oriented languages, and a contract instance a sort of long-lived persistent object. We introduce the main elements of Solidity using the ToyWallet contract in Figure 1.
It implements a very basic "wallet" contract that participants and other contracts can rely upon to store their Ether. The member variables of a contract define the persistent state of the contract. This example contract has a single member variable accs, a mapping from addresses to 256-bit unsigned integers, which keeps track of the balance of Ether each "client" of the contract has in the ToyWallet; the integer accs[addr] gives the current balance for address addr, and an address is represented by a 160-bit number.
Public functions describe the operations that participants and other contracts can execute on the contract. The contract in Figure 1 has public functions deposit and withdraw that can be used to transfer Ether into and out of the ToyWallet contract, respectively. In Solidity, functions have the implicit argument msg.sender designating the caller's address, and payable functions have the msg.value which depict how much Wei -the most basic (sub)unit of Ether -is being transferred, from caller to callee, with that function invocation; such a transfer is carried out implicitly by Ethereum. For instance, when deposit is called on an instance of ToyWallet, the caller can decide on some amount amt of Wei to be sent with the invocation. By the time the deposit body is about to execute, Ethereum will already have carried out the transfer from the balance associated to the caller's address to that of the ToyWallet instance -and amt can be accessed via msg.value. Note that, as mentioned, this balance is part of the blockchain's state rather than an explicit variable declared by the contract's code. One can programmatically access this implicit balance variable for address addr with the command addr.balance. Solidity's construct require (condition) aborts and reverts the execution of the function in question if condition does not hold -even in the case of implicit Ether transfers. The call addr.send(amount) sends amount Wei from the currently executing instance to address addr; it returns true if the transfer was successful, and false otherwise. For instance, the first require statement in the function withdraw requires the caller to have the funds they want to withdraw, whereas the second requires the msg.sender.send(value) statement to succeed, i.e. the value must have been correctly withdrawn from ToyWallet to msg.sender. The final statement in this function updates the account balance of the caller (i.e. msg.sender) in ToyWallet to reflect the withdrawal.
We use the transaction create-contract as a means to create an instance of a Solidity smart contract in Ethereum. In reality, Ethereum only accepts contracts in the EVM bytecode low-level language -Solidity contracts need to be compiled into that. The processing of a transaction create-contract(c, args) creates an instance of contract c and executes its constructor with arguments args. Solidity contracts without a constructor (as our example in Figure 1) are given an implicit one. A create-contract call returns the address at which the contract instance was created. We omit the args when they are not relevant for a call. We use σ to denote the state of the blockchain where σ[ad].balance gives the balance for address ad, and σ[ad].storage.mem the value for member variable mem of the contract instance deployed at ad for this state. For instance, let c tw be the code in Figure 1, and addr tw the address returned by the processing of  create-contract(c tw ). For the blockchain state σ immediately after this processing, we have that: for any address addr, σ [addr tw ].storage.accs[addr] = 0 and its balance is zero, i.e., σ [addr tw ].balance = 0. We introduce and use this intuitive notation to present and discuss state changes as it can concisely and clearly capture them. There are many works that formalise such concepts [18,45,7].
A transaction call-contract can be used to invoke contract functions; processing call-contract(addr, func sig, args) executes the function with signature func sig at address addr with input arguments args. When a contract is created, the code associated with its non-constructor public functions is made available to be called by such transactions. The constructor function is only run (and available) at creation time. For instance, let addr tw be a fresh ToyWallet instance and ToyWallet.deposit give the signature of the corresponding function in Figure 1, processing the transaction call-contract(addr tw , ToyWallet.deposit, args) where args = {msg.sender = addr snd , msg.value = 10} would cause the state of this instance to be updated to σ where we have that σ [addr tw ]. storage.accs[addr snd ] = 10 and σ [addr tw ].balance = 10. So, the above transaction has been issued by address addr snd which has transferred 10 Wei to addr tw .

Formal verification with solc-verify
The modular verifier solc-verify [17,16] was created to help developers to formally check that their Solidity smart contracts behave as expected. Input contracts are manually annotated with contract invariants and their functions with pre-and postconditions. An annotated Solidity contract is then translated into a Boogie program which is verified by the Boogie verifier [9,21]. Its modular nature means that solc-verify verifies functions locally/independently, and function calls are abstracted by the corresponding function's specification, rather than their implementation being precisely analysed/executed. These specification constructs have their typical meaning. An invariant is valid if it is established by the constructor and maintained by the contract's public functions, and a function meets its specification if and only if from a state satisfying its pre-conditions, any state /* * * @notice postcondition address ( this ) . balance == _ _ v e r i f i e r _ o l d _ u i n t ( address ( this  successfully terminating respects its postconditions. So the notion is that of partial correctness. Note that an aborted and reverted execution, such as one triggered by a failing require command, does not successfully terminate. We use Figure 2 illustrates a solc-verify specification for an alternative version of the ToyWallet's withdraw function. The postconditions specify that the balance of the instance and the wallet balance associated with the caller must decrease by the withdrawn amount and no other wallet balance must be affected by the call. This alternative implementation uses msg.sender.call.value(value)("") instead of msg.sender.send(value). While the latter only allows for the transfer of value Wei from the instance to address msg.sender, the former delegates control to msg.sender in addition to the transfer of value. 5 If msg.sender is a smart contract instance that calls withdraw again during this control delegation, it can withdraw all the funds in this alternative ToyWallet instanceeven the funds that were not deposited by it. This reentrancy bug is detected by solc-verify when it analyses this alternative version of the contract. A similar bug was exploited in what is known as the DAO attack/hack to take over US$53 million worth of Ether [37,44,8].

Safe Ethereum Smart Contracts Deployment
We propose a framework for the safe creation and upgrade of smart contracts based around a trusted deployer. This entity is trusted to only create or update contracts that have been verified to meet their corresponding specifications. A smart contract development process built around it prevents developers from deploying contracts that have not been implemented as intended. Thus, stakeholders can be sure that contract instances deployed by this entity, even if their code is upgraded, comply with the intended specification.  Our trusted deployer targets the Ethereum platform, and we implement it as an off-chain service. Generally speaking, a trusted deployer could be implemented as a smart contract in a blockchain platform, as part of its consensus rules, or as an off-chain service. In Ethereum, implementing it as a smart contract is not practically feasible as a verification infrastructure on top of the EVM [1] would need to be created. Furthermore, blocks have an upper limit on the computing power they can use to process their transactions, and even relatively simple computing tasks can exceed this upper limit [46]. As verification is a notoriously complex computing task, it should exceed this upper limit even for reasonably small systems. Neither can we change the consensus rules for Ethereum.
We present the architecture of the trusted deployer infrastructure in Figure 3. The trusted deployer relies on an internal verifier that implements the functions verify-creation and verify-upgrade , and an upgrader that implements functions create-contract and upgrade-contract; we detail what these functions do in the following. The deployer's create-contract (upgrate-contract) check that an implementation meets its specification by calling verify-creation (verify-upgrade ) before relaying this call to the upgrader's create-contract (upgrade-contract) which effectively creates (upgrades) the contract in the Ethereum platform. The get-spec function can be used to test whether a contract instance has been deployed by the trusted deployer and which specification it satisfies.
The verifier is used to establish whether an implementation meets a specification. A verification framework is given by a triple (S, C, ) where S is a language of smart contract specifications, C is a language of implementations, and ∈ (S × C) is a satisfiability relation between smart contracts' specifications and implementations. In this paper, C is the set of Solidity contracts and S a particular form of Solidity contracts, possibly annotated with contract invariants, that include function signatures annotated with postconditions. The functions verify-creation and verify-upgrade both take a specification s ∈ S and a contract implementation c ∈ C and test whether c meets s -they work in slightly different ways as we explain later. When an implementation does not meet a specification, verifiers typically return an error report that points out which parts of the specification do not hold and maybe even witnesses/counterexamples describing system behaviours illustrating such violations; they provide valuable information to help developers correct their implementations.
The upgrader is used to create and manage upgradable smart contracts -Ethereum does not have built-in support for contract upgrades. Function createcontract creates an upgradable instance of contract c ∈ C -it returns the Ethereum address where the instance was created -whereas upgrade-contract allows for the contract's behaviour to be upgraded. The specification used for a successful contract creation will be stored and used as the intended specification for future upgrades. Only the creator of a trusted contract can update its implementation.
Note that once a contract is created via our trusted deployer, the instance's specification is fixed, and not only its initial implementation but all upgrades are guaranteed to satisfy this specification. Therefore, participants in the ecosystem interacting with this contract instance can be certain that its behaviour is as intended by its developer during the instance's entire lifetime, even if the implementation is upgraded as the contract evolves.
In this paper, we focus on contract upgrades that preserve the signature of public functions. Also, we assume contract specifications fix the data structures used in the contract implementation. However, we plan to relax these restrictions in future versions of the framework, allowing the data structures in the contract implementation to be a data refinement of those used in the specification; we also plan to allow the signature of the implementation to extend that of the specification, provided some notion of behaviour preservation is obeyed when the extended interface is projected into the original one.

Verifier
We propose design-by-contract [28] as a methodology to specify the behaviour of smart contracts. In this traditional specification paradigm, conceived for object-oriented languages, a developer can specify invariants for a class and pre-/postconditions for its methods. Invariants must be established by the constructor and guaranteed by the public methods, whereas postconditions are ensured by the code in the method's body provided that the pre-conditions are guaranteed by the caller code and the method terminates -currently, we focus on partial correctness. We propose a specification format that defines what the member variables and signatures of member functions should be. Additionally, the function signatures can be annotated with postconditions, and the specification with invariants; these annotations capture the expected behaviour of the contract. In ordinary programs, a function is called in specific call sites fixed in the program's code. Pre-conditions can, then, be enforced and checked in these call sites. In the context of public functions of smart contracts, however, any well-formed transaction can be issued to invoke such a function. Hence, we move away from preconditions in our specification, requiring, thus, postconditions to be met whenever public functions successfully terminate. Figure 4 illustrates a specification for the ToyWallet contract. Invariants are declared in a comment block preceding the contract declaration, and function postconditions are declared in comment blocks preceding their signatures. Our specification language reuses constructs from Solidity and the solc-verify specification language, which in turn borrows elements from the Boogie language [9,21]. Member variables and function signature declarations are as prescribed by Solidity, whereas the conditions on invariants, and postconditions are side-effect-free Solidity expressions extended with quantifiers and the expression __verifier_old_x(v) that can only be used in a postcondition, and it denotes the value of v in the function's execution pre-state.
We choose to use Solidity as opposed to EVM bytecode as it gives a cleaner semantic basis for the analysis of smart contracts [7] and it also provides a highlevel error message when the specification is not met. The satisfiability relation that we propose is as follows. The purpose of this paper is not to provide a formal semantics to Solidity or to formalise the execution model implemented by the Ethereum platform. Other works propose formalisations for Solidity and Ethereum [17,6,45]. Our focus is on using the modular verifier solc-verify to discharge the semantic obligations imposed by our satisfaction definition.
The verify-creation function works as follows. Firstly, the syntactic obligation imposed by Definition 1 is checked by a syntactic comparison between s and c. If it holds, we rely on solc-verify to check whether the semantic obligation is fulfilled. We use what we call a merged contract as the input to solc-verify -it is obtained by annotating c with the corresponding invariants and postconditions in s. If solc-verify is able to discharge all the proof obligations associated to this merged contract, the semantic obligations are considered fulfilled, and verify-creation succeeds.
Function verify-upgrade is implemented in a very similar way but it relies on a slightly different satisfiability relation and merged contract. While verify-creation checks that the obligations of the constructor are met by its implementation, verify-upgrade assumes they do, since the constructor is only executed -and, therefore, its implementation checked for satisfiability -at creation time. The upgrade process only checks conformance for the implementation of the (non-constructor) public functions.

Upgrader
Ethereum does not provide a built-in mechanism for upgrading smart contracts. However, one can simulate this functionality using the proxy pattern [38], which splits the contract across two instances: the proxy instance holds the persistent state and the upgrade logic, and rely on the code in an implementation instance for its business logic. The proxy instance is the de-facto instance that is the target of calls willing to execute the upgradable contract. It stores the address of the implementation instance it relies upon, and the behaviour of the proxy's public functions can be upgraded by changing this address. Our upgrader relies on our own version of this pattern to deploy upgradable contracts.
Given a contract c that meets its specification according to Definition 1, the upgrader creates the Solidity contract proxy(c) as follows. It has the same member variable declarations, in the same order, as c -having the same order is an implementation detail that is necessary to implement the sort of delegation we use as it enforces proxy and implementation instances to share the same memory layout. In addition to those, it has a new address member variable called implementation -it stores the address of the implementation instance. The constructor of proxy(c) extends the constructor of c with an initial setting up of the variable implementation. 6 This proxy contract also has a public function upgrade that can be used to change the address of the implementation instance. The trusted deployer is identified by a trusted Ethereum address addr td . This address is used to ensure calls to upgrade can only be issued by the trusted deployer. In the process of creating and upgrading contracts the trusted deployer acts as an external participant of the Ethereum platform. We assume that the contract implementations and specifications do not have member variables named implementation, or functions named upgrade to avoid name clashes.
The proxy instance relies on the low-level delegatecall Solidity command to dynamically borrow and execute the function implementations defined in the contract instance at implementation. When the contract instance at address proxy executes implementation.delegatecall(sig, args), it executes the code associated with the function with signature sig stored in the instance at address implementation but applied to the proxy instance -modifying its state -instead of implementation. For each (non-constructor) public function in c with signature sig, proxy(c) has a corresponding function declaration whose implementation relies on implementation.delegatecall(sig, args). This command was proposed as a means to implement and deploy contracts that act as a sort of dynamic library. Such a contract is deployed with the sole purpose of other contracts borrowing and using their code.
The upgrader function create-contract(c) behaves as follows. Firstly, it issues transaction create-contract(c, args) to the Ethereum platform to create the initial implementation instance at address addr impl . Secondly, it issues transaction create-contract(proxy(c), args), such that implementation would be set to addr impl , to create the proxy instance at address addr px . Note that both of these transactions are issued by and using the trusted deployer's address addr td . The upgrader function upgrade-contract(c) behaves similarly, but the second step issues transaction call-contract(addr px ,upgrade, args), triggering the execution of function upgrade in the proxy instance and changing its implementation address to the new implementation instance.

Case Studies: ERC20 and ERC1155
The presentation of our case studies is structured into three main sections: first we describe the context (Section 4.1), next we provide the results (Section 4.2), then we discuss the threats to validity and the limitations (Section 4.3) and, finally, we analyze a scenario based on 0xMonorepo repository in order to find bugs included in the development process (Section 4.4).

Context
The main purpose of the study is to provide evidence that the proposed framework can be used to ensure the deployment and evolution of smart contracts in implement this behaviour for the non-constructor function initialize. Our Trusted Deployer, available at https://github.com/stanis18/safeeveolution, automatically generates the code for such a proxy. a secure manner. The framework must be integrated into a development process and whenever there is any change in the code, one must verify if the change meets the specification, so we intend to answer the following research question: Does the proposed framework improve on the process of creation and evolution of smart contracts?
In the first phase, a review of the literature was carried out. The objective was to explore the main features of smart contract development patterns and the most common error types. As a result, we could identify opportunities for the application of the framework in line with the objectives of the study. In the second phase, we identified, documented and validated requirements related to two Ethereum smart contract specifications: ERC20 and ERC1155. Each of these standards defines a contract interface and is accompanied by an informal description of its functions' behaviours. We chose these standards because they are widely used and in an advanced state of maturity. By structuring the existing requirements in natural language, we were able to extract the formal properties used in the verification process and create a corresponding formal contract specification. Then, we conducted a quantitative analysis, in order to verify the feasibility of the framework, to evaluate its effectiveness, which can be measured by the number of errors found or safe evolutions that have been proven correct, and efficiency, measured by the time to process the verification.
We have implemented a tool to check the syntactic and semantic obligations imposed by our framework. It relies on the abstract syntax tree generated by the Solidity compiler [3] to check the syntactic obligations, and to create a contract resulting from merging the solidity smart contract with the corresponding formal specification; this is then checked by the solc-verify as a means to discharge the semantic obligations. We applied our framework to a number of real-world Solidity smart contract samples implementing the ERC20 and the ERC1155 token standards. The contract samples we analysed were extracted from 12 github repositories that were public, and presented reasonably complex commit histories that changed the smart contract behavior. The samples also cover aspects of evolution that are related to improving the readability and maintenance of the code, but also optimisations where, for instance, redundant checks executed by a function were removed. The evaluation was carried out on a Lenovo IdeapadGaming3i with the operational system Windows 10, Intel(R) Core(TM) i7-10750 CPU @ 2.60GHz, 8GB of RAM, with Docker Engine 20.15.5 and Solidity compiler version 0.5.17.

Results
Our framework was able to identify errors of the following categories: Integer Overflow and Underflow (IOU); Nonstandard Token Interface (NTI), when the contract does not meet the syntactic restriction defined by the standard; wrong operator (WOP), for instance, when the < operator would be expected but ≤ is used instead; and Verification Error (VRE), when the verification process cannot be completed or the results were inconclusive. It also established conformance for some of the samples analysed. obtained. In the following, we use some snippets extracted from ERC20 examples in our evaluation to illustrate the application of our framework, some of the errors that we found, and a case of a safe evolution. The ERC20 is likely to be the most widely implemented Ethereum standard. It defines member variables: totalSupply keeps track of the total number of tokens in circulation, balanceOf maps a wallet (i.e. address) to the balance it owns, and allowance stores the number of tokens that an address has made available to be spent by another one. It defines public functions: totalSupply, balanceOf and allowance are accessors for the above variables; transfer and transferFrom can be used to transfer tokens between contracts; and approve allows a contract to set an "allowance" for a given address. Figure 5 presents a reduced specification, focusing on functions transferFrom and allowance for the purpose of this discussion, derived from the informal description in the standard [43]. In Line 1, we define an invariant requiring that the total number of tokens remain unchanged regardless of the operation carried 1 // / @notice invariant totalSupply == _ _ v e r i f i e r _ s u m _ u i n t ( balanceOf ) 2 contract IERC20 { 3 uint256 totalSupply ; 4 mapping ( address = > uint256 ) balanceOf ; 5 mapping ( address = > mapping ( address = > uint256 ) ) allowance ; 6 7 // ... functions transfer , totalSupply , balanceOf , and approve omitted ...   5: ERC20 reduced specification out by the contract. The function allowance does not change the state of the smart contract so it has only one postcondition (line 9) to ensure that it will return the correct amount of tokens available for withdrawals. The transferFrom function has 4 postconditions; the operation is successful only when the tokens are debited from the source account and credited in the destination account, according to the specifications provided in the ERC20 standard. The first two postconditions (lines 13 to 14) require that the balances are updated as expected, whereas the purpose of the last two (lines 15 to 16) is to ensure that the tokens available for withdrawal have been properly updated. We use the snippet in Figure 6 -extracted from the Uniswap repository, commit 55ae25, we underline the commits that we refer to in Table 1 as well to help readers locate it more easily -to illustrate the detection of wrong operator errors. When checked by our framework, the third postcondition for the transferFrom function presented in the specification in Figure 5 is not satisfied. Note that the allowance amount is not debited if the amount to be transferred is equal to the maximum integer supported by Solidity (i.e. uint(-1)). A possible solution would consist of removing the if branching, allowing the branch code to always execute.
The code snippet in Figure 7 -DigixDao repository, commit 5aee64 -does not conform to its formal specification. The correct allowance for the spender is only returned when it is not greater than the owner's balance. To fix this issue, we need to remove all code related to _balance, ensuring that the _allowance will be returned regardless of the _balance amount.
The ERC1155 (see Figure 8) was created in order to promote a better integration between the ERC20 and ERC721 standards. It provides an interface for managing any combination of fungible and non-fungible tokens in a single contract efficiently. The functions balanceOf and balanceOfBatch returns the balance of specific tokens of the address or a list of addresses specified in the parameter function respectively. The function isApprovedForAll returns a boolean value informing if an address is allowed to handle the tokens from another address. The safeTransferFrom function transfers tokens in a safe way to a valid ERC1155 address. The transferFrom function can do batch operations, transfering tokens to several wallets at the same time, reducing transaction costs and minimizing impacts on the network. The setApprovalForAll function gives an address permission to handle another address' tokens.
The snippet in Figure 11 -extracted from Descentralized-Stock repository, commit 96d5b2 -illustrates another example of the wrong operator error. A postcondition was not satisfied, because, according to the specification, the size of the _ids and _values arrays must be equal. So, any call to this function would result in an error or an unexpected behavior. A possible solution would consist of changing the operator != for == in the second requires in Figure 11. Figures 9 and 10 -extracted from the 0xSequence-erc-1155 repository, commits 99012f and 319740, respectively -illustrate a case of safe contract evolu-  tion. The code of this contract has undergone significant changes. The refactoring in question is one of the most common and is known as extract method (function, in Solidity). From commit 319740 to 99012f, the new internal function _callonERC1155Received was created, and the extracted code from the _safeTransferFrom was moved into it.
The results of our evaluation suggest that the kind of verification that we employ in our framework is tractable, as solc-verify can efficiently analyse these samples. The fact that errors that could lead to millionaire losses were detected _ s a f e T r a n s f e r F r o m ( _from , _to , _id , _value , _data ) ; } Fig. 9: safeTransferFrom function before refactoring in real-world contracts attests to the necessity of our framework and its practical impact. Smart contracts are incresingly popular, and we believe they will become a key and common element of trusted distributed systems in the future. Therefore, having a safe development process supported by our framework will help to increase the credibility of such a technology and promote its adoption.

Threats to Validity and Limitations
Our initial motivation to gather the samples from public github repositories may be a threat to our search strategy. Since we could not analyze private repositories, relevant cases to show strengths and weaknesses of the framework may not have been included. The relatively low number of samples could also be considered as a threat, since it could lead to an unintentionally biased study or less comprehensive than it could have been. Our framework also presents some limitations, since it is not in our scope to verify errors on inter-contract interactions.

Trusted Deployer Tool
After discussing the results of the smart contract verification process, we introduce a scenario based on 0xMonorepo repository which implements the ERC20 pattern and is one of the repositories used during our study. We analysed the whole commit history (see Table 2) in order to find errors or nonconformities and describe what the history of the repository would be if a developer had used our tool since invalid commits would be prevented from being deployed. The idea is to show how our tool implements the architecture depicted in Figure 3; we also demonstrate the tool supports a safe smart contract development process.
As already explained, the trusted deployer requires that developers have their code formally verified before they can deploy their contracts to a blockchain network. In order to create or upgrade a smart contract, a developer has to provide its code and specification together. The tool uses the solc-verify in background to verify the code against its specification before it proceeds to deploy the smart contract. Figure 12 presents a merged contract, which is the result of the merging of the specification and implementation contracts. The verification contract is automatically created from the abstract syntax tree of the contracts after a syntactic check is performed; in this case, the goal is to analyse if there is any discrepancy between the signature of the functions and the data model of the specification and implementation contracts. Provided the syntactic analysis is successful, the tool invokes the solc-verify in background to carry out verification of conformance to the specification.   The trusted registry (see Figure 13) check whether that a given instance was created by the trusted deployer by calling its get-spec function. Since smart contracts in a blockchain platform cannot rely on external services, such as the trusted deployer, that is, they would have no means to check whether an instance that they want to interact with is safe or not. We create a trusted registry as part of the trusted deployer infrastructure which is essentially a mirror of the trusted deployer's internal registry implemented as a smart contract. It has a maintainer and mapping verified_addr that associates the proxy instances that have been created by the trusted deployer with the specification they comply to. As an implementation detail, we do not store the specification themselves but rather a small representative as a 32-byte array -it could be, for instance, a cryptographic hash of the specification. We do not allow this representative to be the zeroed array, bytes32(0) in Solidity syntax, as we use this value to represent absence of an association. That is, if the result of a call get spec(addr) is the value bytes32(0), it means the address addr has not been deployed by the trusted deployed, and hence has no specification associated with it. The proxy pattern as discussed in Section 3.2 separates the logic and the data of a contract. The key concept to understand is that the implementation contract can be replaced while the trusted proxy (see Figure 14), or the access point is never changed. Both contracts are still immutable in the sense that their code cannot be changed, but the logic contract can simply be swapped by another contract. Every proxy must contain all variables (lines 3 to 5) defined in the implementation contract which will store the state as well as the signatures of all its public functions (lines 7 to 10). If there is any constructor in the implementation contract it will be merged with the default constructor of the proxy (lines 17 to 23).
During the analysis of the scenario 30 commits were verified, it was observed the WOP error in its first four commits 7d59fa, 7008e8, b58bf8 and 548fda. If  Table 2: 0xMonorepo Commit History the developer had used our tool the error would have been discovered in the first analysis, these deployments would have been prevented, and an error message containing the specific reason would be returned to the developer forcing him to fix the bug. The results collected from our evolution scenario, one can see that our strategy is effective in identifying error in the early stage of the process. Our tool abstracts many details of the deployment and upgrade process making it simpler for platform users when compared to the manual process.

Related Work
There is a glaring need for a safe mechanism to upgrade smart contracts in platforms, such as Ethereum, where contract implementations are immutable once deployed; the many surveys uncovering this fact [19,40,15] and communityproposed design patterns proposing mechanisms to upgrade smart contracts [38,10,25,32] attest this necessity. Yet, surprisingly, we could only find two close related approaches [11,35] that try to tackle this problem. The preliminary work in [11] proposes a methodology based around special contracts that carry a proof that they meet the expected specification. Their on-chain solution requires fundamental changes in the smart contract platforms themselves. They propose the addition of a special instruction to deploy these special proof-carrying contracts, and the adaptation of platform miners, which are responsible for checking and reaching a consensus on the validity of contract executions, to check these proofs. Our framework and the one presented in that work share the same goal: to pro-pose a mechanism by which contracts can be upgraded but only if they meet the expected specification. However, our approach and theirs differ significantly in many aspects. Firstly, while theirs requires a fundamental change on the rules of the platform -which requires a large distributed network of nodes, i.e. the smart contract platform, to agree upon -ours can be implemented, as already prototyped, on top of Ethereum's current capabilities and can rely on tools that are easier to use, i.e. require less user input, like program verifiers. The fact that their framework is on-chain makes the use of such verification methods more difficult since these methods would slow down consensus, likely to a prohibitive level. Finally, while they introduce abstract ideas with some concrete elements, we provide details on how to implement our framework using current technology and an evaluation based on real-world Solidity samples.
In [35], the authors propose a mechanism to upgrade contracts in Ethereum that works at the EVM-bytecode level. Their framework takes vulnerability reports issued by the community as an input, and tries to patch affected deployed contracts automatically using patch templates. It uses previous contract transactions and, optionally user-provided unit tests, to try to establish whether a patch preserves the behaviour of the contract. Ultimately, the patching process may require some manual input. If the deployed contract and the patch disagree on some test, the user must examine this discrepancy and rule on what should be done. Note that this manual intervention is always needed for attacked contracts, as the transaction carrying out the attack -part of the attacked contract's history -should be prevented from happening in the new patched contract. While they simply test patches that are reactively generated based on vulnerability reports, we proactively require the user to provide a specification of the expected behaviour of a contract and formally verify the evolved contract against such a formal specification. Their approach requires less human intervention, as a specification does not need to be provided -only optionally some unit testsbut it offers no formal guarantees about patches. It could be that a patch passes their validation (i.e. testing with the contract history), without addressing the underlying vulnerability.
Some other papers have proposed methodologies to carry out pre-deployment patching/repairing [41,31,47]. They try to scan a binary for common vulnerabilities and patch the vulnerabilities they find prior to deploying the contract. These papers do not propose a way to update deployed contracts.
A number of analysis tools for EVM bytecode were designed to find specific behaviour patterns witnessing typical bad behaviours [26,30,24,14,39,42,33]. Tools operating on the level of Solidity were also proposed [45,17,16,7,5,4]. These tools tend to focus instead on formally verifying user-provided semantic properties. Our paper proposes a verification-focused development process based around, supported, and enforced by such tools.
Design by contract [28] is a methodology that was originally created for specifying the behaviour of object-oriented programs but was also adopted in other contexts [29,22,9,21,20,17]. This sort of specification is particularly fitting in the case of Solidity smart contracts, especially the format of specification that we propose, as the community already employ a similar format, albeit informal, to describe standard contract interfaces in the form of Ethereum Request for Comments (ERCs); see for example, ERC20 [43].

Conclusion
We propose a framework for the safe deployment of smart contracts. Not only does it check that contracts conform to their specification at creation time, but it also guarantees that subsequent code updates are conforming too. Upgrades can be performed even if the implementation has been proven to satisfy the specification initially. A developer might, for instance, want to optimise the resources used by the contract. Furthermore, our trusted deployer records information about the contracts that have been verified, and which specification they conform to, so that participants can be certain they are interacting with a contract with the expected behaviour; contracts can be safely executed. None of these capabilities are offered by the Ethereum platform by default nor are available in the literature to the extent provided by the framework proposed in this paper.
We have prototyped our trusted deployer and investigated its applicability -specially its formal verification component -to contracts implementing two widely used Ethereum standards: the ERC20 Token Standard and ERC1155 Multi Token Standard, with promising results.
This idea of using trusted computing to verify a smart contract before its deployment can be extended to software in general. Particularly, a trusted deployer could be part of a deployment process for reactive systems in general, such as component-based, (micro)service-based systems, or even system-of-systems.
Our framework shifts immutability from the implementation of a contract to its specification, promoting the "code is law" to the "specification is law" paradigm. We believe that this paradigm shift brings a series of improvements. Firstly, developers are required to outline their intent in the form of a (formal) specification, so they can, early in the development process, identify issues with their design. They can and should validate their specification; we consider this problem orthogonal to the framework that we are providing. Secondly, specifications are more abstract and, as a consequence, tend to be more stable than (the corresponding conforming) implementations. A contract can be optimised, for instance, and both the original and optimised versions must satisfy the same reference specification. Thirdly, even new implementations that involve change of data representation can still be formally verified against the same specification, by using data refinement techniques.
A limitation of our current approach is the restrictive notion of evolution for smart contracts: only the implementation of public functions can be upgradedthe persistent state data structures are fixed. However, we are looking into new types of evolution where the data structure of the contract's persistent state can be changed -as well as the interface of the specification, provided the projected behaviour with respect to the original interface is preserved, based on notions of class [23] and process [12] inheritance, and interface evolution such as in [13].