use super::test_builder::test_builder;
use expect_test::expect;
use std::fmt::Write;
use unc_primitives_core::version::ProtocolFeature;
const FIX_CONTRACT_LOADING_COST: u32 = 129;
static INFINITE_INITIALIZER_CONTRACT: &str = r#"
(module
(func $start (loop (br 0)))
(func (export "main"))
(start $start)
)"#;
#[test]
fn test_infinite_initializer() {
test_builder()
.wat(INFINITE_INITIALIZER_CONTRACT)
.gas(10u64.pow(10))
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 10000000000 used gas 10000000000
Err: Exceeded the prepaid gas.
"#]]);
}
#[test]
fn test_infinite_initializer_export_not_found() {
test_builder()
.wat(INFINITE_INITIALIZER_CONTRACT)
.method("no-such-method")
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 0 storage_usage 0 return data None burnt gas 0 used gas 0
Err: MethodNotFound
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 49101213 used gas 49101213
Err: MethodNotFound
"#]],
]);
}
static SIMPLE_CONTRACT: &str = r#"(module (func (export "main")))"#;
#[test]
fn test_simple_contract() {
test_builder()
.wat(SIMPLE_CONTRACT)
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 42815463 used gas 42815463
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 49397511 used gas 49397511
"#]],
]);
}
#[test]
fn test_imported_memory() {
test_builder()
.wasm(&[
0, 97, 115, 109, 1, 0, 0, 0, 2, 12, 1, 3, 101, 110, 118, 0, 2, 1, 239, 1, 248, 1, 4, 6,
1, 112, 0, 143, 129, 32, 7, 12, 1, 8, 0, 17, 17, 17, 17, 17, 17, 2, 2, 0,
])
.opaque_error()
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 44982963 used gas 44982963
Err: ...
"#]],
]);
}
#[test]
fn test_multiple_memories() {
test_builder()
.wat("(module (memory 1 2) (memory 3 4))")
.opaque_error()
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 39130713 used gas 39130713
Err: ...
"#]],
]);
}
#[test]
fn test_export_not_found() {
test_builder().wat(SIMPLE_CONTRACT)
.method("no-such-method")
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 0 storage_usage 0 return data None burnt gas 0 used gas 0
Err: MethodNotFound
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 42815463 used gas 42815463
Err: MethodNotFound
"#]],
]);
}
#[test]
fn test_empty_method() {
test_builder().wat(SIMPLE_CONTRACT).method("").expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: MethodEmptyName
"#]]);
}
#[test]
fn test_trap_contract() {
test_builder()
.wat(r#"(module (func (export "main") (unreachable)) )"#)
.skip_wasmtime()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 43854969 used gas 43854969
Err: WebAssembly trap: An `unreachable` opcode was executed.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 50437017 used gas 50437017
Err: WebAssembly trap: An `unreachable` opcode was executed.
"#]],
]);
}
#[test]
fn test_trap_initializer() {
test_builder()
.wat(
r#"
(module
(func $f (export "main") (unreachable))
(start $f)
)
"#,
)
.skip_wasmtime()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 47322969 used gas 47322969
Err: WebAssembly trap: An `unreachable` opcode was executed.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 53905017 used gas 53905017
Err: WebAssembly trap: An `unreachable` opcode was executed.
"#]],
]);
}
#[test]
fn test_div_by_zero_contract() {
test_builder()
.wat(
r#"
(module
(func (export "main")
i32.const 1
i32.const 0
i32.div_s
return
)
)
"#,
)
.skip_wasmtime()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 47406987 used gas 47406987
Err: WebAssembly trap: An arithmetic exception, e.g. divided by zero.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 53166279 used gas 53166279
Err: WebAssembly trap: An arithmetic exception, e.g. divided by zero.
"#]],
]);
}
#[test]
fn test_float_to_int_contract() {
for op in ["i32.trunc_f64_s", "i32.trunc_f64_u", "i64.trunc_f64_s", "i64.trunc_f64_u"] {
test_builder()
.wat(&format!(
r#"
(module
(func (export "main")
f64.const 0x1p+1023
{op}
return
)
)
"#,
))
.skip_wasmtime()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 47667981 used gas 47667981
Err: WebAssembly trap: An arithmetic exception, e.g. divided by zero.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 53427273 used gas 53427273
Err: WebAssembly trap: An arithmetic exception, e.g. divided by zero.
"#]],
]);
}
}
#[test]
fn test_indirect_call_to_null_contract() {
test_builder()
.wat(
r#"
(module
(type $ty (func))
(table 1 funcref)
(func (export "main")
i32.const 0
call_indirect (type $ty)
return
)
)
"#,
)
.opaque_error()
.skip_wasmtime()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 50919231 used gas 50919231
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 56678523 used gas 56678523
Err: ...
"#]],
])
}
#[test]
fn test_indirect_call_to_wrong_signature_contract() {
test_builder()
.wat(
r#"
(module
(type $ty (func (result i32)))
(func $f)
(table 1 funcref)
(elem (i32.const 0) $f)
(func (export "main")
i32.const 0
call_indirect (type $ty)
return
)
)
"#,
)
.skip_wasmtime()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 55904481 used gas 55904481
Err: WebAssembly trap: Call indirect incorrect signature trap.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 61663773 used gas 61663773
Err: WebAssembly trap: Call indirect incorrect signature trap.
"#]]
])
}
#[test]
fn test_wrong_signature_contract() {
test_builder()
.wat(r#"(module (func (export "main") (param i32)))"#)
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 0 storage_usage 0 return data None burnt gas 0 used gas 0
Err: MethodInvalidSignature
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 43032213 used gas 43032213
Err: MethodInvalidSignature
"#]],
]);
}
#[test]
fn test_export_wrong_type() {
test_builder()
.wat(r#"(module (global (export "main") i32 (i32.const 123)))"#)
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 0 storage_usage 0 return data None burnt gas 0 used gas 0
Err: MethodNotFound
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 41298213 used gas 41298213
Err: MethodNotFound
"#]],
]);
}
#[test]
fn test_guest_panic() {
test_builder()
.wat(
r#"
(module
(import "env" "panic" (func $panic))
(func (export "main") (call $panic))
)
"#,
)
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 315775830 used gas 315775830
Err: Smart contract panicked: explicit guest panic
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 322357878 used gas 322357878
Err: Smart contract panicked: explicit guest panic
"#]],
]);
}
#[test]
fn test_panic_re_export() {
test_builder()
.wat(
r#"
(module
(import "env" "panic" (func $panic))
(export "main" (func $panic))
)"#,
)
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 312352074 used gas 312352074
Err: Smart contract panicked: explicit guest panic
"#]]);
}
#[test]
fn test_stack_overflow() {
test_builder()
.wat(r#"(module (func $f (export "main") (call $f)))"#)
.skip_wasmtime()
.opaque_error()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 13526101017 used gas 13526101017
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 30376143897 used gas 30376143897
Err: ...
"#]],
]);
}
#[test]
fn test_stack_instrumentation_protocol_upgrade() {
test_builder()
.wat(
r#"
(module
(func $f1 (export "f1")
(local i32)
(call $f1))
(func $f2 (export "f2")
(local i32 i32 i32 i32)
(call $f2))
)
"#,
)
.method("f1")
.protocol_features(&[
ProtocolFeature::CorrectStackLimit,
ProtocolFeature::PreparationV2,
])
.skip_wasmtime()
.opaque_error()
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 18136872021 used gas 18136872021
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 6789985365 used gas 6789985365
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 31767212013 used gas 31767212013
Err: ...
"#]],
]);
test_builder()
.wat(
r#"
(module
(func $f1 (export "f1")
(local i32)
(call $f1))
(func $f2 (export "f2")
(local i32 i32 i32 i32)
(call $f2))
)
"#,
)
.method("f2")
.opaque_error()
.protocol_features(&[
ProtocolFeature::CorrectStackLimit,
ProtocolFeature::PreparationV2,
])
.skip_wasmtime()
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 18136872021 used gas 18136872021
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 2745316869 used gas 2745316869
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 29698803429 used gas 29698803429
Err: ...
"#]],
]);
}
#[test]
fn test_memory_grow() {
test_builder()
.wat(
r#"
(module
(memory 17 32)
(func (export "main")
(loop
(memory.grow (i32.const 1))
drop
br 0
)
)
)"#,
)
.gas(10u64.pow(10))
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 10000000000 used gas 10000000000
Err: Exceeded the prepaid gas.
"#]]);
}
fn bad_import_global(env: &str) -> Vec<u8> {
wat::parse_str(format!(
r#"
(module
(import "{env}" "no-such-global" (global i32))
(func (export "main"))
)"#,
))
.unwrap()
}
fn bad_import_func(env: &str) -> Vec<u8> {
wat::parse_str(format!(
r#"
(module
(import "{env}" "no-such-fn" (func $f))
(export "main" (func $f))
)"#,
))
.unwrap()
}
#[test]
fn test_bad_import_1() {
test_builder()
.wasm(&bad_import_global("no-such-module"))
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Error happened during instantiation.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 50618463 used gas 50618463
Err: PrepareError: Error happened during instantiation.
"#]],
]);
}
#[test]
fn test_bad_import_2() {
test_builder()
.wasm(&bad_import_func("no-such-module"))
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Error happened during instantiation.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 50184963 used gas 50184963
Err: PrepareError: Error happened during instantiation.
"#]],
]);
}
#[test]
fn test_bad_import_3() {
test_builder()
.wasm(&bad_import_global("env"))
.opaque_error()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 48234213 used gas 48234213
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: ...
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 48234213 used gas 48234213
Err: ...
"#]],
]);
}
#[test]
fn test_bad_import_4() {
test_builder().wasm(&bad_import_func("env")).opaque_error().expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 47800713 used gas 47800713
Err: ...
"#]]);
}
#[test]
fn test_initializer_no_gas() {
test_builder()
.wat(
r#"
(module
(func $f (export "main") nop)
(start $f)
)"#,
)
.gas(0)
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: Exceeded the prepaid gas.
"#]]);
}
#[test]
fn test_bad_many_imports() {
let mut imports = String::new();
for i in 0..100 {
writeln!(imports, r#"(import "env" "wtf{i}" (func))"#).unwrap();
}
test_builder()
.wat(&format!(
r#"
(module
{imports}
(export "main" (func 0))
)"#,
))
.opaque_error()
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 299447463 used gas 299447463
Err: ...
"#]])
}
static EXTERNAL_CALL_CONTRACT: &str = r#"
(module
(import "env" "prepaid_gas" (func $prepaid_gas (result i64)))
(func (export "main")
(drop (call $prepaid_gas)))
)"#;
#[test]
fn test_external_call_ok() {
test_builder()
.wat(EXTERNAL_CALL_CONTRACT)
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 320283336 used gas 320283336
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 326865384 used gas 326865384
"#]],
]);
}
#[test]
fn test_external_call_error() {
test_builder().wat(EXTERNAL_CALL_CONTRACT).gas(100).expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 100 used gas 100
Err: Exceeded the prepaid gas.
"#]]);
}
#[test]
fn test_external_call_indirect() {
test_builder()
.wat(
r#"
(module
(import "env" "prepaid_gas" (func $prepaid_gas (result i64)))
(type $prepaid_gas_t (func (result i64)))
(table 1 funcref)
(elem (i32.const 0) $prepaid_gas)
(func (export "main")
(call_indirect (type $prepaid_gas_t) (i32.const 0))
drop
)
)
"#
)
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 328909092 used gas 328909092
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 335491140 used gas 335491140
"#]],
]);
}
#[test]
fn test_address_overflow() {
let code = r#"
(module
(memory 1)
(func (export "main")
i32.const 1
i64.load32_u offset=4294967295 (;2^32 - 1;) align=1
drop
)
)
"#;
test_builder()
.wat(code)
.skip_wasmtime()
.skip_wasmer0()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 48534981 used gas 48534981
Err: WebAssembly trap: Memory out of bounds trap.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 54294273 used gas 54294273
Err: WebAssembly trap: Memory out of bounds trap.
"#]],
]);
test_builder()
.wat(code)
.only_wasmer0()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 48534981 used gas 48534981
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 55117029 used gas 55117029
"#]],
]);
}
#[test]
fn test_nan_sign() {
let code = r#"
(module
(func (export "main")
(i32.div_u
(i32.const 0)
(f32.gt
(f32.copysign
(f32.const 1.0)
(f32.sqrt (f32.const -1.0)))
(f32.const 0)))
drop
)
)"#;
test_builder()
.wat(code)
.skip_wasmtime()
.skip_wasmer0()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 54988767 used gas 54988767
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 61570815 used gas 61570815
"#]],
]);
test_builder()
.wat(code)
.only_wasmer0()
.protocol_features(&[
ProtocolFeature::PreparationV2,
])
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 54988767 used gas 54988767
Err: WebAssembly trap: An arithmetic exception, e.g. divided by zero.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 60748059 used gas 60748059
Err: WebAssembly trap: An arithmetic exception, e.g. divided by zero.
"#]],
]);
}
#[test]
fn test_gas_exceed_loading() {
test_builder().wat(SIMPLE_CONTRACT).method("non_empty_non_existing").gas(1).expect(&expect![[
r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 1 used gas 1
Err: Exceeded the prepaid gas.
"#
]]);
}
#[test]
fn gas_overflow_direct_call() {
test_builder()
.wat(
r#"
(module
(import "env" "gas" (func $gas (param i32)))
(func (export "main")
(call $gas (i32.const 0xffff_ffff)))
)"#,
)
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 100000000000000 used gas 100000000000000
Err: Exceeded the maximum amount of gas allowed to burn per contract.
"#]]);
}
#[test]
fn gas_overflow_indirect_call() {
test_builder()
.wat(
r#"
(module
(import "env" "gas" (func $gas (param i32)))
(type $gas_ty (func (param i32)))
(table 1 funcref)
(elem (i32.const 0) $gas)
(func (export "main")
(call_indirect
(type $gas_ty)
(i32.const 0xffff_ffff)
(i32.const 0)))
)"#,
)
.expect(&expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 100000000000000 used gas 100000000000000
Err: Exceeded the maximum amount of gas allowed to burn per contract.
"#]]);
}
mod fix_contract_loading_cost_protocol_upgrade {
use super::*;
use unc_parameters::ExtCosts;
static ALMOST_TRIVIAL_CONTRACT: &str = r#"
(module
(func (export "main")
i32.const 1
i32.const 1
i32.div_s
return
)
)"#;
#[test]
fn test_fn_loading_gas_protocol_upgrade() {
test_builder()
.wat(ALMOST_TRIVIAL_CONTRACT)
.protocol_features(&[
ProtocolFeature::PreparationV2
])
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 47406987 used gas 47406987
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 53989035 used gas 53989035
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 53989035 used gas 53989035
"#]],
]);
}
#[test]
fn test_fn_loading_gas_protocol_upgrade_exceed_loading() {
let expect = expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 44115963 used gas 44115963
Err: Exceeded the prepaid gas.
"#]];
let test_after = test_builder().wat(ALMOST_TRIVIAL_CONTRACT);
let cfg_costs = &test_after.configs().next().unwrap().wasm_config.ext_costs;
let loading_base = cfg_costs.gas_cost(ExtCosts::contract_loading_base);
let loading_byte = cfg_costs.gas_cost(ExtCosts::contract_loading_bytes);
let wasm_length = test_after.get_wasm().len();
test_after.gas(loading_base + wasm_length as u64 * loading_byte).expect(&expect);
test_builder()
.wat(ALMOST_TRIVIAL_CONTRACT)
.only_protocol_versions(vec![FIX_CONTRACT_LOADING_COST - 1])
.gas(loading_base + wasm_length as u64 * loading_byte)
.expect(&expect);
}
#[test]
fn test_fn_loading_gas_protocol_upgrade_exceed_executing() {
let expect = expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 45000000 used gas 45000000
Err: Exceeded the prepaid gas.
"#]];
let test_after = test_builder().wat(ALMOST_TRIVIAL_CONTRACT);
let cfg_costs = &test_after.configs().next().unwrap().wasm_config.ext_costs;
let loading_base = cfg_costs.gas_cost(ExtCosts::contract_loading_base);
let loading_byte = cfg_costs.gas_cost(ExtCosts::contract_loading_bytes);
let wasm_length = test_after.get_wasm().len();
let prepaid_gas = loading_base + wasm_length as u64 * loading_byte + 884037;
test_after.gas(prepaid_gas).expect(&expect);
test_builder()
.wat(ALMOST_TRIVIAL_CONTRACT)
.only_protocol_versions(vec![FIX_CONTRACT_LOADING_COST - 1])
.gas(prepaid_gas)
.expect(&expect);
}
#[test]
fn test_fn_loading_gas_protocol_upgrade_fail_preparing() {
test_builder()
.wat(r#"(module (export "main" (func 0)))"#)
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Error happened while deserializing the module.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 39347463 used gas 39347463
Err: PrepareError: Error happened while deserializing the module.
"#]],
]);
test_builder()
.wasm(&bad_import_global("wtf"))
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Error happened during instantiation.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 48234213 used gas 48234213
Err: PrepareError: Error happened during instantiation.
"#]],
]);
test_builder()
.wasm(&bad_import_func("wtf"))
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Error happened during instantiation.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 47800713 used gas 47800713
Err: PrepareError: Error happened during instantiation.
"#]],
]);
test_builder()
.wasm(&unc_test_contracts::LargeContract {
functions: 101,
locals_per_function: 9901,
..Default::default()
}
.make())
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Too many locals declared in the contract.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 195407463 used gas 195407463
Err: PrepareError: Too many locals declared in the contract.
"#]],
]);
let functions_number_limit: u32 = 10_000;
test_builder()
.wasm(&unc_test_contracts::LargeContract {
functions: functions_number_limit / 2,
panic_imports: functions_number_limit / 2 + 1,
..Default::default()
}
.make())
.protocol_version(FIX_CONTRACT_LOADING_COST)
.expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 0 used gas 0
Err: PrepareError: Too many functions in contract.
"#]],
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 19554433713 used gas 19554433713
Err: PrepareError: Too many functions in contract.
"#]],
]);
}
}
#[test]
fn test_regression_9393() {
let before_builder = test_builder().only_protocol_versions(vec![62]);
let after_builder = test_builder().only_protocol_versions(vec![63]);
let before_cost = before_builder.configs().next().unwrap().wasm_config.regular_op_cost;
let after_cost = after_builder.configs().next().unwrap().wasm_config.regular_op_cost;
assert_eq!(
before_cost, after_cost,
"this test is not set up to test with different insn costs"
);
let cost = u64::from(before_cost);
let nops = (i32::MAX as u64 + cost - 1) / cost;
let contract = unc_test_contracts::function_with_a_lot_of_nop(nops);
before_builder.wasm(&contract).only_unc_vm().expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 100000000000000 used gas 100000000000000
Err: Exceeded the maximum amount of gas allowed to burn per contract.
"#]],
]);
after_builder.wasm(&contract).expects(&[
expect![[r#"
VMOutcome: balance 4 storage_usage 12 return data None burnt gas 2763981177 used gas 2763981177
"#]],
]);
}