This repository contains a proof of concept to compile the Move language to WASM, for running it in Arbitrum's Stylus Environment.
The generated code can be deployed to the Arbitrum chain as a Stylus contract and called using Solidity interfaces.
- Entrypoint router: Public Move functions are handled by a router to allow using ABI function selectors.
- Function Interface translation and internal function calls
- Basic operations: Constant definition, literals, local variables move and copy is implemented for the following types:
- u8, u16, u32, u64
- u128, u256
- bool
- address
- vector
- structs
- Primitive types: The following primitive types are supported:
- integers (u8, u16, u32, u64, u128, u256)
- booleans
- address
- signer
- references
- tuples and unit
- vector
- User defined datatypes: Structs and Enums
- Structs
- Enum
- Operations: The following operations are supported:
- Arithmetic operations (addition, subtraction, multiplication, division, mod)
- Boolean operations (and, or)
- Bitwise/bitshift operations (left/right shift, and, or, xor)
- Equality operations
- Comparisons (less than, less or equal, more than, more or equal) on all integer types
- Casting
- Vector operations: The following vector operations are supported:
- Push back
- Pop back
- Length
- Borrow fields (mutable and immutable)
- Support for the import and usage of foreign structs/functions within the same package and from external packages.
- Support functions with generic parameters.
- Support for native functions (functions directly implemented in the MoveVM, ported as runtime or host-io functions inside WASM and tailored for EVM/Arbitrum).
- Struct/Enums packing and unpacking, mutable/immutable borrow of fields.
- Support the init function, used as constructor of the contract.
- Support
deletesupport for storage objects. - Support Solidity's
fallbackandreceivefunctions.
The stylus-framework package serves a role similar to the sui-framework package. Its primary purpose is to provide Arbitrum/EVM-specific operations required for interacting with the blockchain and for enforcing semantic aspects of the language—most notably, the object-centric model.
account.moveProvides functions for querying account information on the blockchain:get_account_code_size: retrieves the size of code in bytes at a given address (equivalent to EVM'sEXT_CODESIZE).get_account_balance: retrieves the ETH balance in wei of an account at a given address (equivalent to EVM'sBALANCEopcode).
contract_calls.moveEnables cross-contract calls with support for gas limits, value transfers, and delegate calls. Provides:CrossContractCallstruct for configuring and executing calls to other contracts.ContractCallResultandContractCallEmptyResulttypes for handling call results and status codes.
dynamic_field.moveImplements dynamic fields that can be added to objects after construction. Provides functions for adding, borrowing, removing, and checking existence of dynamic fields.dynamic_field_named_id.moveExtends dynamic field functionality to work withNamedIdobjects, providing a wrapper arounddynamic_fieldoperations for objects with named identifiers.error.moveProvides therevertfunction for reverting the current transaction with a custom error value.event.moveProvides functions for emitting ABI-encoded events/logs.fallback.moveUtilities for the fallack function. Defines theCalldatastruct representing data passed to fallback functions. Provides methods to access calldata as avector<u8>or query its length, similar to how calldata is handled in Solidity fallback functions.object.moveManages storage-backed objects. It defines:UIDandIDtypes, used in structs with thekeyability to uniquely identify stored objects.new, a function for creating globally unique IDs (represented by theUIDstruct).delete, a function for removing structs from storage.
sol_types.moveDefines Solidity-compatible fixed-size byte types (Bytes1throughBytes32) and provides conversion functions to transform these types intovector<u8>for interoperability with Solidity contracts.table.moveImplements a map-like collection where keys and values are stored using the object system rather than within theTablevalue itself. TheTablestruct acts as a handle for retrieving entries. Provides standard map operations: add, borrow, remove, and query operations likecontains,length, andis_empty.transfer.moveImplements object transfer functions that enforce Sui's ownership model:transfer: moves an object to a single owner; only the owner can read and write it.share_object: shares an object; once shared, it can be read and written by anyone.freeze_object: freezes an object; once frozen, it can be read by anyone but not modified.
tx_context.moveDefines theTxContextobject, which provides methods for accessing information about the current transaction.types.moveProvides theis_one_time_witnessfunction, which checks if a struct is a one-time witness.
Set up the stylus environment and install required tools:
make setup-stylusbuild the example contract:
make build-exampletest and debug wasm:
make test-move-bytecode-to-wasm
make disassemblecheck web assembly output at arbitrum dev node:
make check-example
make check-example-primitivesdeploy to arbitrum dev node (local):
make deploy-example
make deploy-example-2
make deploy-example-primitives
make deploy-counter
make deploy-counter-with-initrun test interactions (make sure to setup a .env file):
make example-interaction
make example-interaction-2
make example-interaction-primitives
make example-counter
make example-counter-with-init
make example-dog-walkerIn the example/sources folder, among contracts that only demonstrates the Move Language capabilities, there are several fully functional contracts that showcase different aspects of the Move language semantics:
-
counter.move- Uses the
share_objectfunction to make counters globally accessible so anyone can increment their value. - Emits an event for each created counter so users can capture its ID.
- Allows seamless retrieval of objects from storage by their ID.
- Enforces access control in the
set_valuefunction using theTxContext.sendermethod.
- Uses the
-
counter_with_init.move- Same as
counter.move, but the counter is created with a constructor function (init).
- Same as
-
counter_named_id.move- Variant of the counter contract using
NamedIdfor object identification instead of standardUID. - Demonstrates named object management with deterministic addressing.
- Provides the same functionality as
counter.movewith alternative ID management.
- Variant of the counter contract using
-
dog_walker.move- Enforces access control using the capability pattern.
- Uses the
transferfunction to assign the capability to a unique owner. - Emits an event when the dog goes out for a walk.
- Prevents the action if the contract is not called by the dog's owner.
-
erc20.move- Full implementation of the ERC-20 token standard.
- Includes mint, burn, transfer, and approval functionality.
- Uses dynamic fields for storing balances and allowances.
- Emits standard Transfer and Approval events.
- Demonstrates initialization with constructor (
init) creating shared and frozen objects for token metadata.
-
erc721.move- Complete implementation of the ERC-721 (NFT) standard with metadata extension.
- Supports minting, burning, transferring, and approving NFTs.
- Implements operator approvals for managing multiple tokens.
- Uses dynamic fields for tracking ownership, balances, and approvals.
- Includes safe transfer checks for receiver contracts.
- Demonstrates interface detection via
supports_interface.
-
delegated_counter.move&delegated_counter_logic_*.move- Demonstrates the proxy/delegate pattern for upgradeable contracts.
- Main contract delegates increment operations to external logic contracts.
- Supports changing the logic address dynamically via
change_logic. - Shows how to maintain state while upgrading contract logic.
- Tests delegation with modifications before and after delegated calls.
-
delegated_counter_named_id.move&delegated_counter_named_id_logic_*.move- Same delegation pattern as
delegated_counter.movebut usingNamedIdfor object identification. - Demonstrates how named IDs work with cross-contract calls and delegation.
- Same delegation pattern as
-
cross_contract_call.move- Demonstrates cross-contract calls to external ERC-20 contracts.
- Shows how to query balance, total supply, and execute transfers on external tokens.
- Uses the
contract_callsmodule from the stylus-framework.
-
hello_world.move- Comprehensive demonstration of basic Move language features.
- Includes constants, generic types, structs, enums, and function calls.
- Tests local variable handling, copying, and moving semantics.
-
primitives_and_operations.move- Showcases all supported primitive types and operations.
- Demonstrates arithmetic, bitwise, boolean, and comparison operations.
- Includes casting between different integer types.
-
revert_errors.move- Demonstrates custom error handling with the
revertfunction. - Shows ABI-encoded error types with various data structures.
- Includes examples of standard, custom, and nested struct errors.
- Demonstrates custom error handling with the
-
simple_counter.move- Basic counter implementation without storage backing (uses
dropability). - Includes unit tests demonstrating Move's testing capabilities.
- Shows test patterns including
#[test]and#[expected_failure]attributes.
- Basic counter implementation without storage backing (uses
-
stack.move- Implements a generic stack data structure using the wrapper type pattern.
- Demonstrates generic programming with type parameters.
- Shows safe stack operations with
Optiontypes for empty stack handling.