Skip to content

Commit

Permalink
Add simple testing and re-organize contract files. Include new test_u…
Browse files Browse the repository at this point in the history
…tils crate so we start sharing this across all contracts
  • Loading branch information
earrietadev committed Oct 11, 2024
1 parent ac33556 commit eb462af
Show file tree
Hide file tree
Showing 10 changed files with 605 additions and 298 deletions.
447 changes: 250 additions & 197 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]
resolver = "2"

members = ["contracts/*"]
members = ["contracts/*", "test_utils"]

[profile.release-with-logs]
inherits = "release"
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
build:
soroban contract build
stellar contract build --package registry
stellar contract build --package key-value-db

test:
soroban contract build
make build
cargo test

launch_standalone:
Expand Down
1 change: 1 addition & 0 deletions contracts/key-value-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ soroban-sdk = { workspace = true }

[dev_dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
test_utils = { path = "../../test_utils" }
94 changes: 94 additions & 0 deletions contracts/key-value-db/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use crate::registry::Domain;
use crate::types::{StorageKeys, Value};
use crate::utils::{
extend, extend_key, fetch_domain, get_adm, get_key, pay_fee, remove_key, set_key,
};
use soroban_sdk::{contract, contractimpl, panic_with_error, Address, BytesN, Env, Symbol};

use crate::errors::ContractErrors;

pub trait KeyValueDBTrait {
fn set_config(
e: Env,
adm: Address,
registry: Address,
fee: u128,
currency: Address,
treasury: Address,
);
fn upgrade(e: Env, hash: BytesN<32>);

fn set(e: Env, node: BytesN<32>, key: Symbol, value: Value);
fn get(e: Env, node: BytesN<32>, key: Symbol) -> Option<Value>;
fn remove(e: Env, node: BytesN<32>, key: Symbol);
}

#[contract]
pub struct KeyValueDB;

#[contractimpl]
impl KeyValueDBTrait for KeyValueDB {
fn set_config(
e: Env,
adm: Address,
registry: Address,
fee: u128,
currency: Address,
treasury: Address,
) {
if let Some(current_adm) = get_adm(&e) {
current_adm.require_auth();
}

e.storage().instance().set(&StorageKeys::Admin, &adm);
e.storage()
.instance()
.set(&StorageKeys::Registry, &registry);
e.storage().instance().set(&StorageKeys::Fee, &fee);
e.storage()
.instance()
.set(&StorageKeys::Currency, &currency);
e.storage()
.instance()
.set(&StorageKeys::Treasury, &treasury);

extend(&e);
}

fn upgrade(e: Env, hash: BytesN<32>) {
get_adm(&e).unwrap().require_auth();
e.deployer().update_current_contract_wasm(hash);
extend(&e);
}

fn set(e: Env, node: BytesN<32>, key: Symbol, value: Value) {
let domain: Domain = fetch_domain(&e, &node);
domain.owner.require_auth();
pay_fee(&e, &domain.owner);
set_key(&e, &node, &key, &value, &domain.snapshot);
extend_key(&e, &node, &key);
extend(&e);
}

fn get(e: Env, node: BytesN<32>, key: Symbol) -> Option<Value> {
extend_key(&e, &node, &key);
extend(&e);
match get_key(&e, &node, &key) {
Some((value, snapshot)) => {
let domain: Domain = fetch_domain(&e, &node);
if domain.snapshot != snapshot {
panic_with_error!(&e, &ContractErrors::KeyWasInvalidated);
}
Some(value)
}
None => None,
}
}

fn remove(e: Env, node: BytesN<32>, key: Symbol) {
let domain: Domain = fetch_domain(&e, &node);
domain.owner.require_auth();
remove_key(&e, &node, &key);
extend(&e);
}
}
100 changes: 3 additions & 97 deletions contracts/key-value-db/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,108 +1,14 @@
#![no_std]

const LEDGER_DAY: u32 = 17280;
mod contract;
mod errors;
mod tests;
mod types;
mod utils;

use crate::errors::ContractErrors;
use soroban_sdk::{contract, contractimpl, panic_with_error, Address, BytesN, Env, Symbol};

mod registry {
soroban_sdk::contractimport!(
file = "../../target/wasm32-unknown-unknown/release/registry.wasm"
);
}

use crate::registry::Domain;
use crate::types::{StorageKeys, Value};
use crate::utils::{
extend, extend_key, fetch_domain, get_adm, get_key, pay_fee, remove_key, set_key,
};

const LEDGER_DAY: u32 = 17280;

pub trait KeyValueDBTrait {
fn set_config(
e: Env,
adm: Address,
registry: Address,
fee: u128,
currency: Address,
treasury: Address,
);
fn upgrade(e: Env, hash: BytesN<32>);

fn set(e: Env, node: BytesN<32>, key: Symbol, value: Value);
fn get(e: Env, node: BytesN<32>, key: Symbol) -> Option<Value>;
fn remove(e: Env, node: BytesN<32>, key: Symbol);
}

#[contract]
pub struct KeyValueDB;

#[contractimpl]
impl KeyValueDBTrait for KeyValueDB {
fn set_config(
e: Env,
adm: Address,
registry: Address,
fee: u128,
currency: Address,
treasury: Address,
) {
if let Some(current_adm) = get_adm(&e) {
current_adm.require_auth();
}

e.storage().instance().set(&StorageKeys::Admin, &adm);
e.storage()
.instance()
.set(&StorageKeys::Registry, &registry);
e.storage().instance().set(&StorageKeys::Fee, &fee);
e.storage()
.instance()
.set(&StorageKeys::Currency, &currency);
e.storage()
.instance()
.set(&StorageKeys::Treasury, &treasury);

extend(&e);
}

fn upgrade(e: Env, hash: BytesN<32>) {
get_adm(&e).unwrap().require_auth();
e.deployer().update_current_contract_wasm(hash);
extend(&e);
}

fn set(e: Env, node: BytesN<32>, key: Symbol, value: Value) {
let domain: Domain = fetch_domain(&e, &node);
domain.owner.require_auth();
pay_fee(&e, &domain.owner);
set_key(&e, &node, &key, &value, &domain.snapshot);
extend_key(&e, &node, &key);
extend(&e);
}

fn get(e: Env, node: BytesN<32>, key: Symbol) -> Option<Value> {
extend_key(&e, &node, &key);
extend(&e);
match get_key(&e, &node, &key) {
Some((value, snapshot)) => {
let domain: Domain = fetch_domain(&e, &node);
if domain.snapshot != snapshot {
panic_with_error!(&e, &ContractErrors::KeyWasInvalidated);
}
Some(value)
}
None => None,
}
}

fn remove(e: Env, node: BytesN<32>, key: Symbol) {
let domain: Domain = fetch_domain(&e, &node);
domain.owner.require_auth();
remove_key(&e, &node, &key);
extend(&e);
}
}
59 changes: 59 additions & 0 deletions contracts/key-value-db/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#![cfg(test)]

use soroban_sdk::Env;
use test_utils::{create_global_test_data, key_value_db, registry, GlobalTestData};

#[test]
fn test_keys() {
let e: Env = Env::default();

let global_test_data: GlobalTestData = create_global_test_data(&e);
let registry_test_data: registry::TestData = registry::create_test_data(&e);
let key_value_db_test_data: key_value_db::TestData = key_value_db::create_test_data(&e);

global_test_data
.col_asset_stellar
.mock_all_auths()
.mint(&registry_test_data.test_domain_owner, &i128::MAX);

global_test_data
.gov_asset_stellar
.mock_all_auths()
.mint(&registry_test_data.test_domain_owner, &i128::MAX);

registry::init_contract(&global_test_data, &registry_test_data);
key_value_db::init_contract(
&global_test_data,
&registry_test_data,
&key_value_db_test_data,
);

registry_test_data
.contract_client
.mock_all_auths()
.set_record(
&registry_test_data.test_domain,
&registry_test_data.test_tld,
&registry_test_data.test_domain_owner,
&registry_test_data.test_domain_owner,
&registry_test_data.min_duration,
);

key_value_db_test_data.contract_client.mock_all_auths().set(
&registry_test_data.test_node,
&key_value_db_test_data.test_key,
&key_value_db_test_data.test_value,
);

let saved_value = key_value_db_test_data
.contract_client
.get(
&registry_test_data.test_node,
&key_value_db_test_data.test_key,
)
.unwrap();

assert_eq!(saved_value, key_value_db_test_data.test_value);
}

// TODO: test cases where no signature is provided, snapshot changed, providing wrong Record node and not enough funds to pay fee
3 changes: 2 additions & 1 deletion contracts/key-value-db/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::errors::ContractErrors;
use crate::registry::{ContractErrors as RegistryErrors, Domain, Record, RecordKeys};
use crate::{StorageKeys, Value, LEDGER_DAY};
use crate::types::{StorageKeys, Value};
use crate::LEDGER_DAY;
use soroban_sdk::{panic_with_error, symbol_short, token, Address, BytesN, Env, IntoVal, Symbol};

pub fn set_key(e: &Env, node: &BytesN<32>, key: &Symbol, value: &Value, snapshot: &u64) {
Expand Down
7 changes: 7 additions & 0 deletions test_utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "test_utils"
version = "0.1.0"
edition = "2021"

[dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
Loading

0 comments on commit eb462af

Please sign in to comment.