diff --git a/Cargo.toml b/Cargo.toml index b620a86..a11ccb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,17 @@ [workspace] +members = ["contract", "tests"] +resolver = "2" -members = [ - "contract", - "tests", -] +[workspace.package] +edition = "2021" +homepage = "https://casperlabs.io" +license-file = "../LICENSE" +readme = "../README.md" +repository = "https://github.com/casper-ecosystem/hello-world" + +[workspace.dependencies] +casper-types = { git = "https://github.com/casper-network/casper-node", branch = "feat-2.0" } [profile.release] -lto = true +codegen-units = 1 +lto = true diff --git a/README.md b/README.md index 525ae69..9acdeec 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ casper-client put-deploy \ --payment-amount 5000000000000 \ --session-path [CONTRACT PATH]/contract.wasm \ --session-arg "message:string='hello world'" + --session-arg "key-name:string='my-custom_key-name'" ``` After the deploy is successful, you can view the new NamedKey `special_value` in the faucet account details. diff --git a/contract/Cargo.toml b/contract/Cargo.toml index 9374e15..e180322 100644 --- a/contract/Cargo.toml +++ b/contract/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "contract" -version = "0.1.0" +version = "0.2.0" authors = ["darthsiroftardis "] -edition = "2018" +edition = "2021" [dependencies] -casper-contract = "3.0.0" -casper-types = "3.0.0" +casper-types.workspace = true +casper-contract = { git = "https://github.com/casper-network/casper-node", branch = "feat-2.0" } [[bin]] name = "contract" diff --git a/contract/src/main.rs b/contract/src/main.rs index f0ec1c6..44e1138 100644 --- a/contract/src/main.rs +++ b/contract/src/main.rs @@ -7,25 +7,30 @@ use alloc::string::String; use casper_contract::contract_api::{runtime, storage}; use casper_types::{Key, URef}; -const KEY_NAME: &str = "my-key-name"; -const RUNTIME_ARG_NAME: &str = "message"; +const RUNTIME_ARG_KEY_NAME: &str = "key-name"; +const RUNTIME_ARG_MESSAGE: &str = "message"; -fn store(value: String) { +fn store(value: String, key_name: String) { // Store `value` under a new unforgeable reference. let value_ref: URef = storage::new_uref(value); // Wrap the unforgeable reference in a value of type `Key`. let value_key: Key = value_ref.into(); - // Store this key under the name "my-key-name" in caller context - runtime::put_key(KEY_NAME, value_key); + // Remove the key if already exists in account entity context + runtime::remove_key(&key_name); + + // Store this key under the name "key-name" in caller context + runtime::put_key(&key_name, value_key); } // All session code must have a `call` entrypoint. #[no_mangle] pub extern "C" fn call() { - // This contract expects a single runtime argument to be provided. The arg is named "message" - // and will be of type `String`. - let value: String = runtime::get_named_arg(RUNTIME_ARG_NAME); - store(value); + // This contract expectstwo runtime arguments to be provided. + // The arg is named "message"and will be of type `String`. + let message: String = runtime::get_named_arg(RUNTIME_ARG_MESSAGE); + // The arg is named "key-name" and will be of type `String`. + let key_name: String = runtime::get_named_arg(RUNTIME_ARG_KEY_NAME); + store(message, key_name); } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 0b1fddd..0993aa9 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -1,15 +1,12 @@ [package] name = "tests" -version = "0.1.0" -edition = "2018" +version = "0.2.0" +edition = "2021" [dev-dependencies] -casper-engine-test-support = "5.0.0" -casper-contract = { version = "3.0.0", default-features = false, features = [ - "test-support", -] } -casper-execution-engine = "5.0.0" -casper-types = "3.0.0" +casper-types.workspace = true +casper-engine-test-support = { git = "https://github.com/casper-network/casper-node.git", branch = "feat-2.0", default-features = false } +casper-execution-engine = { git = "https://github.com/casper-network/casper-node.git", branch = "feat-2.0", default-features = false } [[bin]] name = "integration-tests" diff --git a/tests/rust-toolchain b/tests/rust-toolchain new file mode 100644 index 0000000..870bbe4 --- /dev/null +++ b/tests/rust-toolchain @@ -0,0 +1 @@ +stable \ No newline at end of file diff --git a/tests/src/integration_tests.rs b/tests/src/integration_tests.rs index aa23925..36e5138 100644 --- a/tests/src/integration_tests.rs +++ b/tests/src/integration_tests.rs @@ -1,25 +1,34 @@ +fn main() { + panic!("Execute \"cargo test\" to test the contract, not \"cargo run\"."); +} #[cfg(test)] mod tests { use std::path::PathBuf; use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, InMemoryWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + utils::create_run_genesis_request, DeployItemBuilder, ExecuteRequestBuilder, + LmdbWasmTestBuilder, ARG_AMOUNT, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, + DEFAULT_PAYMENT, }; - use casper_execution_engine::core::{engine_state::Error as EngineStateError, execution}; - use casper_types::{runtime_args, ApiError, Key, RuntimeArgs}; + use casper_execution_engine::{engine_state::Error as CoreError, execution::ExecError}; - // Define `KEY_NAME` constant to match that in the contract. - const KEY_NAME: &str = "my-key-name"; - const VALUE: &str = "hello world"; - const RUNTIME_ARG_NAME: &str = "message"; + use casper_types::{runtime_args, ApiError, GenesisAccount, Key, Motes, RuntimeArgs, U512}; + + const RUNTIME_ARG_KEY_NAME: &str = "key-name"; + const KEY_NAME_VALUE: &str = "my-custom_key-name"; + const RUNTIME_ARG_MESSAGE: &str = "message"; + const MESSAGE_VALUE: &str = "hello world"; const CONTRACT_WASM: &str = "contract.wasm"; #[test] fn should_store_hello_world() { - let mut builder = InMemoryWasmTestBuilder::default(); + let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST) + .run_genesis(create_run_genesis_request(vec![GenesisAccount::Account { + public_key: DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + balance: Motes::new(U512::from(5_000_000_000_000_u64)), + validator: None, + }])) .commit(); // The test framework checks for compiled Wasm files in '/wasm'. Paths @@ -27,11 +36,12 @@ mod tests { // absolute paths. let session_code = PathBuf::from(CONTRACT_WASM); let session_args = runtime_args! { - RUNTIME_ARG_NAME => VALUE, + RUNTIME_ARG_MESSAGE => MESSAGE_VALUE, + RUNTIME_ARG_KEY_NAME => KEY_NAME_VALUE }; let deploy_item = DeployItemBuilder::new() - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }) .with_session_code(session_code, session_args) @@ -39,13 +49,13 @@ mod tests { .with_address(*DEFAULT_ACCOUNT_ADDR) .build(); - let execute_request = ExecuteRequestBuilder::from_deploy_item(deploy_item).build(); + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); // prepare assertions. let result_of_query = builder.query( None, Key::Account(*DEFAULT_ACCOUNT_ADDR), - &[KEY_NAME.to_string()], + &[KEY_NAME_VALUE.to_string()], ); assert!(result_of_query.is_err()); @@ -57,7 +67,7 @@ mod tests { .query( None, Key::Account(*DEFAULT_ACCOUNT_ADDR), - &[KEY_NAME.to_string()], + &[KEY_NAME_VALUE.to_string()], ) .expect("should be stored value.") .as_cl_value() @@ -66,7 +76,7 @@ mod tests { .into_t::() .expect("should be string."); - assert_eq!(result_of_query, VALUE); + assert_eq!(result_of_query, MESSAGE_VALUE); } #[test] @@ -75,33 +85,34 @@ mod tests { let session_args = RuntimeArgs::new(); let deploy_item = DeployItemBuilder::new() - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code(session_code, session_args) .build(); - let execute_request = ExecuteRequestBuilder::from_deploy_item(deploy_item).build(); + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - let mut builder = InMemoryWasmTestBuilder::default(); + let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST) + .run_genesis(create_run_genesis_request(vec![GenesisAccount::Account { + public_key: DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + balance: Motes::new(U512::from(5_000_000_000_000_u64)), + validator: None, + }])) .commit(); builder.exec(execute_request).commit().expect_failure(); let actual_error = builder.get_error().expect("must have error"); + assert!( matches!( actual_error, - EngineStateError::Exec(execution::Error::Revert(ApiError::MissingArgument)) + CoreError::Exec(ExecError::Revert(ApiError::MissingArgument)) ), "Expected {:?}, received {:?}", - EngineStateError::Exec(execution::Error::Revert(ApiError::MissingArgument)), + CoreError::Exec(ExecError::Revert(ApiError::MissingArgument)), actual_error ); } } - -fn main() { - panic!("Execute \"cargo test\" to test the contract, not \"cargo run\"."); -}