0

I'm posting my problem here as I'm new to Aptos and I'm facing an issue I havn't found any solution online before. I've recently joined a team and they are codding using Move that basic multisig escrow contract and I have to test my contract using the integrated CLI for Aptos.

Here is the function I want to test:

module TradeSafeMultisig::tradesafe_multisig {
 use std::vector;
 use std::option::{Self, Option};
 use aptos_std::simple_map::{Self, SimpleMap};
 use aptos_framework::account::{Self, SignerCapability};
 use std::bcs::to_bytes;
 use std::signer;
 use aptos_framework::aptos_coin::AptosCoin;
 use aptos_framework::coin;
 use aptos_framework::aptos_account;
 const DOMAIN_SEPARATOR: vector<u8> = b"aptos_framework::multisig_account";
 struct Proposal has copy, store, drop {
 recipient: address,
 amount: u64,
 timestamp_secs: Option<u64>, // Timestamp of proposal expiration / activation
 votes: SimpleMap<address, bool>, // Tracks votes
 }
 struct MultisigInstance has key, store {
 owners: vector<address>, // Owners of the multisig
 threshold: u64, // Approval threshold
 payment_proposal: Option<Proposal>, // Payment proposal
 refund_proposal: Option<Proposal>, // Refund proposal
 signer_cap: SignerCapability, // Signer capability
 }
 /// Generate a seed for creating the resource account.
 fun create_multisig_account_seed(seed: vector<u8>): vector<u8> {
 let multisig_account_seed = vector::empty<u8>();
 vector::append(&mut multisig_account_seed, DOMAIN_SEPARATOR);
 vector::append(&mut multisig_account_seed, seed);
 multisig_account_seed
 }
 #[test_only]
 public fun create_multisig_account_seed_test(seed: vector<u8>): vector<u8> {
 create_multisig_account_seed(seed)
 }
 /// Create a new multisig instance
 public entry fun create_multisig(
 creator: &signer,
 owners: vector<address>, 
 threshold: u64
 ) {
 assert!(threshold > 0, 1); // Valid threshold
 assert!(threshold <= vector::length(&owners), 2); // Threshold cannot exceed owner count
 let creator_address = signer::address_of(creator);
 let creator_nonce = account::get_sequence_number(creator_address);
 let (multisig_account, multisig_signer_cap) =
 account::create_resource_account(creator, create_multisig_account_seed(to_bytes(&creator_nonce)));
 // Ensure the multisig account is registered for APT transfers
 if (!coin::is_account_registered<AptosCoin>(signer::address_of(&multisig_account))) {
 coin::register<AptosCoin>(&multisig_account);
 };
 move_to(&multisig_account, MultisigInstance {
 owners,
 threshold,
 payment_proposal: option::none<Proposal>(), // No active payment proposal initially
 refund_proposal: option::none<Proposal>(), // No active refund proposal initially
 signer_cap: multisig_signer_cap,
 });
 }

As you can see, the function will update the Global Storage, adding a new multisig related to the user and I want to create a testing workflow that will basically create a multisig for a dummy user, and then executes all the corresponding actions.

I've facing tons of problems trying to test this function as everytime I'm calling my function, this line raise an error

 let creator_nonce = account::get_sequence_number(creator_address);

The error is raising that the compilator cannot access the account's global storage sequence number.

borrow_global<Account>(addr).sequence_number
│ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Test was not expected to error, but it gave a MISSING_DATA (code 4008) error with error message: "Failed to borrow global resource from 0000000000000000000000000000000000000000000000000000000000000001". Error originating in the module 0000000000000000000000000000000000000000000000000000000000000001::account rooted here

The account (signer) I'm using is the basic one imjected by the

#[test(a = @0x1, b = @0x2)]

I think I have to initialize in a way my signer to use it and retrieve it's sequence number but after trying almost every way account::create_account and aptos_framework::create_account it's seems that there's always an error at the end.

I must be doing something completely wrong here and I'm asking for you help here to show me the good practice and architecture for testing my function

Here is the full draft testing function I'm codding on now:

 #[test(a = @0x1, b = @0x2)]
 fun test_create_multisig(a: signer, b: address) {
 // Publish the Account resource at address a
 let creator_address = signer::address_of(&a);
 // let sequence = account::get_sequence_number(&a);
 let owners: vector<address> = vector[
 creator_address,
 b
 ];
 let threshold = 2;
 create_multisig(&a, owners, threshold);
 // let payment_proposal = tradesafe_multisig::view_payment_proposal(signer::address_of(&multisig_account));
 // assert!(option::is_none(&payment_proposal), 1);
 }

Thank you very much in advance to anyone helping me out ! :)

asked Mar 13, 2025 at 12:53

1 Answer 1

1

Alright, I managed to find the correct test structure.

So basically, when starting a Move test, you have absolutely nothing settled up, so you have to initialize almost everything for your test ! I used this repo to understand slowly but surely how it's going

Aptos Repository

So I had to initialize my signer account so it could retrieve it's sequence number and I also had to initialize the APT token as it was not natively deployed in my test environement.

Here is my code now

 use std::signer;
 use std::vector;
 use std::bcs::to_bytes;
 use aptos_framework::account::{Self, SignerCapability};
 use aptos_framework::aptos_coin;
 use aptos_framework::aptos_coin::AptosCoin;
 use aptos_framework::coin;
 use aptos_framework::account::create_signer_for_test;
 use aptos_framework::account::create_account_for_test;
 use aptos_framework::aptos_account;
 
 fun init_aptos_coin() {
 let coin_core = create_signer_for_test(@0x1);
 let (burn_cap, mint_cap) = aptos_framework::aptos_coin::initialize_for_test(&coin_core);
 coin::destroy_burn_cap(burn_cap);
 coin::destroy_mint_cap(mint_cap);
 }
 #[test(xtraa = @0x69610, xtraa2 = @0x69003)]
 public fun test_multisig_initialization(xtraa: &signer, xtraa2: &signer) {
 init_aptos_coin();
 create_account_for_test(signer::address_of(xtraa));
}

This may not be the best way, but so far, it's working and I hope this could help you one day !

answered Mar 15, 2025 at 5:11
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.