How to deploy a contract in testnet using RUST-SDK?

Hi there :wave:
Trying to deploy my dapp in testnet using next test, but have an error

Test:

use dotenv::dotenv;
use fuels::prelude::*;

const RPC: &str = "https://node-beta-2.fuel.network/graphql";

#[tokio::test]
async fn deploy_token_contract() {
    let provider = match Provider::connect(RPC).await {
        Ok(p) => p,
        Err(error) => panic!("❌ Problem creating provider: {:#?}", error),
    };

    dotenv().ok();
    let secret = match std::env::var("SECRET") {
        Ok(s) => s,
        Err(error) => panic!("❌ Cannot find .env file: {:#?}", error),
    };

    let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider));

    let token_contract_id = Contract::deploy(
        "out/debug/token_contract.bin",
        &wallet,
        TxParameters::default(),
        StorageConfiguration::with_storage_path(Some(
            "./out/debug/token_contract-storage_slots.json".to_string(),
        )),
    )
    .await;
    let token_contract_id = match token_contract_id {
        Ok(id) => id,
        Err(error) => panic!("❌ Problem deploing the dapp: {:#?}", error),
    };

    println!("✅ Contract deployed @ {token_contract_id}");
}

Error:

   Compiling tests v0.0.0 (/Users/alexey/projects/fuel-token-standard/token_contract)
    Finished test [unoptimized + debuginfo] target(s) in 2.71s
     Running tests/harness.rs (target/debug/deps/tests-ebb925acf86f95a5)

running 1 test
thread 'actions::deploy_token_contract::deploy_token_contract' panicked at '❌ Problem deploing the dapp: ProviderError(
    "Response errors; Unknown field \"consensus\" on type \"Block\".; Unknown type \"Genesis\"; Unknown type \"PoAConsensus\"",
)', tests/actions/deploy_token_contract.rs:32:23
stack backtrace:
   0: rust_begin_unwind
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:142:14
   2: tests::actions::deploy_token_contract::deploy_token_contract::{{closure}}
             at ./tests/actions/deploy_token_contract.rs:32:23
   3: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/future/mod.rs:91:19
   4: <core::pin::Pin<P> as core::future::future::Future>::poll
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/future/future.rs:124:9
   5: <core::pin::Pin<P> as core::future::future::Future>::poll
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/future/future.rs:124:9
   6: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:541:57
   7: tokio::runtime::coop::with_budget
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/coop.rs:102:5
   8: tokio::runtime::coop::budget
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/coop.rs:68:5
   9: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:541:25
  10: tokio::runtime::scheduler::current_thread::Context::enter
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:350:19
  11: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:540:36
  12: tokio::runtime::scheduler::current_thread::CoreGuard::enter::{{closure}}
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:615:57
  13: tokio::macros::scoped_tls::ScopedKey<T>::set
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/macros/scoped_tls.rs:61:9
  14: tokio::runtime::scheduler::current_thread::CoreGuard::enter
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:615:27
  15: tokio::runtime::scheduler::current_thread::CoreGuard::block_on
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:530:19
  16: tokio::runtime::scheduler::current_thread::CurrentThread::block_on
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/scheduler/current_thread.rs:154:24
  17: tokio::runtime::runtime::Runtime::block_on
             at /Users/alexey/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/runtime/runtime.rs:282:47
  18: tests::actions::deploy_token_contract::deploy_token_contract
             at ./tests/actions/deploy_token_contract.rs:35:5
  19: tests::actions::deploy_token_contract::deploy_token_contract::{{closure}}
             at ./tests/actions/deploy_token_contract.rs:7:7
  20: core::ops::function::FnOnce::call_once
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5
  21: core::ops::function::FnOnce::call_once
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
test actions::deploy_token_contract::deploy_token_contract ... FAILED

failures:

failures:
    actions::deploy_token_contract::deploy_token_contract

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 4 filtered out; finished in 0.76s

error: test failed, to rerun pass '-p tests --test tests'
1 Like

I have the same issue when I use RPC url like

2 Likes

Hi, could you please provide the versions you are using for forc, fuel-core, and fuels?

forc --version
fuel-core --version

and your fuels version is specified in your Cargo.toml

@matt

forc 0.31.1
fuel-core 0.14.1
fuels = { version = "0.32", features = ["fuel-core-lib"] }

