Skip to content

Commit

Permalink
add simulator tests
Browse files Browse the repository at this point in the history
  • Loading branch information
iFrostizz committed Jan 31, 2024
1 parent 4c3dae6 commit 9b8cad8
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 24 deletions.
6 changes: 5 additions & 1 deletion x/programs/rust/examples/csamm/scripts/tests.simulator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ simulator_bin="${simulator_path}"/bin/simulator
export SIMULATOR_PATH="${simulator_bin}"

# The path to the compiled Wasm program to be tested
export PROGRAM_PATH="${PWD}"/../../../examples/testdata/csamm.wasm
export TOKEN_PROGRAM_PATH="${PWD}"/../../build/token.wasm
export AMM_PROGRAM_PATH="${PWD}"/build/csamm.wasm

echo "Building CSAMM example..."
./../../scripts/build.sh

echo "Downloading dependencies..."
cd "${simulator_path}"
Expand Down
229 changes: 206 additions & 23 deletions x/programs/rust/examples/csamm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,35 +128,41 @@ fn exchange(program: Program, amount: i64) {
.unwrap();
}

/// Add or remove liquidity. Both asset amounts should conform with the CSAMM properties.
#[public]
fn manage_liquidity(program: Program, dx: i64, dy: i64) {
fn add_liquidity(program: Program, dx: u64, dy: u64) {
let sender = Address::new([0; 32]);
let this = Address::new(*program.id());

assert_eq!(dx, dy, "inconsistent liquidity token amounts");
assert_ne!(dx, 0, "cannot add 0 liquidity");

let (token_sender, token_recipient) = if dx > 0 {
(sender, this)
} else {
(this, sender)
};
token_x(program)
.call_function("transfer", params!(&sender, &this, &dx), 10000)
.unwrap();

token_y(program)
.call_function("transfer", params!(&sender, &this, &dy), 10000)
.unwrap();

// post: is the equation still standing ?
let (x, y) = balances(program);
assert_eq!(x, y, "CSAMM x + y = k property violated");
}

#[public]
fn remove_liquidity(program: Program, dx: u64, dy: u64) {
let sender = Address::new([0; 32]);
let this = Address::new(*program.id());

assert_eq!(dx, dy, "inconsistent liquidity token amounts");
assert_ne!(dx, 0, "cannot add 0 liquidity");

token_x(program)
.call_function(
"transfer",
params!(&token_sender, &token_recipient, &dx),
10000,
)
.call_function("transfer", params!(&this, &sender, &dx), 10000)
.unwrap();

token_y(program)
.call_function(
"transfer",
params!(&token_sender, &token_recipient, &dy),
10000,
)
.call_function("transfer", params!(&this, &sender, &dy), 10000)
.unwrap();

// post: is the equation still standing ?
Expand All @@ -169,13 +175,13 @@ mod tests {
use serial_test::serial;
use std::env;
use wasmlanche_sdk::simulator::{
self, id_from_step, Key, Operator, PlanResponse, Require, ResultAssertion,
id_from_step, Operator, PlanResponse, Require, ResultAssertion,
};

#[test]
#[serial]
#[ignore = "requires SIMULATOR_PATH and PROGRAM_PATH to be set"]
fn test_swap() {
#[ignore = "requires SIMULATOR_PATH, AMM_PROGRAM_PATH, and TOKEN_PROGRAM_PATH to be set"]
fn test_add_liquidity() {
use wasmlanche_sdk::simulator::{self, Endpoint, Key, Param, ParamType, Plan, Step};

let s_path = env::var(simulator::PATH_KEY).expect("SIMULATOR_PATH not set");
Expand All @@ -191,14 +197,191 @@ mod tests {
// create multiple step test plan
let mut plan = Plan::new(owner_key);

// step 0: create program
let p_path = env::var("PROGRAM_PATH").expect("PROGRAM_PATH not set");
// step 0: create amm program
let amm_path = env::var("AMM_PROGRAM_PATH").expect("AMM_PROGRAM_PATH not set");
plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "program_create".into(),
max_units: 0,
params: vec![Param::new(ParamType::String, amm_path.as_ref())],
require: None,
});
let amm_id = id_from_step(0);

// step 1: create token_x and token_x programs
let token_path = env::var("TOKEN_PROGRAM_PATH").expect("TOKEN_PROGRAM_PATH not set");
plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "program_create".into(),
max_units: 0,
params: vec![Param::new(ParamType::String, token_path.as_ref())],
require: None,
});
let token_x_id = id_from_step(1);

plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "program_create".into(),
max_units: 0,
params: vec![Param::new(ParamType::String, p_path.as_ref())],
params: vec![Param::new(ParamType::String, token_path.as_ref())],
require: None,
});
let token_y_id = id_from_step(2);

