Skip to content

Smart Contracts

The Rust SDK provides tools for deploying, interacting with, and querying Move smart contracts on Aptos.

Entry functions are the primary way to interact with smart contracts. Use InputEntryFunctionData for type-safe payload construction:

use aptos_sdk::transaction::InputEntryFunctionData;
// Simple function call
let payload = InputEntryFunctionData::new("0x1::aptos_account::transfer")
.arg(recipient.address())
.arg(1_000_000u64)
.build()?;
let result = aptos.sign_submit_and_wait(&sender, payload, None).await?;

For generic functions, use .type_arg():

let payload = InputEntryFunctionData::new("0x1::coin::transfer")
.type_arg("0x1::aptos_coin::AptosCoin")
.arg(recipient.address())
.arg(500_000u64)
.build()?;
// Quick APT transfer
let payload = InputEntryFunctionData::transfer_apt(recipient.address(), 1_000_000)?;
// Generic coin transfer
let payload = InputEntryFunctionData::transfer_coin(
"0x1::aptos_coin::AptosCoin",
recipient.address(),
1_000_000,
)?;

For full control, construct EntryFunction directly with BCS-encoded arguments:

use aptos_sdk::transaction::{EntryFunction, TransactionPayload};
use aptos_sdk::types::MoveModuleId;
let entry_fn = EntryFunction::new(
MoveModuleId::from_str_strict("0x1::aptos_account")?,
"transfer",
vec![], // No type arguments
vec![
aptos_bcs::to_bytes(&recipient.address())?,
aptos_bcs::to_bytes(&100_000u64)?,
],
);
let payload = TransactionPayload::EntryFunction(entry_fn);
let result = aptos.sign_submit_and_wait(&sender, payload, None).await?;

View functions are read-only and do not modify state:

// JSON-encoded call
let result = aptos
.view(
"0x1::coin::balance",
vec!["0x1::aptos_coin::AptosCoin".to_string()],
vec![serde_json::json!(account.address())],
)
.await?;
println!("Balance: {:?} octas", result);
// BCS-encoded call with typed output
let balance: u64 = aptos
.view_bcs(
"0x1::coin::balance",
vec!["0x1::aptos_coin::AptosCoin".to_string()],
vec![aptos_bcs::to_bytes(&account.address())?],
)
.await?;

List all modules deployed to an account:

let modules = aptos.fullnode().get_account_modules(address).await?;
for module in &modules.data {
if let Some(abi) = &module.abi {
let entry_count = abi.exposed_functions.iter().filter(|f| f.is_entry).count();
let view_count = abi.exposed_functions.iter().filter(|f| f.is_view).count();
println!("{}::{} ({} entry, {} view functions)", abi.address, abi.name, entry_count, view_count);
}
}

Deploying a Move module requires compiling it first, then publishing the bytecode on-chain.

  1. Write your Move module and compile it

    Terminal window
    aptos move compile --save-metadata

    This produces bytecode files (.mv) and a package-metadata.bcs file in the build/ directory.

  2. Read the compiled bytecode

    use std::fs;
    let metadata = fs::read("build/MyModule/package-metadata.bcs")?;
    let module_bytecode = fs::read("build/MyModule/bytecode_modules/my_module.mv")?;
  3. Create the publish transaction

    use aptos_sdk::transaction::EntryFunction;
    use aptos_sdk::types::MoveModuleId;
    let payload = EntryFunction::new(
    MoveModuleId::from_str_strict("0x1::code")?,
    "publish_package_txn",
    vec![],
    vec![
    aptos_bcs::to_bytes(&metadata)?,
    aptos_bcs::to_bytes(&vec![module_bytecode])?,
    ],
    );
  4. Submit the deployment

    let result = aptos
    .sign_submit_and_wait(&deployer, payload.into(), None)
    .await?;

The aptos_contract! macro generates type-safe Rust bindings from a Move module’s ABI. This requires the macros feature flag.

[dependencies]
aptos-sdk = { git = "https://github.com/aptos-labs/aptos-rust-sdk", package = "aptos-sdk", features = ["macros"] }
use aptos_sdk::aptos_contract;
// Generate bindings from an ABI JSON string or file
aptos_contract!(MyContract, "path/to/abi.json");

The macro generates type-safe functions for all entry and view functions in the module, providing compile-time checks for argument types and counts.

The SDK supports NFT operations through entry functions on the Aptos token standards:

// NFT operations use the standard entry function pattern
let payload = InputEntryFunctionData::new("0x4::collection::create_unlimited_collection")
.arg(move_string("My Collection")) // collection name
.arg(move_string("A cool collection")) // description
.arg(move_string("https://example.com")) // URI
.build()?;