move-langaptos

How do I execute a Move script with the Aptos CLI?


Let's say I have a Move script like this:

script {
    use std::signer;
    use aptos_framework::aptos_account;
    use aptos_framework::aptos_coin;
    use aptos_framework::coin;

    fun main(src: &signer, dest: address, desired_balance: u64) {
        let src_addr = signer::address_of(src);

        let balance = coin::balance<aptos_coin::AptosCoin>(src_addr);
        if (balance < desired_balance) {
            aptos_account::transfer(src, dest, desired_balance - balance);
        };

        addr::my_module::do_nothing();
    }
}

This is calling functions on the aptos_coin.move module, which is deployed on chain. What it does isn't so important for this question, but in short, it checks that the balance of the destination account is less than desired_balance, and if so, tops it up to desired_balance.

Notice also how it calls a function in a Move module I've defined:

module addr::my_module {
    public entry fun do_nothing() { }
}

Where do I put these files? Do I need a Move.toml? How do I run my script with the CLI?


Solution

  • Let's run through how to execute a Move script with a step by step example, this should answer all your questions.

    Make a new directory to work from:

    mkdir testing
    cd testing
    

    Setup the Aptos CLI:

    aptos init
    

    The CLI will ask you which network you want to work with (e.g. devnet, testnet, mainnet). It will also ask you for your private key (which looks like this: 0xf1adc8d01c1a890f17efc6b08f92179e6008d43026dd56b71e7b0d9b453536be), or it can generate a new one for you, as part of setting up your account.

    From here, initialize a new Move project:

    aptos move init --name my_script
    

    Now you need to make a file for your script. So, take the script you created above, and put it in sources/, e.g. like this:

    testing/
       Move.toml
       sources/
          top_up.move
    

    In other words, top_up.move should contain the script you included in the question.

    Now do the same thing with the Move module, leaving you with this:

    testing/
       Move.toml
       sources/
          top_up.move
          my_module.move
    

    Now you can compile the script:

    $ aptos move compile --named-addresses addr=81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e
    Compiling, may take a little while to download git dependencies...
    INCLUDING DEPENDENCY AptosFramework
    INCLUDING DEPENDENCY AptosStdlib
    INCLUDING DEPENDENCY MoveStdlib
    BUILDING my_script
    {
      "Result": []
    }
    

    Note how I use the --named-addresses argument. This is necessary because in your code, you refer to this named address called addr. The compiler needs to know what this refers to. Instead of using this CLI argument, you could put something like this in your Move.toml:

    [addresses]
    addr = "b078d693856a65401d492f99ca0d6a29a0c5c0e371bc2521570a86e40d95f823"
    

    Finally you can run the compiled script:

    $ aptos move run-script --compiled-script-path build/my_script/bytecode_scripts/main.mv --args address:b078d693856a65401d492f99ca0d6a29a0c5c0e371bc2521570a86e40d95f823 --args u64:5
    Do you want to submit a transaction for a range of [17000 - 25500] Octas at a gas unit price of 100 Octas? [yes/no] >
    yes
    {
      "Result": {
        "transaction_hash": "0x655f839a45c5f14ba92590c321f97c3c3f9aba334b9152e994fb715d5648db4b",
        "gas_used": 178,
        "gas_unit_price": 100,
        "sender": "81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e",
        "sequence_number": 53,
        "success": true,
        "timestamp_us": 1669811892262502,
        "version": 370133122,
        "vm_status": "Executed successfully"
      }
    }
    

    Note that the path of the compiled script is under build/my_script/, not build/top_up/. This is because it uses the name of the project contained in Move.toml, which is my_script from when we ran aptos move init --name my_script.

    So to answer one of your questions, yes you need a Move.toml, you can't currently just execute a script file on its own with the CLI. The compiler needs this determine what Aptos framework to use for example.

    See the code used in this answer here: https://github.com/banool/move-examples/tree/main/run_script.

    See also how to do this with the Rust SDK instead of the CLI: How do I execute a Move script on Aptos using the Rust SDK?.


    P.S. There is a more streamlined way to execute a script. Instead of running aptos move compile and then aptos move run-script --compiled-script-path separately, you can just do this:

    $ aptos move run-script --script-path sources/my_script.move --args address:b078d693856a65401d492f99ca0d6a29a0c5c0e371bc2521570a86e40d95f823 --args u64:5
    

    This will do both steps with a single CLI command. Note however that there are some major footguns with this approach, see https://github.com/aptos-labs/aptos-core/issues/5733. So I'd recommend using the previous two-step approach for now.