// step 2: create alice key
plan.add_step(Step {
endpoint: Endpoint::Key,
method: "key_create".into(),
params: vec![Param::new(ParamType::Key(Key::Ed25519), "alice_key")],
max_units: 0,
require: None,
});

// step 3: init tokens programs
plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "init".into(),
params: vec![Param::new(ParamType::Id, &token_x_id)],
max_units: 10000,
require: None,
});

plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "init".into(),
params: vec![Param::new(ParamType::Id, &token_y_id)],
max_units: 10000,
require: None,
});

// step 4: mint to alice
plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "mint_to".into(),
params: vec![
Param::new(ParamType::Id, &token_x_id),
Param::new(ParamType::Key(Key::Ed25519), "alice_key"),
Param::new(ParamType::U64, "1000"),
],
max_units: 10000,
require: None,
});

plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "mint_to".into(),
params: vec![
Param::new(ParamType::Id, &token_y_id),
Param::new(ParamType::Key(Key::Ed25519), "alice_key"),
Param::new(ParamType::U64, "1000"),
],
max_units: 10000,
require: None,
});

// step 5: add liquidity from alice with 100 tokens
plan.add_step(Step {
endpoint: Endpoint::Execute,
method: "add_liquidity".into(),
params: vec![
Param::new(ParamType::Id, &amm_id),
Param::new(ParamType::U64, "100"),
Param::new(ParamType::U64, "100"),
],
max_units: 10000,
require: None,
});

// run plan
let plan_responses = simulator.run::<PlanResponse>(&plan).unwrap();

// ensure no errors
assert!(
plan_responses.iter().all(|resp| resp.error.is_none()),
"error: {:?}",
plan_responses
.iter()
.filter_map(|resp| resp.error.as_ref())
.next()
);

let mut resp = plan_responses.iter();
let _program_amm_id = resp.next().unwrap().result.id.as_ref().unwrap();
let program_token_x_id = resp.next().unwrap().result.id.as_ref().unwrap();
let program_token_y_id = resp.next().unwrap().result.id.as_ref().unwrap();

// verify alice balance is 900
let resp = simulator
.read_only::<PlanResponse>(
"owner",
"get_balance",
vec![
Param::new(ParamType::Id, program_token_x_id),
Param::new(ParamType::Key(Key::Ed25519), "alice_key"),
],
Some(Require {
result: ResultAssertion {
operator: Operator::NumericEq,
value: "900".into(),
},
}),
)
.expect("failed to get alice balance");
assert_eq!(resp.error, None);

let resp = simulator
.read_only::<PlanResponse>(
"owner",
"get_balance",
vec![
Param::new(ParamType::Id, program_token_y_id),
Param::new(ParamType::Key(Key::Ed25519), "alice_key"),
],
Some(Require {
result: ResultAssertion {
operator: Operator::NumericEq,
value: "900".into(),
},
}),
)
.expect("failed to get alice balance");
assert_eq!(resp.error, None);

// verify program balance is 100
let resp = simulator
.read_only::<PlanResponse>(
"owner",
"get_balance",
vec![
Param::new(ParamType::Id, program_token_x_id),
Param::new(ParamType::Key(Key::Ed25519), "alice_key"),
],
Some(Require {
result: ResultAssertion {
operator: Operator::NumericEq,
value: "100".into(),
},
}),
)
.expect("failed to get program balance");
assert_eq!(resp.error, None);

let resp = simulator
.read_only::<PlanResponse>(
"owner",
"get_balance",
vec![
Param::new(ParamType::Id, program_token_y_id),
Param::new(ParamType::Id, &amm_id),
],
Some(Require {
result: ResultAssertion {
operator: Operator::NumericEq,
value: "100".into(),
},
}),
)
.expect("failed to get program balance");
assert_eq!(resp.error, None);
}
}
1 change: 1 addition & 0 deletions x/programs/rust/examples/token/scripts/tests.simulator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ go build -o "${simulator_bin}" "${simulator_path}"/simulator.go

echo "Running Simulator Tests..."

cd -
cargo test --lib -- --include-ignored

0 comments on commit 9b8cad8

Please sign in to comment.