Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: symbolic execution support #1235

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7d93f77
test api & contracts copied from RV repo
andrei-marinica Oct 3, 2023
ceb6179
test api integrated in SC api
andrei-marinica Oct 8, 2023
0dbfea2
fmt
andrei-marinica Oct 8, 2023
0023a8a
cargo update
andrei-marinica Oct 8, 2023
dcf8cae
dependency fix
andrei-marinica Oct 9, 2023
e333549
sc-meta prettier print
andrei-marinica Oct 9, 2023
e335988
clippy fix
andrei-marinica Oct 10, 2023
298a08c
Merge pull request #1231 from multiversx/foundry
andrei-marinica Oct 10, 2023
005db9a
Merge branch 'feat/unified' into feat/symbolic
andrei-marinica Apr 22, 2024
c1f213c
fix after merge
andrei-marinica Apr 23, 2024
28eab1e
Merge pull request #1580 from multiversx/symbolic-unified
andrei-marinica Apr 23, 2024
33d971a
parametric tests rename
andrei-marinica Apr 23, 2024
0ea1af1
Merge pull request #1585 from multiversx/pt-rename
andrei-marinica Apr 24, 2024
d1c8917
Merge branch 'feat/unified' into merge-unified-to-symbolic
andrei-marinica May 2, 2024
93275ec
Merge pull request #1602 from multiversx/merge-unified-to-symbolic
andrei-marinica May 3, 2024
c83eebc
Merge branch 'master' into 'feat/symbolic'
andrei-marinica May 10, 2024
5c1908b
Merge pull request #1624 from multiversx/merge-symb-master
andrei-marinica May 13, 2024
bf89a20
Merge branch 'master' into feat/symbolic
andrei-marinica May 31, 2024
33fe9d6
Merge pull request #1667 from multiversx/merge-symb-master
andrei-marinica May 31, 2024
243c7fc
param tests - unified call syntax
andrei-marinica May 2, 2024
8c56281
pretty print
andrei-marinica Jun 3, 2024
1666391
rebuild, kasmer config fix
andrei-marinica Jun 3, 2024
e2b889e
param tests - use regular read from address
andrei-marinica Jun 3, 2024
03bc446
param tests - deploy unified syntax
andrei-marinica Jun 4, 2024
9dcb53a
param tests - multisig-pt unified syntax
andrei-marinica Jun 4, 2024
075ef0d
multisig-pt - quorum as usize
andrei-marinica Jun 5, 2024
bf77c2b
cleanup
andrei-marinica Jun 5, 2024
dbc76ab
Merge pull request #1673 from multiversx/symb-syntax
andrei-marinica Jun 7, 2024
b56dda8
kasmer config for adder & multisig
andrei-marinica Jul 4, 2024
d4f6b59
kasmer readme
andrei-marinica Jul 5, 2024
45dff22
typos
andrei-marinica Jul 5, 2024
a62885c
Merge pull request #1695 from multiversx/kup-integration
andrei-marinica Jul 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
840 changes: 555 additions & 285 deletions Cargo.lock

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,17 @@ members = [
"contracts/feature-tests/scenario-tester/meta",
"contracts/feature-tests/use-module",
"contracts/feature-tests/use-module/meta",

"contracts/parametric-tests/adder-pt",
"contracts/parametric-tests/adder-pt/meta",
"contracts/parametric-tests/addercaller",
"contracts/parametric-tests/addercaller/meta",
"contracts/parametric-tests/callee",
"contracts/parametric-tests/callee/meta",
"contracts/parametric-tests/caller",
"contracts/parametric-tests/caller/meta",
"contracts/parametric-tests/multisig-pt",
"contracts/parametric-tests/multisig-pt/meta",
"contracts/parametric-tests/testapi-pt",
"contracts/parametric-tests/testapi-pt/meta",
]
3 changes: 3 additions & 0 deletions contracts/examples/adder/sc-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

[[proxy]]
path = "src/adder_proxy.rs"

[[proxy]]
path = "../../parametric-tests/adder-pt/src/adder_proxy.rs"
3 changes: 3 additions & 0 deletions contracts/examples/multisig/sc-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ add-labels = ["multisig-external-view"]

[[proxy]]
path = "src/multisig_proxy.rs"

[[proxy]]
path = "../../parametric-tests/multisig-pt/src/multisig_proxy.rs"
11 changes: 11 additions & 0 deletions contracts/parametric-tests/adder-pt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Generated by Cargo
# will have compiled files and executables
/target/
*/target/

