---
# System prepended metadata

title: How to Get Started with ZKsync as a Solidity Developer

---

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!