diff --git a/concordium-std/Cargo.toml b/concordium-std/Cargo.toml index a48f4732..40d27791 100644 --- a/concordium-std/Cargo.toml +++ b/concordium-std/Cargo.toml @@ -22,8 +22,8 @@ quickcheck = {version = "1", optional = true } getrandom = { version = "0.2", features = ["custom"], optional = true } [dependencies.concordium-contracts-common] -path = "../../../LocalTestingLibrary/concordium-smart-contract-tools/concordium-base/concordium-contracts-common/concordium-contracts-common" -version = "7.1" +path = "../concordium-contracts-common/concordium-contracts-common" +version = "7.0" default-features = false features = ["smart-contract"] diff --git a/examples/cis3-nft-sponsored-txs/Cargo.toml b/examples/cis3-nft-sponsored-txs/Cargo.toml index 56c2254c..fa6d0a09 100644 --- a/examples/cis3-nft-sponsored-txs/Cargo.toml +++ b/examples/cis3-nft-sponsored-txs/Cargo.toml @@ -15,10 +15,6 @@ crypto-primitives = ["concordium-std/crypto-primitives"] concordium-std = {path = "../../concordium-std", default-features = false} concordium-cis2 = {path = "../../concordium-cis2", default-features = false} -[dev-dependencies] -concordium-smart-contract-testing = {path = "../../../../LocalTestingLibrary/concordium-smart-contract-tools/concordium-smart-contract-testing"} -ed25519-dalek = "1.0.1" - [lib] crate-type=["cdylib", "rlib"] diff --git a/examples/cis3-nft-sponsored-txs/tests/test.rs b/examples/cis3-nft-sponsored-txs/tests/test.rs deleted file mode 100644 index 36beb03a..00000000 --- a/examples/cis3-nft-sponsored-txs/tests/test.rs +++ /dev/null @@ -1,643 +0,0 @@ -//! This module contains integration tests for the cis3-sponsored-transaction -//! contract. To run them, use `cargo test`. -use cis3_nft_sponsored_txs::{ - AccountAddressStruct, ContractTokenAmount, ContractTokenId, MintParams, NonceEvent, - NonceOfQueryResponse, PermitMessage, PermitParam, PublicKeyOfQueryResponse, - VecOfAccountAddresses, NONCE_EVENT_TAG, -}; -use concordium_cis2::{TokenIdU32, *}; -use concordium_smart_contract_testing::{AccountAccessStructure, *}; -use concordium_std::{ - AccountPublicKeys, AccountSignatures, CredentialSignatures, PublicKey, SignatureEd25519, - Timestamp, -}; -use std::collections::BTreeMap; - -const ACC_ADDR_OWNER: AccountAddress = AccountAddress([0u8; 32]); -const ADDR_OWNER: Address = Address::Account(ACC_ADDR_OWNER); -const ACC_ADDR_OTHER: AccountAddress = AccountAddress([1u8; 32]); -const ADDR_OTHER: Address = Address::Account(ACC_ADDR_OTHER); -const NON_EXISTING_ACCOUNT: AccountAddress = AccountAddress([2u8; 32]); -const ACC_INITIAL_BALANCE: Amount = Amount::from_ccd(1000); - -const TOKEN_1: TokenIdU32 = TokenIdU32(1); - -// Private key: 8ECA45107A878FB879B84401084B55AD4919FC0F7D14E8915D8A5989B1AE1C01 -const PUBLIC_KEY: [u8; 32] = [ - 120, 154, 141, 6, 248, 239, 77, 224, 80, 62, 139, 136, 211, 204, 105, 208, 26, 11, 2, 208, 195, - 253, 29, 192, 126, 199, 208, 39, 69, 4, 246, 32, -]; - -const SIGNATURE_TRANSFER: SignatureEd25519 = SignatureEd25519([ - 46, 96, 133, 143, 232, 24, 149, 54, 217, 245, 162, 135, 64, 125, 32, 61, 209, 147, 240, 151, - 19, 244, 137, 244, 91, 59, 120, 202, 39, 201, 82, 39, 64, 210, 250, 183, 187, 27, 147, 50, 31, - 88, 78, 79, 78, 135, 192, 72, 38, 234, 90, 226, 89, 75, 124, 86, 1, 190, 196, 195, 248, 19, - 181, 11, -]); - -const SIGNATURE_UPDATE_OPERATOR: SignatureEd25519 = SignatureEd25519([ - 50, 83, 36, 119, 75, 223, 109, 182, 152, 68, 46, 46, 249, 11, 169, 109, 51, 211, 47, 56, 60, - 155, 62, 59, 70, 8, 107, 72, 147, 141, 226, 153, 43, 234, 82, 164, 168, 43, 202, 244, 213, 95, - 101, 101, 155, 226, 130, 77, 47, 243, 161, 219, 100, 208, 106, 109, 102, 189, 171, 159, 22, - 179, 148, 0, -]); - -/// A helper method for setting up: -/// - The chain, -/// - The two accounts `ACC_ADDR_OWNER` and `ACC_ADDR_OTHER`, both with -/// `ACC_INITIAL_BALANCE` CCD. `ACC_ADDR_OTHER` will be set up with valid -/// public keys so it can generate signatures. -/// - The deployed and initialized contract. -fn setup_chain_and_contract() -> (Chain, ContractInitSuccess) { - let mut chain = Chain::new(); - - let balance = AccountBalance { - total: ACC_INITIAL_BALANCE, - staked: Amount::zero(), - locked: Amount::zero(), - }; - - let mut inner_key_map: BTreeMap = BTreeMap::new(); - - inner_key_map.insert( - KeyIndex(0u8), - VerifyKey::Ed25519VerifyKey( - ed25519_dalek::PublicKey::from_bytes(&PUBLIC_KEY) - .expect("Should be able to create public key"), - ), - ); - - let credential_public_keys = CredentialPublicKeys { - keys: inner_key_map, - threshold: SignatureThreshold::ONE, - }; - - let mut key_map: BTreeMap = BTreeMap::new(); - key_map.insert( - CredentialIndex { - index: 0u8, - }, - credential_public_keys, - ); - - let keys = AccountAccessStructure { - keys: key_map, - threshold: AccountThreshold::ONE, - }; - chain.create_account(Account::new_with_keys(ACC_ADDR_OTHER, balance, keys)); - chain.create_account(Account::new(ACC_ADDR_OWNER, ACC_INITIAL_BALANCE)); - - let module = module_load_v1("contract.wasm.v1").expect("Module exists and is valid"); - let deployment = chain - .module_deploy_v1(Signer::with_one_key(), ACC_ADDR_OWNER, module) - .expect("Deploying valid module should succeed"); - - let initialization = chain - .contract_init( - Signer::with_one_key(), - ACC_ADDR_OWNER, - Energy::from(10000), - InitContractPayload { - amount: Amount::zero(), - mod_ref: deployment.module_reference, - init_name: OwnedContractName::new_unchecked("init_cis3_nft".to_string()), - param: OwnedParameter::empty(), - }, - ) - .expect("Initialization should always succeed"); - - (chain, initialization) -} - -/// Test that initializing the contract works and that its balance can be -/// queried afterwards. -#[test] -fn test_init() { - let (chain, initialization) = setup_chain_and_contract(); - assert_eq!( - chain.contract_balance(initialization.contract_address), - Some(Amount::zero()), - "Contract should be initilized with 0 CCD" - ); -} - -/// Test `nonceOf` query. We check that the nonce of `ACC_ADDR_OTHER` is 1 when -/// the account already sent one sponsored transaction. We check that the nonce -/// of `ACC_ADDR_OWNER` is 0 when the account did not send any sponsored -/// transaction. We check that the nonce of `NON_EXISTING_ACCOUNT` is 0. -#[test] -fn test_nonce_of_query() { - let (mut chain, initialization) = setup_chain_and_contract(); - - // To increase the nonce of account `ACC_ADDR_OTHER`, we invoke the - // `update_permit` function with a valid signature from account - // `ACC_ADDR_OTHER`. - - // Create input parematers for the `permit` updateOperator function. - let update_operator = UpdateOperator { - update: OperatorUpdate::Add, - operator: ADDR_OWNER, - }; - let payload = UpdateOperatorParams(vec![update_operator]); - - let mut inner_signature_map = BTreeMap::new(); - inner_signature_map.insert(0u8, concordium_std::Signature::Ed25519(SIGNATURE_UPDATE_OPERATOR)); - - let mut signature_map = BTreeMap::new(); - signature_map.insert(0u8, CredentialSignatures { - sigs: inner_signature_map, - }); - - let permit_update_operator_param = PermitParam { - signature: AccountSignatures { - sigs: signature_map, - }, - signer: ACC_ADDR_OTHER, - message: PermitMessage { - timestamp: Timestamp::from_timestamp_millis(10000000000), - contract_address: ContractAddress { - index: 0, - subindex: 0, - }, - entry_point: OwnedEntrypointName::new_unchecked("updateOperator".into()), - nonce: 0, - payload: to_bytes(&payload), - }, - }; - - // Update operator with the permit function. - let _ = chain - .contract_update( - Signer::with_one_key(), - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.permit".to_string()), - message: OwnedParameter::from_serial(&permit_update_operator_param) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to update operator with permit"); - - // Check if correct nonces are returned by the `nonceOf` function. - let nonce_query_vector = VecOfAccountAddresses { - queries: vec![ - AccountAddressStruct { - account: ACC_ADDR_OTHER, - }, - AccountAddressStruct { - account: ACC_ADDR_OWNER, - }, - AccountAddressStruct { - account: NON_EXISTING_ACCOUNT, - }, - ], - }; - - let invoke = chain - .contract_invoke( - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.nonceOf".to_string()), - message: OwnedParameter::from_serial(&nonce_query_vector) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to query publicKeyOf"); - - let nonces: NonceOfQueryResponse = - from_bytes(&invoke.return_value).expect("Should return a valid result"); - - assert_eq!( - nonces.0[0], 1, - "Nonce of ACC_ADDR_OTHER should be 1 because the account already sent one sponsored \ - transaction" - ); - assert_eq!( - nonces.0[1], 0, - "Nonce of ACC_ADDR_OWNER should be 0 because the account did not send any sponsored \ - transaction" - ); - assert_eq!(nonces.0[2], 0, "Nonce of non-existing account should be 0"); -} - -/// Test `publicKeyOf` query. `ACC_ADDR_OTHER` should have its correct keys -/// returned. `NON_EXISTING_ACCOUNT` should have `None` returned because it does -/// not exist on chain. -#[test] -fn test_public_key_of_query() { - let (chain, initialization) = setup_chain_and_contract(); - - let public_key_of_query_vector = VecOfAccountAddresses { - queries: vec![ - AccountAddressStruct { - account: ACC_ADDR_OTHER, - }, - AccountAddressStruct { - account: NON_EXISTING_ACCOUNT, - }, - ], - }; - - let invoke = chain - .contract_invoke( - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.publicKeyOf".to_string()), - message: OwnedParameter::from_serial(&public_key_of_query_vector) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to query publicKeyOf"); - - let public_keys_of: PublicKeyOfQueryResponse = - from_bytes(&invoke.return_value).expect("Should return a valid result"); - - let mut inner_key_map: BTreeMap = BTreeMap::new(); - - inner_key_map.insert(0u8, PublicKey::Ed25519(concordium_std::PublicKeyEd25519(PUBLIC_KEY))); - - let credential_public_keys = concordium_std::CredentialPublicKeys { - keys: inner_key_map, - threshold: SignatureThreshold::ONE, - }; - - let mut key_map: BTreeMap = BTreeMap::new(); - key_map.insert(0u8, credential_public_keys); - - let account_public_keys: AccountPublicKeys = AccountPublicKeys { - keys: key_map, - threshold: AccountThreshold::ONE, - }; - - assert_eq!( - public_keys_of.0[0], - Some(account_public_keys), - "An existing account should have correct public keys returned" - ); - assert!(public_keys_of.0[1].is_none(), "Non existing account should have no public keys"); -} - -/// Permit transfer function. -#[test] -fn test_permit_transfer() { - let (mut chain, initialization) = setup_chain_and_contract(); - - // Owner of the newly minted token. - let mint_param = MintParams { - owner: ADDR_OTHER, - }; - - // Mint token. - let _ = chain - .contract_update( - Signer::with_one_key(), - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.mint".to_string()), - message: OwnedParameter::from_serial(&mint_param) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to mint token"); - - // Check balances in state. - let balance_of_query = BalanceOfQuery { - token_id: TOKEN_1, - address: ADDR_OWNER, - }; - let balance_of_query2 = BalanceOfQuery { - token_id: TOKEN_1, - address: ADDR_OTHER, - }; - - let balance_of_query_vector = BalanceOfQueryParams { - queries: vec![balance_of_query, balance_of_query2], - }; - - let invoke = chain - .contract_invoke( - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.balanceOf".to_string()), - message: OwnedParameter::from_serial(&balance_of_query_vector) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to query balanceOf"); - - let balance_of: BalanceOfQueryResponse = - from_bytes(&invoke.return_value).expect("Should return a valid result"); - - assert_eq!(balance_of.0, [TokenAmountU8(0), TokenAmountU8(1)]); - - let transfer = concordium_cis2::Transfer { - from: ADDR_OTHER, - to: Receiver::from_account(ACC_ADDR_OWNER), - token_id: TOKEN_1, - amount: ContractTokenAmount::from(1), - data: AdditionalData::empty(), - }; - let payload = TransferParams::from(vec![transfer]); - - let mut inner_signature_map = BTreeMap::new(); - inner_signature_map.insert(0u8, concordium_std::Signature::Ed25519(SIGNATURE_TRANSFER)); - - let mut signature_map = BTreeMap::new(); - signature_map.insert(0u8, CredentialSignatures { - sigs: inner_signature_map, - }); - - let permit_transfer_param = PermitParam { - signature: AccountSignatures { - sigs: signature_map, - }, - signer: ACC_ADDR_OTHER, - message: PermitMessage { - timestamp: Timestamp::from_timestamp_millis(10000000000), - contract_address: ContractAddress { - index: 0, - subindex: 0, - }, - entry_point: OwnedEntrypointName::new_unchecked("transfer".into()), - nonce: 0, - payload: to_bytes(&payload), - }, - }; - - // Transfer token with the permit function. - let update = chain - .contract_update( - Signer::with_one_key(), - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.permit".to_string()), - message: OwnedParameter::from_serial(&permit_transfer_param) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to transfer token with permit"); - - // Check logged events. - let events: Vec<(ContractAddress, &[ContractEvent])> = update.events().collect(); - - // Check transfer event. - let transfer_event = &events[0].1[0]; - - // Check event tag. - assert_eq!(transfer_event.as_ref()[0], TRANSFER_EVENT_TAG, "Transfer event tag is wrong"); - - // We remove the tag byte at the beginning of the event. - let transfer_event_type: TransferEvent = - from_bytes(&transfer_event.as_ref()[1..]).expect("Tag removal should work"); - - assert_eq!( - transfer_event_type, - TransferEvent { - token_id: TOKEN_1, - amount: ContractTokenAmount::from(1), - from: ADDR_OTHER, - to: ADDR_OWNER, - }, - "Transfer event is wrong" - ); - - // Check nonce event. - let nonce_event = &events[0].1[1]; - - // Check event tag. - assert_eq!(nonce_event.as_ref()[0], NONCE_EVENT_TAG, "Nonce event tag is wrong"); - - // We remove the tag byte at the beginning of the event. - let nonce_event_type: NonceEvent = - from_bytes(&nonce_event.as_ref()[1..]).expect("Tag removal should work"); - - assert_eq!( - nonce_event_type, - NonceEvent { - account: ACC_ADDR_OTHER, - nonce: 0, - }, - "Nonce event is wrong" - ); - - // Check balances in state - let balance_of_query_owner = BalanceOfQuery { - token_id: TOKEN_1, - address: ADDR_OWNER, - }; - let balance_of_query_other = BalanceOfQuery { - token_id: TOKEN_1, - address: ADDR_OTHER, - }; - - let balance_of_query_vector = BalanceOfQueryParams { - queries: vec![balance_of_query_owner, balance_of_query_other], - }; - - let invoke = chain - .contract_invoke( - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.balanceOf".to_string()), - message: OwnedParameter::from_serial(&balance_of_query_vector) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to query balanceOf"); - - let balance_of: BalanceOfQueryResponse = - from_bytes(&invoke.return_value).expect("Should return a valid result"); - - assert_eq!(balance_of.0, [TokenAmountU8(1), TokenAmountU8(0)]); -} - -/// Permit update operator function. -#[test] -fn test_update_operator() { - let (mut chain, initialization) = setup_chain_and_contract(); - - // Check operator in state - let operator_of_query = OperatorOfQuery { - address: ADDR_OWNER, - owner: ADDR_OTHER, - }; - - let operator_of_query_vector = OperatorOfQueryParams { - queries: vec![operator_of_query], - }; - - // Check operator in state - let invoke = chain - .contract_invoke( - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.operatorOf".to_string()), - message: OwnedParameter::from_serial(&operator_of_query_vector) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to query operatorOf"); - - let is_operator_of: OperatorOfQueryResponse = - from_bytes(&invoke.return_value).expect("Should return a valid result"); - - assert_eq!(is_operator_of.0, [false]); - - // Create input parematers for the `permit` updateOperator function. - let update_operator = UpdateOperator { - update: OperatorUpdate::Add, - operator: ADDR_OWNER, - }; - let payload = UpdateOperatorParams(vec![update_operator]); - - let mut inner_signature_map = BTreeMap::new(); - inner_signature_map.insert(0u8, concordium_std::Signature::Ed25519(SIGNATURE_UPDATE_OPERATOR)); - - let mut signature_map = BTreeMap::new(); - signature_map.insert(0u8, CredentialSignatures { - sigs: inner_signature_map, - }); - - let permit_update_operator_param = PermitParam { - signature: AccountSignatures { - sigs: signature_map, - }, - signer: ACC_ADDR_OTHER, - message: PermitMessage { - timestamp: Timestamp::from_timestamp_millis(10000000000), - contract_address: ContractAddress { - index: 0, - subindex: 0, - }, - entry_point: OwnedEntrypointName::new_unchecked("updateOperator".into()), - nonce: 0, - payload: to_bytes(&payload), - }, - }; - - // Update operator with the permit function. - let update = chain - .contract_update( - Signer::with_one_key(), - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.permit".to_string()), - message: OwnedParameter::from_serial(&permit_update_operator_param) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to update operator with permit"); - - // Check logged events. - let events: Vec<(ContractAddress, &[ContractEvent])> = update.events().collect(); - - // Check update operator event. - let update_operator_event = &events[0].1[0]; - - // Check event tag. - assert_eq!( - update_operator_event.as_ref()[0], - UPDATE_OPERATOR_EVENT_TAG, - "Update operator event tag is wrong" - ); - - // We remove the tag byte at the beginning of the event. - let update_operator_event_type: UpdateOperatorEvent = - from_bytes(&update_operator_event.as_ref()[1..]).expect("Tag removal should work"); - - assert_eq!( - update_operator_event_type, - UpdateOperatorEvent { - update: OperatorUpdate::Add, - owner: ADDR_OTHER, - operator: ADDR_OWNER, - }, - "Update operator event is wrong" - ); - - // Check nonce event. - let nonce_event = &events[0].1[1]; - - // Check event tag. - assert_eq!(nonce_event.as_ref()[0], NONCE_EVENT_TAG, "Nonce event tag is wrong"); - - // We remove the tag byte at the beginning of the event. - let nonce_event_type: NonceEvent = - from_bytes(&nonce_event.as_ref()[1..]).expect("Tag removal should work"); - - assert_eq!( - nonce_event_type, - NonceEvent { - account: ACC_ADDR_OTHER, - nonce: 0, - }, - "Nonce event is wrong" - ); - - // Check operator in state - let operator_of_query = OperatorOfQuery { - address: ADDR_OWNER, - owner: ADDR_OTHER, - }; - - let operator_of_query_vector = OperatorOfQueryParams { - queries: vec![operator_of_query], - }; - - // Check operator in state - let invoke = chain - .contract_invoke( - ACC_ADDR_OWNER, - Address::Account(ACC_ADDR_OWNER), - Energy::from(10000), - UpdateContractPayload { - amount: Amount::zero(), - address: initialization.contract_address, - receive_name: OwnedReceiveName::new_unchecked("cis3_nft.operatorOf".to_string()), - message: OwnedParameter::from_serial(&operator_of_query_vector) - .expect("Should be a valid inut parameter"), - }, - ) - .expect("Should be able to query operatorOf"); - - let is_operator_of: OperatorOfQueryResponse = - from_bytes(&invoke.return_value).expect("Should return a valid result"); - - assert_eq!(is_operator_of.0, [true]) -}