# The mxpy output
/output*/

# Kasmer
.property
generated_claims
21 changes: 21 additions & 0 deletions contracts/parametric-tests/adder-pt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "adder-pt"
version = "0.0.0"
authors = [ "you",]
edition = "2018"
publish = false

[lib]
path = "src/adder_pt.rs"

[dev-dependencies]
num-bigint = "0.4.2"

[dependencies.multiversx-sc]
version = "0.50.0"
path = "../../../framework/base"

[dev-dependencies.multiversx-sc-scenario]
version = "0.50.0"
path = "../../../framework/scenario"

19 changes: 19 additions & 0 deletions contracts/parametric-tests/adder-pt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Parametric test example for: Adder

This is an example on how to write a basic parametric test contract.

To run fuzzing on it using Kasmer, build the contracts and simply run

```
kasmer fuzz
```


To run symbolic execution:

```
kasmer build
kasmer verify test_call_add --booster
## and / or
kasmer verify test_call_add_twice --booster
```
5 changes: 5 additions & 0 deletions contracts/parametric-tests/adder-pt/kasmer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"contracts": [
"../../examples/adder"
]
}
15 changes: 15 additions & 0 deletions contracts/parametric-tests/adder-pt/meta/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "adder-pt-meta"
version = "0.0.0"
edition = "2018"
publish = false
authors = [ "you",]

[dev-dependencies]

[dependencies.adder-pt]
path = ".."

[dependencies.multiversx-sc-meta]
version = "0.50.0"
path = "../../../../framework/meta"
3 changes: 3 additions & 0 deletions contracts/parametric-tests/adder-pt/meta/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
multiversx_sc_meta::cli_main::<adder_pt::AbiProvider>();
}
3 changes: 3 additions & 0 deletions contracts/parametric-tests/adder-pt/multiversx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"language": "rust"
}
71 changes: 71 additions & 0 deletions contracts/parametric-tests/adder-pt/scenarios/test-adder.scen.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "test-adder",
"comment": "run foundry-like test for Adder",
"gasSchedule": "v3",
"steps": [
{
"step": "setState",
"accounts": {
"address:k": {
"nonce": "1",
"balance": "100000"
}
},
"newAddresses": [
{
"creatorAddress": "address:k",
"creatorNonce": "1",
"newAddress": "sc:k-test"
}
]
},
{
"step": "fetchWasmSource",
"wasmPath": "file:../../../../deps/mx-sdk-rs/contracts/examples/adder/output/adder.wasm"
},
{
"step": "scDeploy",
"id": "deploy test",
"comment": "deploy the test contract",
"tx": {
"from": "address:k",
"contractCode": "file:../output/test-adder.wasm",
"arguments": [
"file:../../../../deps/mx-sdk-rs/contracts/examples/adder/output/adder.wasm"
],
"gasLimit": "5,000,000,000,000",
"gasPrice": "0"
},
"expect": {
"out": [],
"status": "",
"logs": "*",
"gas": "*",
"refund": "*"
}
},
{
"step": "scCall",
"id": "call test",
"comment": "call the parametric test endpoint with a concrete value",
"tx": {
"from": "address:k",
"to": "sc:k-test",
"function": "test_call_add",
"value": "0",
"arguments": [
"3"
],
"gasLimit": "5,000,000",
"gasPrice": "0"
},
"expect": {
"out": [],
"status": "",
"logs": "*",
"gas": "*",
"refund": "*"
}
}
]
}
114 changes: 114 additions & 0 deletions contracts/parametric-tests/adder-pt/src/adder_proxy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Code generated by the multiversx-sc proxy generator. DO NOT EDIT.

////////////////////////////////////////////////////
////////////////// AUTO-GENERATED //////////////////
////////////////////////////////////////////////////

#![allow(dead_code)]
#![allow(clippy::all)]

use multiversx_sc::proxy_imports::*;

pub struct AdderProxy;

impl<Env, From, To, Gas> TxProxyTrait<Env, From, To, Gas> for AdderProxy
where
Env: TxEnv,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
type TxProxyMethods = AdderProxyMethods<Env, From, To, Gas>;

fn proxy_methods(self, tx: Tx<Env, From, To, (), Gas, (), ()>) -> Self::TxProxyMethods {
AdderProxyMethods { wrapped_tx: tx }
}
}

