The setup_contract_test! macro
When deploying contracts with the abigen!
macro, as shown in the previous sections, the user can:
- change the default configuration parameters
- launch several providers
- create multiple wallets
- create specific assets, etc.
However, it is often the case that we want to test only the contract methods and we want to deploy the contract with the default configuration parameters. The setup_contract_test!
macro can do exactly that.
Used to reduce boilerplate in integration tests. Accepts input in the form
of COMMAND(ARG...)...
COMMAND
is either Wallets
, Abigen
or Deploy
.
ARG
is either a:
- name-value (e.g.
name="MyContract"
), or, - a literal (e.g.
"some_str_literal"
,true
,5
, ...)
Available COMMAND
s:
Wallets
Example: Wallets("a_wallet", "another_wallet"...)
Description: Launches a local provider and generates wallets with names taken from the provided ARG
s.
Cardinality: 0 or 1.
Abigen
Example: Abigen(name="MyContract", abi="some_folder")
Description: Generates the contract bindings under the name name
. abi
should point to the folder containing the out
directory of the forc build.
Cardinality: 0 or N.
Deploy
Example: Deploy(name="instance_name", contract="MyContract", wallet="a_wallet")
Description: Deploys the contract
(with salt) using wallet
. Will create a contract instance accessible via name
. Due to salt usage, the same contract can be deployed multiple times. Requires that an Abigen
command be present with name
equal to contract
. wallet
can either be one of the wallets in the Wallets
COMMAND
or the name of a wallet you've previously generated yourself.
Cardinality: 0 or N.
The setup code that you have seen in previous sections gets reduced to:
setup_contract_test!(
Wallets("wallet"),
Abigen(
name = "TestContract",
abi = "packages/fuels/tests/contracts/contract_test"
),
Deploy(
name = "contract_instance",
contract = "TestContract",
wallet = "wallet"
),
);
let response = contract_instance
.methods()
.initialize_counter(42)
.call()
.await?;
assert_eq!(42, response.value);
Note The same contract can be deployed several times as the macro deploys the contracts with salt. You can also deploy different contracts to the same provider by referencing the same wallet in the
Deploy
command.
setup_contract_test!(
Wallets("wallet"),
Abigen(
name = "LibContract",
abi = "packages/fuels/tests/contracts/lib_contract"
),
Abigen(
name = "LibContractCaller",
abi = "packages/fuels/tests/contracts/lib_contract_caller"
),
Deploy(
name = "lib_contract_instance",
contract = "LibContract",
wallet = "wallet"
),
Deploy(
name = "contract_caller_instance",
contract = "LibContractCaller",
wallet = "wallet"
),
Deploy(
name = "contract_caller_instance2",
contract = "LibContractCaller",
wallet = "wallet"
),
);
let lib_contract_id = lib_contract_instance.contract_id();
let contract_caller_id = contract_caller_instance.contract_id();
let contract_caller_id2 = contract_caller_instance2.contract_id();
// Because we deploy with salt, we can deploy the same contract multiple times
assert_ne!(contract_caller_id, contract_caller_id2);
// The first contract can be called because they were deployed on the same provider
let response = contract_caller_instance
.methods()
.increment_from_contract(lib_contract_id.into(), 42)
.set_contracts(&[&lib_contract_instance])
.call()
.await?;
assert_eq!(43, response.value);
let response = contract_caller_instance2
.methods()
.increment_from_contract(lib_contract_id.into(), 42)
.set_contracts(&[&lib_contract_instance])
.call()
.await?;
assert_eq!(43, response.value);
In this example, three contracts are deployed on the same provider using the wallet
generated by the Wallets
command. The second and third macros use the same contract but have different IDs because of the deployment with salt. Both of them can call the first contract by using their ID.
In addition, you can manually create the wallet
variable and then use it inside the macro. This is useful if you want to create custom wallets or providers but still want to use the macro to reduce boilerplate code. Below is an example of this approach.
let config = WalletsConfig::new(Some(2), Some(1), Some(DEFAULT_COIN_AMOUNT));
let mut wallets = launch_custom_provider_and_get_wallets(config, None, None).await;
let wallet = wallets.pop().unwrap();
let wallet_2 = wallets.pop().unwrap();
setup_contract_test!(
Abigen(
name = "TestContract",
abi = "packages/fuels/tests/contracts/contract_test"
),
Deploy(
name = "contract_instance",
contract = "TestContract",
wallet = "wallet"
),
);