A bug in the Move verifier was recently uncovered and fixed, a program that checks the validity and security of smart contracts written in the Move language. This bug could have allowed attackers to bypass multiple security properties of Move, leading to potentially significant financial damages for protocols based on Aptos or Sui, two blockchain networks that use Move as their smart contract language.
Source Edit in Canva
The importance and features of Move language.
Move is a language for creating blockchain apps that has features just for them. It was originally developed by Meta Platforms (formerly Facebook) as part of its Libra project, which was later shut down. However, the Move language and its open-source implementation were forked by several other projects, such as Aptos, Sui, Starcoin, and 0L. Move aims to provide a safe and expressive way to write smart contracts that can manipulate custom data types, such as coins, tokens, or NFTs. Unlike other languages that use a generic data type for all values, Move allows developers to define their own data types with specific rules and behaviors. For example, Move has a built-in coin type that cannot be copied or deleted, ensuring that coins are always conserved. Move also supports a novel feature called resource types, which are data types that can only be moved (hence the name of the language), not copied or dropped. This means that resources always have a unique owner and location on the blockchain, preventing accidental duplication or loss of valuable assets. Resource types can be used to model any kind of scarce or non-fungible resource, such as tokens, NFTs, keys, or certificates.
What is the Move verifier and what does it do?
The Move verifier is a program that runs before deploying a smart contract written in Move to the blockchain. Its role is to ensure that the contract code does not violate any of the security properties of Move, such as type safety, memory safety, resource safety or arithmetic safety. The verifier performs a series of checks on the contract code and rejects it if any of these checks fail. The verifier does not operate on the human-readable Move source code directly, but on its compiled version called bytecode. Bytecode is a low-level representation of the contract code that can be executed by the blockchain virtual machine. Bytecode is generated by a compiler that translates the Move source code into bytecode. The verifier is an essential component of the Move ecosystem, as it guarantees that any smart contract deployed on the blockchain is safe and compliant with the rules of the language. Without the verifier, malicious or buggy contracts could compromise the integrity and functionality of the blockchain and its applications.
What was the bug and how did it affect Aptos and Sui?
The bug was discovered by Zellic, a security firm hired by Mysten Labs, the developer of Sui blockchain network. Zellic reported the bug to Mysten Labs on March 29th 2023 and published a detailed blog post about it on May 16th 2023. The bug was located in a file called bytecode_verifier.rs
, which is part of the open-source implementation of Move provided by Meta Platforms. This file contains the logic for verifying bytecode modules before deployment. The function verify_dependencies was where the bug happened. It makes sure that all the other modules that the module being checked needs are in agreement and work well together.
The bug happened because Rust's HashMap
data structure was used wrongly. It puts key-value pairs in any order it wants. The function verify_dependencies
used this data structure to keep and check dependencies, but it did not consider that the HashMap
can change the order of its elements for different reasons, such as how the memory is arranged or what hashing algorithm is used. As a result, the function verify_dependencies
could sometimes return different results for the same input, depending on how the HashMap
ordered its elements internally. This created a possibility for an attacker to craft a malicious bytecode module that would pass verification under some conditions but fail under others. Such a module could then exploit this inconsistency to bypass some of the security checks performed by other parts of the verifier, such as type checking or resource checking. This bug affected all blockchain networks that use Move as their smart contract language and rely on Meta Platforms' implementation of Move verifier. This includes Aptos and Sui, two forks of Libra project that aim to create scalable and interoperable blockchains for decentralized finance and social impact applications.
How was the bug fixed and what are the implications?
The bug was fixed by Mysten Labs on March 30th 2023, by replacing the HashMap
data structure with a BTreeMap
, which preserves the order of its elements. The fix was merged into Meta Platforms' Move repository on April 9th 2023, and into Aptos' repository on April 10th 2023. The fix was also applied to other Move-based networks, such as Starcoin and 0L. The fix ensures that the verifier behaves consistently and correctly for all bytecode modules, regardless of how their dependencies are ordered internally. This prevents any potential attacks that could exploit the bug to violate the security properties of Move and cause loss of funds or other damages. The discovery and resolution of this bug highlights the importance of rigorous security auditing and testing for blockchain networks and smart contracts, especially for new and experimental languages such as Move. It also demonstrates the value of open-source collaboration and communication among different projects that share a common code base or technology. The bug also raises some questions about the design and implementation of Move verifier, such as why it relies on a data structure that can introduce non-determinism, or why it does not have more comprehensive test cases to cover all possible scenarios. These questions may inspire further research and improvement for the Move ecosystem and its future development.