pchain-runtime 0.4.3

parallelchain-runtime: ParallelChain Mainnet Runtime for state transition in ParallelChain Mainnet
Documentation
use pchain_types::blockchain::{ExitStatus, Transaction};

use crate::common::{compute_contract_address, ArgsBuilder, SimulateWorldState, TestData};

mod common;

/// Simulate test to call smart contract with sufficient balance in from account.
/// 1. transfer initial balance to contract at etoc call
/// 2. make ctoe call to transfer value <= contract's balance to contract itself
/// 3. make ctoe call to transfer value <= contract's balance to another address
#[test]
fn test_success_ctoe() {
    let contract_code = TestData::get_test_contract_code("all_features");
    let origin_address = [1u8; 32];
    let contract_address = compute_contract_address(origin_address, 0);

    let bd = TestData::block_params();

    let mut sws = SimulateWorldState::default();
    let init_from_balance = 500_000_000_000;
    sws.set_balance(origin_address, init_from_balance);

    // 0. deploy contract
    let mut tx = TestData::transaction();
    tx.signer = origin_address;
    tx.gas_limit = 300_000_000;
    tx.commands = vec![ArgsBuilder::new()
        .empty_args()
        .make_deploy(contract_code, 0)];

    let result = pchain_runtime::Runtime::new().transition(sws.world_state, tx, bd.clone());
    let receipt = result.receipt.unwrap();
    assert_eq!(receipt.last().unwrap().exit_status, ExitStatus::Success);
    let sws: SimulateWorldState = result.new_state.into();

    let mut base_tx = TestData::transaction();
    base_tx.signer = origin_address;
    base_tx.gas_limit = 100_000_000;

    // make transfer balance to contract itself
    let result = pchain_runtime::Runtime::new().transition(
        sws.world_state,
        Transaction {
            commands: vec![ArgsBuilder::new()
                .add(contract_address.clone())
                .add(100_000_u64)
                .make_call(Some(100_000_u64), contract_address, "make_balance_transfer")],
            nonce: 1,
            ..base_tx
        },
        bd.clone(),
    );
    let receipt = result.receipt.unwrap();
    assert_eq!(receipt.last().unwrap().exit_status, ExitStatus::Success);
    let sws: SimulateWorldState = result.new_state.into();

    // check contract balance is unchanged.
    let contract_balance = sws.get_balance(contract_address);
    assert_eq!(contract_balance, 100_000_u64);

    // make transfer balance to another address itself
    let result = pchain_runtime::Runtime::new().transition(
        sws.world_state,
        Transaction {
            commands: vec![ArgsBuilder::new()
                .add([9u8; 32])
                .add(100_000_u64)
                .make_call(Some(0), contract_address, "make_balance_transfer")],
            nonce: 2,
            ..base_tx
        },
        bd.clone(),
    );
    let receipt = result.receipt.unwrap();
    assert_eq!(receipt.last().unwrap().exit_status, ExitStatus::Success);
    let sws: SimulateWorldState = result.new_state.into();

    // check contract balance is empty.
    let contract_balance = sws.get_balance(contract_address);
    assert_eq!(contract_balance, 0_u64);
}

/// Simulate test to call smart contract with sufficient balance in from account.
/// Verify the transaction status code is FailureBalanceInsufficientInContract
/// 1. transfer initial balance to contract at etoc call
/// 2. make ctoe call to transfer value > contract's balance to contract itself
#[test]
fn test_ctoe_tx_with_insufficient_balance() {
    let contract_code = TestData::get_test_contract_code("all_features");
    let origin_address = [1u8; 32];
    let contract_address = compute_contract_address(origin_address, 0);

    let bd = TestData::block_params();

    let mut sws = SimulateWorldState::default();
    let init_from_balance = 500_000_000_000;
    sws.set_balance(origin_address, init_from_balance);

    // 0. deploy contract
    let tx = Transaction {
        signer: origin_address,
        commands: vec![ArgsBuilder::new()
            .empty_args()
            .make_deploy(contract_code, 0)],
        gas_limit: 300_000_000,
        priority_fee_per_gas: 0,
        max_base_fee_per_gas: 1,
        nonce: 0,
        hash: [0u8; 32],
        signature: [0u8; 64],
    };

    let result = pchain_runtime::Runtime::new().transition(sws.world_state, tx, bd.clone());
    let receipt = result.receipt.unwrap();
    assert_eq!(receipt.last().unwrap().exit_status, ExitStatus::Success);
    let sws: SimulateWorldState = result.new_state.into();

    let mut base_tx = TestData::transaction();
    base_tx.signer = origin_address;
    base_tx.gas_limit = 100_000_000;

    // make transfer balance
    let result = pchain_runtime::Runtime::new().transition(
        sws.world_state,
        Transaction {
            commands: vec![ArgsBuilder::new()
                .add(contract_address.clone())
                .add(100_000_000_u64)
                .make_call(Some(0), contract_address, "make_balance_transfer")],
            nonce: 1,
            ..base_tx
        },
        bd.clone(),
    );
    let receipt = result.receipt.unwrap();
    assert_eq!(receipt.last().unwrap().exit_status, ExitStatus::Failed);
}