pub struct AdderProxyMethods<Env, From, To, Gas>
where
Env: TxEnv,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
wrapped_tx: Tx<Env, From, To, (), Gas, (), ()>,
}

#[rustfmt::skip]
impl<Env, From, Gas> AdderProxyMethods<Env, From, (), Gas>
where
Env: TxEnv,
Env::Api: VMApi,
From: TxFrom<Env>,
Gas: TxGas<Env>,
{
pub fn init<
Arg0: ProxyArg<BigUint<Env::Api>>,
>(
self,
initial_value: Arg0,
) -> TxTypedDeploy<Env, From, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_deploy()
.argument(&initial_value)
.original_result()
}
}

#[rustfmt::skip]
impl<Env, From, To, Gas> AdderProxyMethods<Env, From, To, Gas>
where
Env: TxEnv,
Env::Api: VMApi,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
pub fn upgrade<
Arg0: ProxyArg<BigUint<Env::Api>>,
>(
self,
initial_value: Arg0,
) -> TxTypedUpgrade<Env, From, To, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_upgrade()
.argument(&initial_value)
.original_result()
}
}

#[rustfmt::skip]
impl<Env, From, To, Gas> AdderProxyMethods<Env, From, To, Gas>
where
Env: TxEnv,
Env::Api: VMApi,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
pub fn sum(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, BigUint<Env::Api>> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("getSum")
.original_result()
}

/// Add desired amount to the storage variable.
pub fn add<
Arg0: ProxyArg<BigUint<Env::Api>>,
>(
self,
value: Arg0,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("add")
.argument(&value)
.original_result()
}
}
91 changes: 91 additions & 0 deletions contracts/parametric-tests/adder-pt/src/adder_pt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#![no_std]

mod adder_proxy;

multiversx_sc::imports!();

static INIT_SUM: u32 = 5u32;

#[multiversx_sc::contract]
pub trait TestAdder {
#[storage_mapper("ownerAddress")]
fn owner_address(&self) -> SingleValueMapper<ManagedAddress>;

#[storage_mapper("adderAddress")]
fn adder_address(&self) -> SingleValueMapper<ManagedAddress>;

/// Create the owner account and deploy adder
#[init]
fn init(&self, code_path: ManagedBuffer) {
// create the owner account
let owner = ManagedAddress::from(b"owner___________________________");
self.owner_address().set(&owner);

self.test_raw()
.create_account(&owner, 1, &BigUint::from(0u64));

// register an address for the contract to be deployed
let adder = ManagedAddress::from(b"adder___________________________");
self.test_raw().register_new_address(&owner, 1, &adder);

let adder = self
.tx()
.from(&owner)
.typed(adder_proxy::AdderProxy)
.init(INIT_SUM)
.code_path(code_path)
.gas(5000000000000)
.returns(ReturnsNewManagedAddress)
.test_deploy();

// save the deployed contract's address
self.adder_address().set(&adder);

// check the initial sum value
let sum: BigUint = self.storage_raw().read_from_address(&adder, "sum");
self.test_raw().assert(sum == INIT_SUM);
}

// Make a call from 'owner' to 'adder' and check the sum value
#[endpoint(test_call_add)]
fn test_call_add(&self, value: BigUint) {
self.test_raw().assume(value <= 100u32);

let adder = self.adder_address().get();

self.call_add(&value);

// check the sum value
let sum: BigUint = self.storage_raw().read_from_address(&adder, "sum");
self.test_raw().assert(sum == (value + INIT_SUM));
}

#[endpoint(test_call_add_twice)]
fn test_call_add_twice(&self, value1: BigUint, value2: BigUint) {
self.test_raw().assume(value1 <= 100u32);
self.test_raw().assume(value2 <= 100u32);

let adder = self.adder_address().get();

self.call_add(&value1);
self.call_add(&value2);

// check the sum value
let sum: BigUint = self.storage_raw().read_from_address(&adder, "sum");
self.test_raw().assert(sum == (value1 + value2 + INIT_SUM));
}

fn call_add(&self, value: &BigUint) {
let owner = self.owner_address().get();
let adder = self.adder_address().get();

// start a prank and call 'adder' from 'owner'
self.tx()
.from(owner)
.to(adder)
.typed(adder_proxy::AdderProxy)
.add(value)
.gas(5000000)
.test_call();
}
}
Loading