I know there is a Move module (smart contract) on chain with a function that looks like this:
public entry fun do_nothing() {}
I know it is deployed at 6286dfd5e2778ec069d5906cd774efdba93ab2bec71550fa69363482fbd814e7::other::do_nothing
. You can see the module in the explorer here.
I have a Move module of my own that looks like this.
Move.toml
:
[package]
name = 'mine'
version = '1.0.0'
[dependencies.AptosFramework]
git = 'https://github.com/aptos-labs/aptos-core.git'
rev = 'main'
subdir = 'aptos-move/framework/aptos-framework'
[addresses]
my_addr = "81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e"
other_addr = "6286dfd5e2778ec069d5906cd774efdba93ab2bec71550fa69363482fbd814e7"
sources/mine.move
:
module my_addr::mine {
use other_addr::other::do_nothing;
public entry fun do_stuff() {
do_nothing();
}
}
As you can see, I'm telling the compiler where the other
module is by setting other_addr = "6286dfd5e2778ec069d5906cd774efdba93ab2bec71550fa69363482fbd814e7"
. However, when I try to compile my Move module, it fails, saying "unbound module", meaning it doesn't know what the "other" module is.
$ aptos move compile --named-addresses my_addr="`yq .profiles.default.account < .aptos/config.yaml`"
Compiling, may take a little while to download git dependencies...
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING mine
error[E03002]: unbound module
┌─ /Users/dport/github/move-examples/call_other_module/mine/sources/mine.move:2:9
│
2 │ use other_addr::other::do_nothing;
│ ^^^^^^^^^^^^^^^^^ Invalid 'use'. Unbound module: '(other_addr=0x6286DFD5E2778EC069D5906CD774EFDBA93AB2BEC71550FA69363482FBD814E7)::other'
error[E03005]: unbound unscoped name
┌─ /Users/dport/github/move-examples/call_other_module/mine/sources/mine.move:5:9
│
5 │ do_nothing();
│ ^^^^^^^^^^ Unbound function 'do_nothing' in current scope
{
"Error": "Move compilation failed: Compilation error"
}
Why is compilation failing? Why can't the compiler figure it out for me based on the ABIs of the Move modules it finds at other_addr
on chain?
In order to publish a Move module that calls a function in another Move module, you need its source code. This is true of all Move modules, not just your own. You'll notice in Move.toml
there is already a dependency on AptosFramework
. This is what allows you to call all the framework functions, e.g. those related to coins, tokens, signer, timestamps, etc.
So to make this work, you need to have access to the source.
If you have access to the source in another git repository, you can tell the compiler where to find the other
module by adding this to your Move.toml:
[dependencies.other]
git = 'https://github.com/banool/move-examples.git'
rev = 'main'
subdir = 'call_other_module/other'
This is telling the compiler, "the source code for other
can be found in the call_other_module/other/
directory at that git repo".
If you have the source code locally, you can do this instead:
[dependencies.other]
local = "../other"
Where the argument for local
is the path to the source code.
If you don't have the source, you can try to download it. By default, when someone publishes a Move module, they include the source code alongside it.
First try to download the code:
cd /tmp
aptos move download --account 6286dfd5e2778ec069d5906cd774efdba93ab2bec71550fa69363482fbd814e7 --package other
If the source code was indeed deployed on chain, you should see this:
Saved package with 1 module(s) to `/tmp/other`
{
"Result": "Download succeeded"
}
Inside /tmp/other
you'll find the full source, including Move.toml
and sources/
.
From here, you can just follow the steps for Source: Local
above.
Note: The value for --package
should match the name
field in Move.toml
of the deployed code. More to come on how to determine this based on on-chain data.
If you ran aptos move download
and saw this:
module without code: other
Saved package with 1 module(s) to `/private/tmp/other_code/other`
{
"Result": "Download succeeded"
}
You'll find that sources/other.move
is empty.
This means the author published the code with this CLI argument set:
--included-artifacts none
Meaning they purposely chose not to include the source on chain.
Unfortunately at this point you're out of luck right now. It is a hard requirement of compilation that if you want to call a function in another Move module, you must have the source for that module. There is work in the pipeline that should enable decompilation of Move bytecode, but that's not ready yet.
I hope this helps, happy coding!!
The code used in this answer can be found here: https://github.com/banool/move-examples/tree/main/call_other_module.