If you want to deploy to the testnet v2 you are going to have to downgrade your fuels version to work with your version of forc and fuel-core. Try fuels version 0.31

panicked at 'called `Result::unwrap()` on an `Err` value: ProviderError("Response errors; Unknown type \"ExcludeInput\"; Unknown type \"ExcludeInput\"; Unknown field \"resourcesToSpend\" on type \"Query\". Did you mean \"coinsToSpend\"?; Unknown field \"messageId\" on type \"Message\".")', tests/harness.rs:54:63

Could you post your code somewhere so we can look at it?

sure

Repo
Test File

I’m getting 404 errors when trying to view the links you sent

Oh sorry it was private, please try again

This compiles and runs on my computer (one test still fails). Make sure you change your fuels version to 0.31 (this isn’t the case for what’s on github rn)

use fuels::prelude::*;

abigen!(TestToken, "out/debug/token_contract-abi.json");

pub struct WaletsSetup {
    pub wallet_owner: WalletUnlocked,
    pub wallet1: WalletUnlocked,
    pub wallet2: WalletUnlocked,
}

pub mod abi_calls {
    use fuels::contract::contract::CallResponse;

    use super::*;

    pub async fn initialize(
        contract: &TestToken,
        mint_amount: u64,
        address: Address,
    ) -> Result<CallResponse<()>, Error> {
        contract
            .methods()
            .initialize(mint_amount, address)
            .call()
            .await
    }

    pub async fn get_mint_amount(contract: &TestToken) -> Result<CallResponse<u64>, Error> {
        contract.methods().get_mint_amount().call().await
    }
    pub async fn name(contract: &TestToken) -> Result<CallResponse<fuels::core::types::SizedAsciiString<9>>, Error> {
        contract.methods().name().call().await
    }
    pub async fn symbol(contract: &TestToken) -> Result<CallResponse<fuels::core::types::SizedAsciiString<4>>, Error> {
        contract.methods().symbol().call().await
    }
    pub async fn decimals(contract: &TestToken) -> Result<CallResponse<u8>, Error> {
        contract.methods().decimals().call().await
    }

    pub async fn set_mint_amount(
        contract: &TestToken,
        mint_amount: u64,
    ) -> Result<CallResponse<()>, Error> {
        contract.methods().set_mint_amount(mint_amount).call().await
    }

    pub async fn mint_coins(
        contract: &TestToken,
        mint_amount: u64,
    ) -> Result<CallResponse<()>, Error> {
        contract.methods().mint_coins(mint_amount).call().await
    }

    pub async fn burn_coins(
        contract: &TestToken,
        burn_amount: u64,
    ) -> Result<CallResponse<()>, Error> {
        contract.methods().burn_coins(burn_amount).call().await
    }

    pub async fn get_balance(contract: &TestToken) -> Result<CallResponse<u64>, Error> {
        contract.methods().get_balance().call().await
    }

    pub async fn transfer_token_to_output(
        contract: &TestToken,
        coins: u64,
        asset_id: ContractId,
        address: Address,
    ) -> Result<CallResponse<()>, Error> {
        contract
            .methods()
            .transfer_token_to_output(coins, asset_id, address)
            .call()
            .await
    }

    pub async fn transfer_coins(
        contract: &TestToken,
        coins: u64,
        address: Address,
    ) -> Result<CallResponse<()>, Error> {
        contract
            .methods()
            .transfer_coins(coins, address)
            .append_variable_outputs(1)
            .call()
            .await
    }
    pub async fn mint(contract: &TestToken) -> Result<CallResponse<()>, Error> {
        contract
            .methods()
            .mint()
            .append_variable_outputs(1)
            .call()
            .await
    }
}

pub mod setup_utils {
    use super::*;

    pub async fn setup_wallets() -> WaletsSetup {
        let initial_amount = 1000000000;
        let num_wallets = 3;
        let num_coins = 1;

        let config = WalletsConfig::new(Some(num_wallets), Some(num_coins), Some(initial_amount));
        let wallets = launch_custom_provider_and_get_wallets(config, None, None).await;
        let wallet_owner = wallets.get(0).unwrap().clone();
        let wallet1 = wallets.get(1).unwrap().clone();
        let wallet2 = wallets.get(2).unwrap().clone();

        return WaletsSetup {
            wallet_owner,
            wallet1,
            wallet2,
        };
    }

