diff --git a/.github/workflows/rust-checks.yml b/.github/workflows/rust-checks.yml index 599a306..5359683 100644 --- a/.github/workflows/rust-checks.yml +++ b/.github/workflows/rust-checks.yml @@ -56,7 +56,7 @@ jobs: shell: bash run: | rustup component add rust-src - cargo install cargo-contract --version 3.0.1 + cargo install cargo-contract --version 3.2.0 - name: Run tests for examples shell: bash diff --git a/Cargo.lock b/Cargo.lock index 2d04c76..1e99f0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -938,7 +938,7 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "drink" -version = "0.1.1" +version = "0.1.2" dependencies = [ "contract-transcode", "frame-support", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "drink-cli" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index ffbcac7..8b0f7ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ homepage = "https://github.com/Cardinal-Cryptography/drink" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/Cardinal-Cryptography/drink" -version = "0.1.1" +version = "0.1.2" [workspace.dependencies] anyhow = { version = "1.0.71" } @@ -43,4 +43,4 @@ sp-core = { version = "22.0.0" } # Local dependencies -drink = { version = "0.1.1", path = "drink" } +drink = { version = "0.1.2", path = "drink" } diff --git a/drink/src/chain_api.rs b/drink/src/chain_api.rs index 975396c..505ff1c 100644 --- a/drink/src/chain_api.rs +++ b/drink/src/chain_api.rs @@ -13,6 +13,10 @@ pub trait ChainApi { fn build_block(&mut self) -> DrinkResult; /// Build `n` empty blocks and return the new height. + /// + /// # Arguments + /// + /// * `n` - The number of blocks to build. fn build_blocks(&mut self, n: u64) -> DrinkResult { let mut last_block = None; for _ in 0..n { @@ -22,7 +26,19 @@ pub trait ChainApi { } /// Add tokens to an account. + /// + /// # Arguments + /// + /// * `address` - The address of the account to add tokens to. + /// * `amount` - The number of tokens to add. fn add_tokens(&mut self, address: AccountId32, amount: u128); + + /// Return the balance of an account. + /// + /// # Arguments + /// + /// * `address` - The address of the account to query. + fn balance(&mut self, address: &AccountId32) -> u128; } impl ChainApi for Sandbox { @@ -45,4 +61,9 @@ impl ChainApi for Sandbox { let _ = pallet_balances::Pallet::::deposit_creating(&address, amount); }); } + + fn balance(&mut self, address: &AccountId32) -> u128 { + self.externalities + .execute_with(|| pallet_balances::Pallet::::free_balance(address)) + } } diff --git a/drink/src/contract_api.rs b/drink/src/contract_api.rs index f65f065..1a62d6d 100644 --- a/drink/src/contract_api.rs +++ b/drink/src/contract_api.rs @@ -2,29 +2,69 @@ use frame_support::{sp_runtime::AccountId32, weights::Weight}; use pallet_contracts::{CollectEvents, DebugInfo, Determinism}; -use pallet_contracts_primitives::{Code, ContractExecResult, ContractInstantiateResult}; +use pallet_contracts_primitives::{ + Code, CodeUploadResult, ContractExecResult, ContractInstantiateResult, +}; use crate::{runtime::Runtime, EventRecordOf, Sandbox}; /// Interface for contract-related operations. pub trait ContractApi { /// Interface for `bare_instantiate` contract call. + /// + /// # Arguments + /// + /// * `contract_bytes` - The contract code. + /// * `value` - The number of tokens to be transferred to the contract. + /// * `data` - The input data to be passed to the contract (including constructor name). + /// * `salt` - The salt to be used for contract address derivation. + /// * `origin` - The sender of the contract call. + /// * `gas_limit` - The gas limit for the contract call. + /// * `storage_deposit_limit` - The storage deposit limit for the contract call. + #[allow(clippy::too_many_arguments)] fn deploy_contract( &mut self, contract_bytes: Vec, + value: u128, data: Vec, salt: Vec, origin: AccountId32, gas_limit: Weight, + storage_deposit_limit: Option, ) -> ContractInstantiateResult>; + /// Interface for `bare_upload_code` contract call. + /// + /// # Arguments + /// + /// * `contract_bytes` - The contract code. + /// * `origin` - The sender of the contract call. + /// * `storage_deposit_limit` - The storage deposit limit for the contract call. + fn upload_contract( + &mut self, + contract_bytes: Vec, + origin: AccountId32, + storage_deposit_limit: Option, + ) -> CodeUploadResult<::Hash, u128>; + /// Interface for `bare_call` contract call. + /// + /// # Arguments + /// + /// * `address` - The address of the contract to be called. + /// * `value` - The number of tokens to be transferred to the contract. + /// * `data` - The input data to be passed to the contract (including message name). + /// * `origin` - The sender of the contract call. + /// * `gas_limit` - The gas limit for the contract call. + /// * `storage_deposit_limit` - The storage deposit limit for the contract call. fn call_contract( &mut self, address: AccountId32, + value: u128, data: Vec, origin: AccountId32, gas_limit: Weight, + storage_deposit_limit: Option, ) -> ContractExecResult>; } @@ -32,17 +72,19 @@ impl ContractApi for Sandbox { fn deploy_contract( &mut self, contract_bytes: Vec, + value: u128, data: Vec, salt: Vec, origin: AccountId32, gas_limit: Weight, + storage_deposit_limit: Option, ) -> ContractInstantiateResult> { self.externalities.execute_with(|| { pallet_contracts::Pallet::::bare_instantiate( origin, - 0, + value, gas_limit, - None, + storage_deposit_limit, Code::Upload(contract_bytes), data, salt, @@ -52,20 +94,38 @@ impl ContractApi for Sandbox { }) } + fn upload_contract( + &mut self, + contract_bytes: Vec, + origin: AccountId32, + storage_deposit_limit: Option, + ) -> CodeUploadResult<::Hash, u128> { + self.externalities.execute_with(|| { + pallet_contracts::Pallet::::bare_upload_code( + origin, + contract_bytes, + storage_deposit_limit, + Determinism::Enforced, + ) + }) + } + fn call_contract( &mut self, address: AccountId32, + value: u128, data: Vec, origin: AccountId32, gas_limit: Weight, + storage_deposit_limit: Option, ) -> ContractExecResult> { self.externalities.execute_with(|| { pallet_contracts::Pallet::::bare_call( origin, address, - 0, + value, gas_limit, - None, + storage_deposit_limit, data, DebugInfo::UnsafeDebug, CollectEvents::UnsafeCollect, diff --git a/drink/src/session.rs b/drink/src/session.rs index c8c35a6..76dca03 100644 --- a/drink/src/session.rs +++ b/drink/src/session.rs @@ -13,6 +13,9 @@ use crate::{ Sandbox, DEFAULT_ACTOR, DEFAULT_GAS_LIMIT, }; +const ZERO_TRANSFER: u128 = 0; +const DEFAULT_STORAGE_DEPOSIT_LIMIT: Option = None; + /// Session specific errors. #[derive(Error, Debug)] pub enum SessionError { @@ -165,6 +168,11 @@ impl Session { &mut self.sandbox } + /// Returns a reference for basic contracts API. + pub fn contracts_api(&mut self) -> &mut impl ContractApi { + &mut self.sandbox + } + /// Deploys a contract with a given constructor, arguments and salt. In case of a success, /// returns `self`. pub fn deploy_and( @@ -196,10 +204,12 @@ impl Session { let result = self.sandbox.deploy_contract( contract_bytes, + ZERO_TRANSFER, data, salt, self.actor.clone(), self.gas_limit, + DEFAULT_STORAGE_DEPOSIT_LIMIT, ); let ret = match &result.result { @@ -272,9 +282,14 @@ impl Session { .clone(), }; - let result = self - .sandbox - .call_contract(address, data, self.actor.clone(), self.gas_limit); + let result = self.sandbox.call_contract( + address, + ZERO_TRANSFER, + data, + self.actor.clone(), + self.gas_limit, + DEFAULT_STORAGE_DEPOSIT_LIMIT, + ); let ret = match &result.result { Ok(exec_result) if exec_result.did_revert() => Err(SessionError::CallReverted), diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8f357ce..f400973 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.69" +channel = "1.70"