[{"data":1,"prerenderedAt":20},["ShallowReactive",2],{"blog-detail:securing-the-aptos-framework-through-formal-verification":3},{"category":4,"article":5},null,{"slug":6,"category":7,"categoryLabel":8,"subcategoryLabel":9,"authorName":10,"title":11,"excerpt":12,"contentHtml":13,"coverUrl":14,"seoTitle":11,"seoDescription":12,"seoImageUrl":14,"publishedAt":15,"updatedAt":16,"readTime":17,"cover":14,"hasCover":18,"coverAlt":19},"securing-the-aptos-framework-through-formal-verification","research","Research","Industry Research","MoveBit","Securing the Aptos Framework through formal verification","The Aptos Framework has continuously undergone rigorous testing and comprehensive auditing. To further increase the level of assurance, we have formally verified its security and correctness.","\u003Cp>by Aptos Labs, \u003Cstrong>MoveBit\u003C\u002Fstrong>, and OtterSec\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fmedia\u002Fmovebit\u002F2024\u002F01\u002F6f281789b5f6916b6462bff8c834a944.png\" alt=\"aptos-move-prover-movebit\" title=\"Aptos Move Prover with MoveBit\">\u003C\u002Fp>\n\u003Cp>\u003Cem>The Aptos Framework has continuously undergone rigorous testing and comprehensive auditing. To further increase the level of assurance, we have formally verified its security and correctness.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\n\u003Cem>We worked with\u003C\u002Fem> \u003Cstrong>\u003Cem>MoveBit\u003C\u002Fem>\u003C\u002Fstrong> \u003Cem>in creating formal specifications for large parts of the Framework, which were then verified with the Move Prover.\u003C\u002Fem>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cem>We worked with\u003C\u002Fem> \u003Cstrong>\u003Cem>OtterSec\u003C\u002Fem>\u003C\u002Fstrong> \u003Cem>in auditing the Aptos Framework and identifying critical security requirements for each module.\u003C\u002Fem>\n\u003C\u002Fli>\n\u003Cli>\u003Cem>This combined effort gives the Aptos Framework an unmatched level of quality assurance in the blockchain industry and beyond.\u003C\u002Fem>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"Introduction\">Introduction\u003C\u002Fh2>\n\u003Cp>The Aptos Framework is the collection of Move smart contract modules that define standard and common on-chain actions for the Aptos Network, including the prologue and epilogue of transactions, the staking mechanism, and the Aptos Digital Asset Standard. It is imperative to ensure the correctness and security of the Aptos Framework because the unexpected behavior of such foundational Move modules could lead to substantial asset loss or disrupt the normal functioning of the network. For this reason, the Aptos Framework has continuously undergone rigorous testing and comprehensive auditing, and to further increase the level of assurance, we have f_ormally verified its security and correctness._  This article will explain how we have secured the Aptos Framework through formal verification using the Move Prover.\u003C\u002Fp>\n\u003Ch2 id=\"What-is-the-Move-Prover\">What is the Move Prover?\u003C\u002Fh2>\n\u003Cp>The Move Prover (Prover for short) is a  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FFormal_verification\">formal verification\u003C\u002Fa>  tool for smart contracts that are written in the Move language. The Move language is tightly coupled and integrated with the Prover because they have been developed and are evolving together. Move features an expressive  \u003Cem>specification language\u003C\u002Fem>  designed to define the intended behaviors of a Move smart contract. Employing an automatic theorem-proving technology (e.g.,  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSatisfiability_modulo_theories\">satisfiability modulo theories\u003C\u002Fa>), the Prover automatically checks whether the contract satisfies the user-given specification for all possible program variable assignments. If it does not, the Prover generates a so-called  \u003Cem>counter-example\u003C\u002Fem>, that is an assignment to program variables such that the specification does  \u003Cem>not\u003C\u002Fem>  hold. The Prover is  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Flink.springer.com\u002Fchapter\u002F10.1007\u002F978-3-030-99524-9_10\">fast and reliable\u003C\u002Fa>, and can be used routinely during smart contract development, making the experience of running the Prover similar to the experience of running compilers, linters, type checkers, and other development tools.\u003C\u002Fp>\n\u003Ch2 id=\"The-Move-Specification-Language\">The Move Specification Language\u003C\u002Fh2>\n\u003Cp>The Move specification allows developers to specify the properties of their smart contracts, leveraging the Prover to guarantee they behave as specified without adding any runtime cost on-chain. In the specification language, developers can provide pre and post-conditions for functions, which include conditions over input parameters and global memory. Developers can also provide invariants over data structures as well as the contents of the global memory. The language also supports universal and existential quantification over bounded domains, such as the indices of a vector, as well as effectively unbounded domains, such as memory addresses and integers (e.g.,  \u003Ccode>forall a: address: P(a)\u003C\u002Fcode>, and  \u003Ccode>exists i: u64: Q(i)\u003C\u002Fcode>, for some predicates  \u003Ccode>P\u003C\u002Fcode>  and  \u003Ccode>Q\u003C\u002Fcode>). While quantifiers can render the verification problem undecidable and lead to timeout issues, they offer a practical advantage: they allow for a more direct formalization of various properties, enhancing the clarity of specifications (e.g., the data invariant of  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fstorage_gas.md#@Specification_16_GasCurve\">GasCurve\u003C\u002Fa>).\u003C\u002Fp>\n\u003Cp>As an example, the  \u003Ccode>spec\u003C\u002Fcode>  below shows  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fcoin.md#@Specification_1_extract\">the specification\u003C\u002Fa>  of the extract function in  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fcoin.md#0x1_coin\">the coin module\u003C\u002Fa>:\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-none\">\u003Ccode class=\"language-none\">spec extract&lt;CoinType&gt;(  \n    coin: &amp;mut Coin&lt;CoinType&gt;,  \n    amount: u64  \n): Coin&lt;CoinType&gt; {  \n    aborts_if coin.value &lt; amount;  \n    ensures result.value == amount;  \n    ensures coin.value == old(coin.value) - amount;  \n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>The  \u003Ccode>extract\u003C\u002Fcode>  function is expected to extract and return the amount of coins from the coin parameter. The specification above is the mathematical representation of the expected behavior of the function. The  \u003Ccode>aborts_if\u003C\u002Fcode>  clause specifies that the function should abort if the value of the original  \u003Ccode>coin\u003C\u002Fcode>  is less than the amount. It also implies that the function should not abort in any other case. The two  \u003Ccode>ensures\u003C\u002Fcode>  clauses specify that the value of the returned coin is equal to amount and the value of the original coin decreases by  \u003Ccode>amount\u003C\u002Fcode>. The Prover guarantees that  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fcoin.md#0x1_coin_extract\">the function implementation\u003C\u002Fa>  satisfies this specification for all input values and all coin types. The Prover’s formal verification contrasts with testing, where a single test case only covers a specific instance of input and coin type. Moreover, once a specification for the Prover is defined, it enables the Prover to automatically check the specification thereafter. This automation significantly reduces the costs associated with repetitive manual audits for every modification of the smart contract.\u003C\u002Fp>\n\u003Ch2 id=\"What-have-we-Achieved\">What have we Achieved?\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>From Security Requirement to Verification\u003C\u002Fstrong>: The first thing to highlight is that we have identified the high-level security requirements of each module of the Aptos framework and verified them using the Prover. We collaborated with  \u003Cstrong>OtterSec\u003C\u002Fstrong>  in auditing the Aptos Framework and identifying critical security requirements for each module. We thoroughly documented these requirements, outlining their definition, criticality, implementation approach, and methods of enforcement. The enforcement methods include audit, test, and, where appropriate, formal verification. We also collaborated with  \u003Cstrong>MoveBit\u003C\u002Fstrong>  in creating formal specifications for large parts of the Framework, which were then verified with the Prover. The verification result is then tracked back to the safety requirement documentation.\u003C\u002Fp>\n\u003Cp>For example, the table below is part of  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Faccount.md#high-level-req\">the high-level requirements\u003C\u002Fa> for  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Faccount.md\">the account module\u003C\u002Fa>:\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fmedia\u002Fmovebit\u002F2024\u002F01\u002F7f32f3a8da74773ab279e40173c82e9c.png\" alt=\"aptos-movebit-example\" title=\"Aptos MoveBit Example\">\u003C\u002Fp>\n\u003Cp>The row above is a critical requirement that, after successfully creating an account, it is initialized with the correct default data, ensuring the proper initialization of the account state. This is implemented in a way that creating an account via  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Faccount.md#0x1_account_create_account\">the create_account function\u003C\u002Fa>  validates the state and moves a new account resource under  \u003Ccode>new_address\u003C\u002Fcode>. This is formally specified and verified as follows:\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-none\">\u003Ccode class=\"language-none\">spec create_account(new_address: address): signer {  \n    …  \n    \u002F\u002F This enforces high-level requirement 2:  \n    ensures exists&lt;Account&gt;(new_address);  \n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>\u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Faccount.md#high-level-req-2\">The ensure clause\u003C\u002Fa>  above is part of the specification of the  \u003Ccode>create_account\u003C\u002Fcode>  function that specifies the high-level security requirement. The post-condition ensures that the Account resource always exists at the end of the function call.\u003C\u002Fp>\n\u003Cp>We have integrated the high-level security requirements into the Move documentation generation process. Thus, these security requirement descriptions are imported into the Aptos Framework documentation automatically. We also established a traceability framework that maps high-level properties to their corresponding formal specifications, and maps the formal specifications back to the high-level requirement, as shown in the specification above . For example, the high-level requirements of the account module can be found  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Faccount.md#high-level-req\">here\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Function by function\u003C\u002Fstrong>: In addition to the high-level security requirement verification, we have also systematically inferred the specifications from the Move functions and modules, collaborating with  \u003Cstrong>MoveBit\u003C\u002Fstrong>. These specifications include abort conditions and post-conditions of each Move function as well as invariants of structs and modules.\u003C\u002Fp>\n\u003Cp>\u003Ccode>aborts_if\u003C\u002Fcode>  specifications cover important classes of properties, such as access control checks, input validation, and state validation. Move functions are normally designed to abort when they are called (1) by an account without permission, (2) with an input argument outside of an expected range, or (3) on an unexpected global state. For example, in the Aptos Framework’s \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fstaking_config.md\">staking config contract\u003C\u002Fa>, only the aptos_framework account (i.e., 0x1) can call  \u003Ccode>update_recurring_lockup_duration_secs\u003C\u002Fcode>. Also, the input parameter  \u003Ccode>new_recurring_lockup_duration_secs\u003C\u002Fcode>  should be non-zero. It should be called only when the resource  \u003Ccode>StakingConfig\u003C\u002Fcode>  is published under the aptos_framework address. These expected behaviors are captured by the following specification:\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-none\">\u003Ccode class=\"language-none\">spec update_recurring_lockup_duration_secs(  \n    aptos_framework: &amp;signer,  \n    new_recurring_lockup_duration_secs: u64  \n){  \n    aborts_if signer::address_of(aptos_framework) != @aptos_framework;  \n    aborts_if new_recurring_lockup_duration_secs == 0;  \n    aborts_if !exists&lt;StakingConfig&gt;(@aptos_framework);  \n    …  \n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Given this  \u003Ccode>aborts_if\u003C\u002Fcode>  specification, the Prover verifies two things. First, it verifies that the function indeed aborts when any one of the conditions holds. Second, the Prover verifies that the function does  \u003Cem>not\u003C\u002Fem>  abort on any other condition. This verification is important because it allows developers to understand the complete set of conditions under which the function can abort, thus the specifications also serve as precise documentation. The complete specification of the function above can be found  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fstaking_config.md#@Specification_1_update_recurring_lockup_duration_secs\">here\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"Impact-of-Formal-Verification\">Impact of Formal Verification\u003C\u002Fh2>\n\u003Cp>Formal verification has had many positive impacts on the Aptos Framework, providing assurance on the execution of the critical functions, and finding issues before new functionality landed on Aptos Network in production.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Before Aptos went to  \u003Ccode>mainnet\u003C\u002Fcode>, we had already verified the absence of unexpected abort behavior in  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fblock.md#0x1_block_block_prologue\">block::block_prologue\u003C\u002Fa>. This function must never abort since it is executed with each block, and a malfunction can bring the entire network down. The block prologue complex execution involves 96 Move functions in 22 different Move modules. We formally specified all these modules and proved that the block prologue execution would never fail (or abort) in an unexpected condition. During this process, we identified and fixed some potential arithmetic overflows during the block prologue execution. The complete specification of this function can be found  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fblock.md#@Specification_1_block_prologue\">here\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>A number of issues were found during the specification and verification of the code. The code had already undergone unit testing and auditing, resulting in a relatively small number of new findings. However, formal verification ensures that the probability of further unknown issues is very low. In contrast to testing, formal verification does not just show the presence of bugs but proves their absence.\u003C\u002Fli>\n\u003Cli>We have identified and defined various invariants within the modules, significantly enhancing our understanding of their behaviors and their security implications. This deeper insight has subsequently guided the refactoring and improvement of several modules.\u003C\u002Fli>\n\u003Cli>The specifications form an integral part of the  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main\">automatically generated Aptos Framework documentation\u003C\u002Fa>, providing a clear and detailed account of the expected behavior for each function and module (e.g., the  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fcoin.md#@Specification_1_register\">specification\u003C\u002Fa>  of  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Faptos.dev\u002Freference\u002Fmove\u002F?branch=main&amp;page=aptos-framework\u002Fdoc\u002Fcoin.md#0x1_coin_register\">coin::register\u003C\u002Fa>). This precise documentation of security requirements is essential for ongoing maintenance and ensuring quality assurance.\u003C\u002Fli>\n\u003Cli>Finally, integrating the Prover into the Continuous Integration (CI) testing process significantly reduces the necessity for frequent audits with each contract modification. Consequently, formal verification has effectively decreased both the time and cost associated with auditing.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"Conclusion-and-Future-Plans\">Conclusion and Future Plans\u003C\u002Fh2>\n\u003Cp>In order to ensure the highest quality and security of the Aptos Framework, we have applied a methodology that combines manual auditing, testing, and automated formal verification. In collaboration with  \u003Cstrong>OtterSec\u003C\u002Fstrong>, the framework was audited, and high-level security requirements were elicited and documented. In collaboration with  \u003Cstrong>MoveBit\u003C\u002Fstrong>, the Framework was specified, function-by-function, until most of the high-level security requirements were eventually formally verified. During this work, we also found bugs and usability issues in the Move Prover, which have been fixed to the benefit of all users of Aptos Move.\u003C\u002Fp>\n\u003Cp>This combined work  \u003Cem>gives the Aptos Framework an unmatched level of quality assurance in the blockchain industry and beyond\u003C\u002Fem>. Moving forward, Aptos Labs is committed to maintaining and evolving the verification work as well as improving the Prover itself, keeping it available for builders and auditors across the Aptos ecosystem, pushing the boundaries of software quality in the space.\u003C\u002Fp>\n\u003Cp>\u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fmedium.com\u002Faptoslabs\u002Fsecuring-the-aptos-framework-through-formal-verification-14124d1ed660\">Source\u003C\u002Fa>\u003C\u002Fp>\n\u003Ch2 id=\"About-MoveBit\">About MoveBit\u003C\u002Fh2>\n\u003Cp>MoveBit, a subsidiary brand of BitsLab, is a blockchain security company that specializes in the Move Ecosystem. We are at the forefront of utilizing cutting-edge Formal Verification techniques. The team comprises security professionals with extensive experience in both academia and enterprise. As one of the earliest contributors to the Move ecosystem, we have collaborated closely with Move developers to establish security standards for secure Move applications, making it the most secure Web3 destination.\u003C\u002Fp>\n\u003Cp>\u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fwww.movebit.xyz\u002F?type=getAudit\">Requests a quote\u003C\u002Fa>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Website: \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fwww.movebit.xyz\u002F\">https:\u002F\u002Fwww.movebit.xyz\u002F\u003C\u002Fa>\n\u003C\u002Fli>\n\u003Cli>Twitter: \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Ftwitter.com\u002Fmovebit_\">https:\u002F\u002Ftwitter.com\u002Fmovebit_\u003C\u002Fa>\n\u003C\u002Fli>\n\u003C\u002Ful>","\u002Fmedia\u002Fmovebit\u002F2024\u002F01\u002F6f281789b5f6916b6462bff8c834a944.png","2024-01-11T03:15:00Z","2026-08-11T17:56:38Z","10 min read",true,"Securing the Aptos Framework through formal verification cover image",1792635794928]