Movy is a Move testing framework that offers:
- Modular low-level building bricks for Move language. Specifically, the executor and tracer abstractions and layered database design borrowed from revm that allow you to emulate and inspect an execution.
- Static analysis capabilities inherited from MoveScan, the state-of-the-art static analyzer.
- Cutting-edge fuzzing reimplemented from scratch learned from Belobog that supports both property testing and on-chain fuzzing, in the a flavor similar to foundry by writing invariants in Move language.
- And a lot of more...
Checkout our documentations at here
Movy is still in very early-alpha stage and we are working heavily for new features
let mut tracer = TreeTracer::new();
let _ = executor.run_tx_trace(
tx,
epoch,
timestamp_ms,
Some(tracer),
)?;
println!("The trace is:\n{}", trace.take_inner().pprint());This snippet traces an arbitrary transaction tx, either on-chain or built by yourself.
Deploy your Move modules in a single function, even if it requires multiple transactions.
public fun movy_init(
deployer: address,
attacker: address
) {
let mut scenario = ts::begin(deployer);
{
ts::next_tx(&mut scenario, deployer);
counter::create(ts::ctx(&mut scenario));
};
ts::next_tx(&mut scenario, attacker);
{
let mut counter_val = ts::take_shared<Counter>(&scenario);
counter::increment(&mut counter_val, 0);
assert!(counter::value(&counter_val) == 1, 0);
ts::return_shared(counter_val);
};
ts::end(scenario);
}Write an invariant test for your functions in a Move testing module:
#[test]
public fun movy_pre_increment(
movy: &mut context::MovyContext,
ctr: &mut Counter,
_n: u64
) {
let (ctr_id, val) = extract_counter(ctr);
let state = context::borrow_mut_state(movy);
bag::add(state, ctr_id, val);
}
#[test]
public fun movy_post_increment(
movy: &mut context::MovyContext,
ctr: &mut Counter,
n: u64
) {
let (ctr_id, new_val) = extract_counter(ctr);
let state = context::borrow_state(movy);
let previous_val = bag::borrow<ID, u64>(state, ctr_id);
if (*previous_val + n != new_val) {
crash_because(b"Increment does not correctly inreases internal value.".to_string());
}
}Generate a type graph for a move package.
Generate a call graph for a move package.
TODO.
Install dependencies:
apt install -y libssl-dev libclang-devBuild movy binaries.
git clone https://github.com/BitsLabSec/movy
cd movy
cargo build --releaseNote a stable rust toolchain should be present.
Check the usage menu.
./target/release/movy --helpAdd this to your Cargo.toml
movy = {git = "https://github.com/BitsLabSec/movy", branch = "master"}Unfortunately, both sui and aptos are not on crates.io so we can not publish crates at this moment, unless we fully re-implement the MoveVM for both chains.
To write invariants for contracts, see the counter sample. Note you need to add the line to your Move.toml. It is test dependency and will be never live on-chain.
[dev-dependencies]
movy = {git = "https://github.com/BitsLabSec/movy", subdir = "move/movy", rev = "master"}Movy is very open to contributions! We expect your feedbacks and pull requests. See the roadmap or contact us for further information.
At this moment, movy is in very early-alpha state with the folloing features missing:
- Upstream our changes to sui and aptos-core
- Full Aptos support. (We have a private branch for that but still figuring out a good API design.)
- On-chain incidents backtesting.
Belobog is inspired by several pioneering projects:
