MOVE, a rising smart contract language, is getting increasingly more attraction from developer communities as the upcoming launch of Aptos and SUI. Also, as a new language that comes along with a unique coding philosophy and underlying storage data structure, the best practice of publishing a move module (also referred as contract deployment in this article) is one of the most heated and urgent issues heavily discussed in the dev community. It is such a critical issue that it will greatly effect the security, decentralization and extensibility of the launching protocols. In this article, we will discuss the following question on Aptos system for MOVE:
- How Move code storage is different from Solidity, and what does this implies?
- What are the existing solutions? And what’s their advantages & disadvantages?
- Comparison of the existing solutions.
Note: There is a lot of on-going on Aptos ecosystem, and the conclusions of this article might be not accurate or out-of-date. We would love to hear your suggestions and feedbacks and make the change accordingly.
1. Code storage: Solidity vs MOVE
In this part, we will compare MOVE to the most popular smart contract language Solidity in code storage mechanism.
In EVM based chains, all smart contract has a unique address called “contract owned address”. The contract account lives in the same hierarchy as the deployer account, where the code is stored within, and does not bind with the deployer address after deployment.
For upgradeable smart contract, the implementation is a bit complicated shown as follows:
- The deployer deploys the proxy contract that have two key storages: 1. owner that point to the deployer address; 2. Code that point to the upgradeable contract address.
- The owner storage field specifies which account has the permission to upgrade the smart contract, and can be changed to any account later.
- The code storage field specifies the contract code to do delegate call when the proxy smart contract is called. A contract upgrade is basically deploying a new contract and change the code field to redirect the delegate call.
Thus, Ethereum implements the upgradeable contract with delegate call even the code field is immutable.
On the other hand, MOVE has a totally different storage model for code deployment. In MOVE system, the code data is stored under the code module under the resource account.
For contract upgrade, MOVE execute the upgrade logic in system module code.move where the upgrade policy and compatibility is checked before the code deployment. After compatibility check, the code written in the resource is replaced through a native function call and will execute the new logic.
There are several implications from the MOVE code storage model:
- According to contract upgrade policy, the owner of the code has the full control of the upgrade permission.
- The owner of the code is immutable after the initial deployment.
- Thus the deployer address own the upgrade privilege forever after the deployment.
1.3 Key Difference
EVM has the concept of contract owned address — each contract has the same data structure as the account model. And the upgradeable permission of a contract is specified in the storage in proxy code, which can be overwritten to another owner with full flexibility. The relationship between the owner and the contract is be viewed as “soft link”.
However, in MOVE ecosystem, because of the unique data storage structure defined by Aptos MOVE, the code is published directly under an address, and the address can not be changed after deployment, which can be viewed as “Hard link”.
Thus the default MOVE module deployment method will potentially expose some vulnerability in protocol maintenance and upgrade.
2. Solutions for MOVE module publish
There are some existing solutions for MOVE module publish.
Vulnerability in deployment with a single signed walletThe simplest and the default way (as written in Aptos handbook) is to deploy the smart contract in MOVE is through a single signed wallet.
However, as we discussed in 2.3, because of the immutable connection between the deployer address and the smart contract code, the owner of the private key of the deployer address is the only individual or entity that takes the full control of the protocol. Since the implementation of a move module can be upgraded to any logic, the protocol will be under huge risk if the deployer account is compromised.
Solution 1: Immutable smart contract
One simple solution is to make the smart contract immutable. If the smart contract is not upgradeable, there will not be vulnerability related to upgrade permission. However, immutable smart contract is also dangerous since there is no way for the developer to fix bugs, and is very limited in extensibility.
Solution 2: Aptos native multi-sig wallet
Aptos has a native implementation of multi-signer authentication. Multi-sig wallet can help decrease the risk of single point of failure, since it will require multiple signatures to conduct a contract upgrade. Thus the holder of the multi-sig can be distributed among project team members, and even community leads from DAO voting. This will greatly mitigate the risk of single point failure as mentioned in solution 1.
However, the native multi-sig solution is hard to use:
- It will require multiple signatures to be aggregated on a single instance for each operation of the wallet. All the operations need to be done off-chain.
- There is no UI interface.
- All operations need to be done in one single operation — There is no asynchronized way to store the transaction signature and payload.
Solution 3: Deploy with a resource account
Other than the multi-sig solutions, there are also some protocols that has adopted the solution of combining the resource account and governance smart contract for smart contract deployment. The adopter includes Pyth network and Wormhole. Here is a diagram shows the deployment process with governance contracts from Code reference of Pyth.
- The project first create a deployer account.
- Deploy a governance smart contract from the deployer.
- During init_module of the governance contract, a resource account is created and the signer capability of the resource account is stored in governance resource.
- The admin is a multi-sig of wormhole guardians. In practice, the multi-sig adopted by wormhole is a 13 of 19 guardians verified via VAA. The guardian governance public keys are stored and maintained in state.move.
- The access to all governance operations are defined in goveranance through VAA verification.
- For contract upgrade, the guardians first sign off the contract upgrade hash off-chain, and submit to blockchain using VAA. The upgrade hash will be stored in smart contract.
- Another function call to contract_upgrade::upgrade is submitted with metadata and code bytes. The data are verified against the upgrade hash in the last step, and the code will be published under system module code.move.
The solution has the following benefits:
- The deployer address does not have direct control of the contract upgrade logic.
- The the admin account of the protocol can be assigned dynamically — No longer a “hard link” to the deployer’s address. The admin can be changed after deployment.
- The system structure is able to achieve almost the same flexibility and dev experience as mentioned in 2.1 (Ethereum contract upgrade logic) in MOVE ecosystem.
- The protocol control logic (parameter changes, contract upgrade) is performed through the governance smart contract, not directly exposed to admin, which adds an additional security layer.
However, the solution has its short comings as well.
- The solution is super complicated. You will need to implement another governance contract that need to define all governance operations prior to deployment.
- Since the governance contract has to be upgradeable for future accommodation of adding more governance operations, the deployer address still have the full control of the protocol by upgrading the governance contract, E.g. change the admin, change the operation, e.t.c.
- A complete solution shall be that both the deployer and admin are multi-sig wallets, and they do not overlap in owners.
The complete solution shall involve:
- Two smart contracts: governance and pyth.
- Two multi-sig wallets: deployer and admin.
Solution 4: Momentum safe
Momentum Safe is the first and most extensible multi-sig solution built on Aptos move ecosystem, currently alive on both Devnet and Testnet. One of the key feature momentum safe offers is the contract deployment with the multi-sig wallet.
Momentum safe is building on top of Aptos native Multi-Ed25519 with an additional dummy public key specifier. The overall structure can be generalized as follows:
- The final transaction of Momentum safe is executed with Aptos native Multi-Ed25519 schema, making the product as secure as the Aptos core protocol.
- The transaction payload and signatures of the multi-sig transaction is cached and stored in Move module Momentum Safe. The Move module will help with the momentum safe multi-sig creation, creating a smooth asynchronize experience for end users.
- On top of the MOVE module, there is a well design UI that provide a user-friendly interface to interact with the smart contract. The web app is currently available on both Devnet and Testnet.
- Other than the UI interface, Momentum safe is also offering the interactive CLI, and SDK for developers to interact with momentum safe smart contract.
So with these additional layer of features added to Aptos native multi-sig implementation, Momentum safe is able to provide all features that the native multi-sig provides but also extra features including:
- Asynchronize transaction initialization and signature collection.
- Allow owner of the multi-sig to operate remotely.
- Provide a UI interface. (https://devnet.m-safe.io)
If you want to deploy a smart contract with momentum safe, you may directly use the script for the handbook MOVE module deployment. The handbook will walk you through a script to initialize the transaction to deploy MOVE modules. After transaction initialization, the other owners are able to approve and confirm the transaction in Web UI. So this will make it just as easy as deploying with a single signed account, while still adding another security layer to protect the code and protocol.
Moreover, momentum safe will offer key rotation features to rotate your existing single signed wallet to a momentum safe in the near future. This will add more flexibility to the contract deployment — you may deploy with single signed wallet, and key rotate to adopt momentum safe solution later. Please stay tuned for further updates.
In this article, we have analyzed some move contract deployment best practices.
First, the code storage model is different in Solidity vs Move — The connection between the deployer and the contract code is in Solidity is mutable with flexibility, while the connection in Move is immutable, which analogize to a “hard link”. This specific code storage will expose some vulnerability when engaged with smart contract upgrade, and the whole protocol could be in danger if the deployer private key is compromised.
Regarding this issue, we propose several solutions:
- Deploy an immutable smart contract. This will fully resolve the issue but will leave the protocol no room for further changes or new features.
- Deploy with a native multi-sig wallet. The solution can provide a certain level of security. However, the user experience is the worst since user will need to aggregate the signature off-chain for each transaction.
- Deploy with resource account as Pyth. The solution offers flexibility in owner change, no direct exposure of smart contract entry function to the public, e.t.c. However, the solution is complicated that will require some extra engineering resources to implement the governance contract.
- Deploy with Momentum Safe. The solution will offer the same level of security as deploying using a native multi-sig wallet. Additionally, it provides a user friendly interface, and momentum safe has made the experience smooth, and as easy as using a single signed account.
In conclusion, we evaluate contract deployment with Momentum Safe to be the most practical way to deploy a smart contract for its simplicity, user friendliness, and security, and we would recommend every team on Aptos to adopt momentum safe for contract deployment.
Some useful links
If you would like to learn more about momentum safe, please check out the following links:
- Devnet web app: https://devnet.m-safe.io/
- Testnet web app: https://testnet.m-safe.io/
- Website: https://m-safe.io/
- Gitbook: https://doc.m-safe.io/msafe/
- Github for CLI (with scripts and SDK): https://github.com/Momentum-Safe/CLI-MSafe
- Handbook for interactive CLI: https://doc.m-safe.io/msafe/cli-interactive-tool
- Handbook for deployment using a script: https://doc.m-safe.io/msafe/sdk/deploy-a-move-module
- Handbook for calling an entry function with a script: https://doc.m-safe.io/msafe/sdk/call-an-entry-function
- How to reach us? email@example.com
Throughout the creation of this article, we have received valuable inputs coming from our friends and partners. We would like to appreciate our gratitude for the discussion, insights, and feedbacks received from these talented engineers and entrepreneurs.
- Boris Povod @ Pontem network
- Csongor Kiss @ Wormhole
- Robert Chen @ OtterSec
- alnoki @ Econia Labs
- Rei @ Soffl3