#smart-contracts #companion #concordium #testing #concordium-std

concordium-smart-contract-testing

A companion crate to concordium-std that supports off-chain end-to-end testing of smart contracts

7 stable releases (3 major)

4.2.0 Mar 26, 2024
4.1.0 Jan 26, 2024
3.2.0 Nov 23, 2023
3.1.0 Oct 18, 2023
1.0.0 May 8, 2023

#190 in Magic Beans

Download history 99/week @ 2024-03-14 367/week @ 2024-03-21 130/week @ 2024-03-28 250/week @ 2024-04-04 132/week @ 2024-04-11 110/week @ 2024-04-18 106/week @ 2024-04-25 9/week @ 2024-05-02 2/week @ 2024-05-09 10/week @ 2024-05-16 10/week @ 2024-05-23 16/week @ 2024-05-30 33/week @ 2024-06-06 14/week @ 2024-06-13 8/week @ 2024-06-20 6/week @ 2024-06-27

64 downloads per month

MPL-2.0 license

250KB
4K SLoC

Concordium Smart Contract Testing

A library that supports writing integration tests in Rust for Concordium smart contracts.

This is a companion to concordium-std which is used to write smart contracts in Rust.

Documentation

MSRV

The minimum supported Rust version can be found in the Cargo.toml manifest file. Changes in MSRV will be accompanied by at least a minor version bump.


lib.rs:

Concordium Smart Contract Testing

This library supports writing integration tests in Rust for Concordium smart contracts.

To use the library, you must add it to your Cargo.toml file under the [dev-dependencies] section. The library requries the rust edition 2021 or greater.

[package]
# ...
edition = "2021"

[dev-dependencies]
concordium-smart-contract-testing = "4.0"

Basic usage

use concordium_smart_contract_testing::*;

// Create a "chain" with default parameters.
let mut chain = Chain::new();

// Define an account address to be used.
const ACC: AccountAddress = AccountAddress([0;32]);

// Create an account with 10000 CCD in balance.
chain.create_account(Account::new(ACC, Amount::from_ccd(1000)));

// Deploy a smart contract module (built with [Cargo Concordium](https://developer.concordium.software/en/mainnet/smart-contracts/guides/setup-tools.html#cargo-concordium)).
let deployment = chain
    .module_deploy_v1(
        Signer::with_one_key(),
        ACC,
        module_load_v1("path/to/contract.wasm.v1").unwrap())
    .unwrap();

// Initialize a smart contract from the deployed module.
let initialization = chain
    .contract_init(
        Signer::with_one_key(), // Used for specifying the number of signatures.
        ACC, // Invoker account.
        Energy::from(10000), // Maximum energy allowed for initializing.
        InitContractPayload {
            mod_ref: deployment.module_reference, // Module to initialize from.
            init_name: OwnedContractName::new_unchecked("init_my_contract".into()), // Contract to init.
            param: OwnedParameter::from_serial(&"my_param").unwrap(), // Any type implementing [`Serial`] can be used.
            amount: Amount::zero(), // CCD to send the contract.
        }
    )
    .unwrap();

// Update the initialized contract.
let update = chain
    .contract_update(
        Signer::with_one_key(), // Used for specifying the number of signatures.
        ACC, // Invoker account.
        Address::Account(ACC), // Sender (can also be a contract).
        Energy::from(10000),  // Maximum energy allowed for the update.
        UpdateContractPayload {
            address: initialization.contract_address, // The contract to update.
            receive_name: OwnedReceiveName::new_unchecked("my_contract.my_entrypoint".into()), // The receive function to call.
            message: OwnedParameter::from_serial(&42u8).unwrap(), // The parameter sent to the contract.
            amount: Amount::from_ccd(100), // Sending the contract 100 CCD.
        }
    )
    .unwrap();

// Check the trace elements produced (updates, interrupts, resumes, transfers, etc.).
assert!(matches!(update.effective_trace_elements().collect::<Vec<_>>()[..], [ContractTraceElement::Updated{..}]));

// Check the return value.
assert_eq!(update.return_value, to_bytes(&84u8));

// Check the balances of both contracts and accounts.
assert_eq!(chain.contract_balance(initialization.contract_address), Some(Amount::from_ccd(100)));
assert_eq!(chain.account_balance_available(ACC), Some(
    Amount::from_ccd(1000)
    - Amount::from_ccd(100) // Amount sent to contract.
    - deployment.transaction_fee
    - initialization.transaction_fee
    - update.transaction_fee));
    

Dependencies

~26–41MB
~552K SLoC