Title: How to Write and Deploy Your First Aptos Smart Contract
Introduction
In this hands-on tutorial, you'll build and deploy a minimal “Hello, Aptos!” smart contract on the Aptos blockchain using the Move language and the Aptos CLI. By the end, you'll have:
• Written a Move module that stores a greeting on-chain
• Compiled and published your module to Aptos DevNet
• Invoked your contract to initialize and update the greeting
• Retrieved on-chain data to verify your changes
Let’s dive in.
Prerequisites
Before you begin, make sure you have:
1. Node.js (v16+) installed
2. Rust & Move installed (via Aptos CLI)
3. Aptos CLI (v0.5+) installed and in your PATH (see Source: first-move-module.mdx)
4. A funded DevNet account (we'll use the CLI faucet)
5. Git (optional, for cloning templates)
6. A terminal/command prompt
Step-by-Step Guide
Step 1: Configure Your Aptos CLI & Account
First, verify your CLI installation:
```bash
aptos --version
```
Initialize your local Aptos configuration and create a new account:
```bash
aptos init --profile default
```
This command prompts you for a profile name (we'll use default) and generates a key pair plus a local config file (~/.aptos/config.yaml).
Next, fund your account on DevNet:
```bash
aptos account fund-with-faucet --profile default --amount 1
```
This gives you 1 APT to pay for gas when publishing and transacting (Source: first-move-module.mdx).
Step 2: Create and Initialize a Move Package
Create a new directory for your contract and initialize a Move package:
```bash
mkdir hello_world
cd hello_world
aptos move init --name hello_world
```
This generates:
• Move.toml — your package manifest
• A `sources/` folder for your modules
• A `Move.toml` pointing at `sources/` by default (Source: smart-contracts.mdx)
Step 3: Write Your Move Module
Open `sources/hello_world.move` and replace its contents with the following:
```move
address 0x1 {
module hello_world {
use std::signer;
use std::vector;
/// A resource that holds our on-chain greeting.
resource struct Greeting { value: vector<u8> }
/// Entry function to store a default greeting.
public entry fun init(account: &signer) {
// Move the Greeting resource under the caller’s address.
move_to<Greeting>(account, Greeting { value: b"Hello, Aptos!" });
}
/// Entry function to update the existing greeting.
public entry fun update(account: &signer, new_value: vector<u8>) {
let addr = signer::address_of(account);
// Borrow the resource and mutate its `value` field.
let greeting_ref = borrow_global_mut<Greeting>(addr);
greeting_ref.value = new_value;
}
}
}
```
Key points:
- We declare a Greeting resource that wraps a `vector<u8>` (bytes) for text.
- `init` publishes the Greeting under the signer’s address.
- `update` mutates the stored resource.
(Source: first-move-module.mdx)
Step 4: Compile Your Module
From the `hello_world` root directory, run:
```bash
aptos move compile --package-dir .
```
If all goes well, you should see “Build finished with no errors.” This ensures your Move code is syntactically valid and type-safe.
Step 5: Publish (Deploy) to DevNet
Deploy your module to the chain:
```bash
aptos move publish --package-dir . --profile default
```
You’ll see a transaction hash and confirmation once your module is live at your account address. Note the “Sender” address; that’s where our module now resides.
Step 6: Initialize Your Greeting On-Chain
Invoke your `init` entry function to create the resource:
```bash
# Replace 0x1 with your sender address if you used a different one.
MODULE_ADDR=$(aptos account list --profile default | grep Address | awk '{print $2}')
aptos move run \
--function-id "${MODULE_ADDR}::hello_world::init" \
--profile default
```
This transaction stores the `Greeting` resource on-chain under your address.
Step 7: Read Your On-Chain Greeting
Use the CLI to fetch your resource and view the stored bytes:
```bash
aptos account resource \
--account $MODULE_ADDR \
--resource-type "${MODULE_ADDR}::hello_world::Greeting" \
--profile default
```
You’ll see something like:
```json
{
"parsed": {
"value": [72,101,108,108,111,44,32,65,112,116,111,115,33]
},
...
}
```
Those numbers are ASCII codes for “Hello, Aptos!”.
Step 8: Update Your Greeting
Let’s change the greeting to “Aptos FTW!”. Note we need to pass the new string as a `vector<u8>` literal by encoding to hex or bytes. For simplicity, we’ll pass ASCII codes directly:
```bash
aptos move run \
--function-id "${MODULE_ADDR}::hello_world::update" \
--args 65 112 116 111 115 32 70 84 87 33 \
--profile default
```
This updates the `Greeting` resource.
Step 9: Verify the Updated Greeting
Fetch the resource again:
```bash
aptos account resource \
--account $MODULE_ADDR \
--resource-type "${MODULE_ADDR}::hello_world::Greeting" \
--profile default
```
Now you’ll see the ASCII codes for “Aptos FTW!”.
The Full Code
Below is the complete, copy-pasteable Move module for your `sources/hello_world.move`. Make sure your `Move.toml` name matches `hello_world`.
```move
address 0x1 {
module hello_world {
use std::signer;
use std::vector;
/// A resource that holds our on-chain greeting.
resource struct Greeting { value: vector<u8> }
/// Entry function to store a default greeting.
public entry fun init(account: &signer) {
move_to<Greeting>(account, Greeting { value: b"Hello, Aptos!" });
}
/// Entry function to update the existing greeting.
public entry fun update(account: &signer, new_value: vector<u8>) {
let addr = signer::address_of(account);
let greeting_ref = borrow_global_mut<Greeting>(addr);
greeting_ref.value = new_value;
}
}
}
```
Move.toml (auto-generated by `aptos move init`):
```toml
[package]
name = "hello_world"
version = "0.0.1"
authors = ["Your Name <you@example.com>"]
edition = "2022"
[addresses]
# Replace 0x1 with your actual deployer address after publishing.
hello_world = "0x1"
[dependencies]
```
Conclusion
Congratulations! You’ve:
• Written a Move module that manages on-chain data
• Compiled and published it to Aptos DevNet
• Interacted via CLI to initialize, update, and read the resource
Next Steps
• Integrate this module into a frontend using the Aptos TypeScript SDK (see multi-agent and sponsoring docs in the TS SDK guides)
• Dive deeper into Move with the Move Book or Aptos Move examples (Source: smart-contracts.mdx)
• Explore advanced patterns: capabilities, coin standards, and multi-signer transactions
Head over to the Aptos Discord to show off your first smart contract and keep building!