    pub async fn setup_token_contract(wallet_owner: &WalletUnlocked) -> TestToken {
        let token_contract_id = Contract::deploy(
            "out/debug/token_contract.bin",
            wallet_owner,
            TxParameters::default(),
            StorageConfiguration::with_storage_path(Some(
                "./out/debug/token_contract-storage_slots.json".to_string(),
            )),
        )
        .await
        .unwrap();

        return get_token_instance(&token_contract_id, wallet_owner);
    }

    pub async fn setup() -> (TestToken, WaletsSetup) {
        let wallets = setup_wallets().await;
        let token = setup_token_contract(&wallets.wallet_owner).await;
        return (token, wallets);
    }

    pub fn get_token_instance(
        token_contract_id: &Bech32ContractId,
        wallet: &WalletUnlocked,
    ) -> TestToken {
        return TestToken::new(token_contract_id.clone(), wallet.clone());
    }
}

//=========================== 👇🏻 DRAFTS 👇🏻 ================================
//========================================================================
//========================================================================
//========================================================================

// pub struct Metadata {
//     pub token: TestToken,
//     pub wallet_owner: WalletUnlocked,
//     pub wallet_mint1: WalletUnlocked,
//     pub wallet_mint2: WalletUnlocked,
// }

// pub mod test_helpers {
//     use super::*;

//     pub async fn setup() -> (Metadata, Vec<WalletUnlocked>) {
//         let wallets = launch_custom_provider_and_get_wallets(WalletsConfig::default(), None).await;

//         let contract_id = Contract::deploy(
//             "./out/debug/token_contract.bin",
//             &wallets[0],
//             TxParameters::default(),
//             StorageConfiguration::default(),
//         )
//         .await
//         .unwrap();

//         let user = Metadata {
//             token: Token::new(contract_id.clone(), wallets[0].clone()),
//             wallet: wallets[0].clone().lock(),
//         };

//         (user, wallets)
//     }
// }

Removed out, target, and .lock files. rebuild the dapp and refactor a bit

and now the output looks like that

thread 'actions::deploy_token_contract::deploy_token_contract' panicked at '❌ Problem deploing the dapp: ProviderError(
    "Response errors; Unknown field \"header\" on type \"Block\".",
)', tests/actions/deploy_token_contract.rs:32:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test actions::deploy_token_contract::deploy_token_contract ... FAILED

try changing your rpc string to “node-beta-2.fuel.network”

Maybe I have the wrong versions?

installed toolchains
--------------------
beta-2-aarch64-apple-darwin (default)
latest-aarch64-apple-darwin
alt-toolchain

active toolchain
-----------------
beta-2-aarch64-apple-darwin (default)
  forc : 0.31.1
    - forc-client
      - forc-deploy : 0.31.1
      - forc-run : 0.31.1
    - forc-doc : 0.31.1
    - forc-explore : 0.28.1
    - forc-fmt : 0.31.1
    - forc-lsp : 0.31.1
    - forc-wallet : 0.1.2
  fuel-core : 0.14.1
  fuel-indexer - not found

Your versions look correct to interact with the v2 testnet. Try my rpc string suggestion and if it doesn’t work I can take another look

After changing of RPC error changed

thread 'actions::deploy_token_contract::deploy_token_contract' panicked at '❌ Problem deploing the dapp: ProviderError(
    "gas_price(0) is lower than the required min_gas_price(1)",
)', tests/actions/deploy_token_contract.rs:32:23

Btw it looks cool already

I can setup it with tx_params

yeah to interact with the testnet (deploy your contract) you need to specify a gas price.
Try this

TxParameters::new(Some(1), None, None)

instead of TxParameters::default() when you deploy your contract. Also I would suggest only deploying and testing on the testnet after you have thoroughly tested your contracts locally. That way you don’t uneccessarily burn through test tokens.

1 Like

Thanks! Deploy well done!!!
One more question
trying to call initialize in and have the same error

Code:

instance
        .methods()
        .initialize(parse_units(1000, decimals), Address::from(wallet.address()))
        .tx_params(TxParameters::new(Some(1), None, None))
        .call()
        .await
        .unwrap();

Error

thread 'initialize_usdt' panicked at 'called `Result::unwrap()` on an `Err` value: ProviderError("gas_price(0) is lower than the required min_gas_price(1)")', tests/harness.rs:54:63

How to provide the gas price correctly in that case?

Hmm the code you have should work. Could you push your code again so I take another look at it?