Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic types support #1399

Merged
merged 34 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
24f7521
Add total contract deposit
smiasojed Sep 27, 2023
a94edf0
Typo fixed, changelog updated
smiasojed Sep 28, 2023
64f2fe0
Rename item deposit to items deposit
smiasojed Sep 28, 2023
1234e21
Use of dynamic values
smiasojed Oct 20, 2023
1eef23b
Merge remote-tracking branch 'origin/master' into sm/storage-dep
smiasojed Oct 20, 2023
fee63d0
Added dynamic types
smiasojed Nov 7, 2023
4157790
Merge remote-tracking branch 'origin/master' into sm/storage-dep
smiasojed Nov 7, 2023
032c5d0
Cleanup
smiasojed Nov 7, 2023
7d650b5
Fixed items deposit name
smiasojed Nov 7, 2023
f0974f1
Merge remote-tracking branch 'origin/sm/storage-dep' into sm/dynamic
smiasojed Nov 8, 2023
6309523
Removed scale_decode dep and code cleanup
smiasojed Nov 8, 2023
5adbe28
Added unit test
smiasojed Nov 9, 2023
ff23ea2
Updated unit test
smiasojed Nov 10, 2023
06a8a0c
Merge remote-tracking branch 'origin/master' into sm/storage-dep
smiasojed Nov 10, 2023
5d0d28b
Updated tests
smiasojed Nov 10, 2023
18474d8
Fixed tests
smiasojed Nov 10, 2023
1b743dd
Renamed type
smiasojed Nov 10, 2023
e7fdf89
Added dynamic types for transactions
smiasojed Nov 10, 2023
b244fdf
Merge remote-tracking branch 'origin/sm/storage-dep' into sm/dynamic
smiasojed Nov 10, 2023
ab3c566
Add dynamic types
smiasojed Nov 13, 2023
88aba33
Fixed compact types
smiasojed Nov 14, 2023
7fbf8c8
Code refactoring and comments
smiasojed Nov 14, 2023
9a3e1bb
Make internal struct private
smiasojed Nov 15, 2023
742bda1
Code cleanup
smiasojed Nov 15, 2023
465b552
Merge remote-tracking branch 'origin/master' into sm/dynamic
smiasojed Nov 15, 2023
e790a43
Fixed unit test
smiasojed Nov 15, 2023
3ae240f
Make Weight internal to extrinsics crate
smiasojed Nov 16, 2023
2b16a8f
Renamed runtime_api
smiasojed Nov 21, 2023
521ceed
Move extrinsics calls to separate file
smiasojed Nov 21, 2023
3d564a0
Merge remote-tracking branch 'origin/master' into sm/dynamic
smiasojed Nov 21, 2023
9781ff7
Fix fmt
smiasojed Nov 21, 2023
315814e
Code cleanup
smiasojed Nov 22, 2023
d652522
Remove warnings and code cleanup
smiasojed Nov 22, 2023
3ac6d1c
Revert wasm-opt features and code cleanup
smiasojed Nov 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Remove check for compatible `scale` and `scale-info` versions - [#1370](https://github.com/paritytech/cargo-contract/pull/1370)
- Add workspace support -[#1358](https://github.com/paritytech/cargo-contract/pull/1358)
- Add `Storage Total Deposit` to `info` command output - [#1347](https://github.com/paritytech/cargo-contract/pull/1347)
- Add dynamic types support - [#1399](https://github.com/paritytech/cargo-contract/pull/1399)

### Fixed
- Do not allow to execute calls on immutable contract messages - [#1397](https://github.com/paritytech/cargo-contract/pull/1397)
Expand Down
13 changes: 3 additions & 10 deletions crates/cargo-contract/src/cmd/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ use super::{
display_all_contracts,
DefaultConfig,
};
use anyhow::{
anyhow,
Result,
};
use anyhow::Result;
use contract_analyze::determine_language;
use contract_extrinsics::{
fetch_all_contracts,
Expand Down Expand Up @@ -107,12 +104,8 @@ impl InfoCommand {

let info_to_json = fetch_contract_info(contract, &rpc, &client).await?;

let wasm_code = fetch_wasm_code(&client, &rpc, info_to_json.code_hash())
.await?
.ok_or(anyhow!(
"Contract wasm code was not found for account id {}",
contract
))?;
let wasm_code =
fetch_wasm_code(&client, &rpc, info_to_json.code_hash()).await?;
// Binary flag applied
if self.binary {
if self.output_json {
Expand Down
2 changes: 1 addition & 1 deletion crates/extrinsics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ documentation = "https://docs.rs/contract-extrinsics"
homepage = "https://www.substrate.io/"
description = "Library defining extrinsics for smart contracts on substrate"
keywords = ["wasm", "parity", "webassembly", "blockchain", "edsl"]
include = ["Cargo.toml", "*.rs", "LICENSE", "src/**/*.scale",]
include = ["Cargo.toml", "*.rs", "LICENSE",]

[dependencies]
contract-build = { version = "4.0.0-alpha", path = "../build" }
Expand Down
24 changes: 12 additions & 12 deletions crates/extrinsics/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use super::{
account_id,
events::DisplayEvents,
runtime_api::api,
state,
state_call,
submit_extrinsic,
Expand All @@ -33,6 +32,7 @@ use super::{
};
use crate::{
check_env_types,
extrinsic_calls::Call,
extrinsic_opts::ExtrinsicOpts,
};

Expand Down Expand Up @@ -240,10 +240,7 @@ impl CallExec {
pub async fn call_dry_run(&self) -> Result<ContractExecResult<Balance, ()>> {
let storage_deposit_limit = self
.opts
.storage_deposit_limit()
.as_ref()
.map(|bv| bv.denominate_balance(&self.token_metadata))
.transpose()?;
.storage_deposit_limit_balance(&self.token_metadata)?;
let call_request = CallRequest {
origin: account_id(&self.signer),
dest: self.contract.clone(),
Expand Down Expand Up @@ -281,7 +278,7 @@ impl CallExec {
"Tried to execute a call on the immutable contract message '{}'. Please do a dry-run instead.",
&self.message
);
return Err(inner.into());
return Err(inner.into())
}

// use user specified values where provided, otherwise estimate
Expand All @@ -290,15 +287,18 @@ impl CallExec {
None => self.estimate_gas().await?,
};
tracing::debug!("calling contract {:?}", self.contract);
let storage_deposit_limit = self
.opts
.storage_deposit_limit_balance(&self.token_metadata)?;

let call = api::tx().contracts().call(
let call = Call::new(
self.contract.clone().into(),
self.value.denominate_balance(&self.token_metadata)?,
gas_limit.into(),
self.opts
.compact_storage_deposit_limit(&self.token_metadata)?,
gas_limit,
storage_deposit_limit,
self.call_data.clone(),
);
)
.build();

let result =
submit_extrinsic(&self.client, &self.rpc, &call, &self.signer).await?;
Expand Down Expand Up @@ -416,7 +416,7 @@ impl CallExec {
///
/// Copied from `pallet-contracts-rpc-runtime-api`.
#[derive(Encode)]
pub struct CallRequest {
struct CallRequest {
origin: <DefaultConfig as Config>::AccountId,
dest: <DefaultConfig as Config>::AccountId,
value: Balance,
Expand Down
38 changes: 20 additions & 18 deletions crates/extrinsics/src/contract_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use anyhow::{

use super::{
get_best_block,
runtime_api::api,
Balance,
Client,
CodeHash,
Expand Down Expand Up @@ -207,18 +206,21 @@ pub async fn fetch_wasm_code(
client: &Client,
rpc: &LegacyRpcMethods<DefaultConfig>,
hash: &CodeHash,
) -> Result<Option<Vec<u8>>> {
let pristine_code_address = api::storage().contracts().pristine_code(hash);
) -> Result<Vec<u8>> {
let best_block = get_best_block(rpc).await?;

let pristine_bytes = client
let pristine_code_address =
dynamic("Contracts", "PristineCode", vec![Value::from_bytes(hash)]);
let pristine_code = client
.storage()
.at(best_block)
.fetch(&pristine_code_address)
.await?
.map(|v| v.0);

Ok(pristine_bytes)
.ok_or_else(|| anyhow!("No WASM code was found for code hash {}", hash))?;
let pristine_code = pristine_code
.as_type::<BoundedVec<u8>>()
.map_err(|e| anyhow!("Contract wasm code could not be parsed: {e}"));
pristine_code.map(|v| v.0)
}

/// Parse a contract account address from a storage key. Returns error if a key is
Expand All @@ -236,18 +238,18 @@ fn parse_contract_account_address(
.map_err(|err| anyhow!("AccountId deserialization error: {}", err))
}

/// Fetch all contract addresses from the storage using the provided client and count of
/// requested elements starting from an optional address
/// Fetch all contract addresses from the storage using the provided client.
pub async fn fetch_all_contracts(
client: &Client,
rpc: &LegacyRpcMethods<DefaultConfig>,
) -> Result<Vec<AccountId32>> {
let root_key = api::storage()
.contracts()
.contract_info_of_iter()
.to_root_bytes();

let best_block = get_best_block(rpc).await?;
let root_key = subxt::dynamic::storage(
"Contracts",
"ContractInfoOf",
vec![Value::from_bytes(AccountId32([0u8; 32]))],
)
.to_root_bytes();
let mut keys = client
.storage()
.at(best_block)
Expand Down Expand Up @@ -341,7 +343,7 @@ mod tests {
#[test]
fn contract_info_v11_decode_works() {
// This version of metadata includes the deposit_account field in ContractInfo
#[subxt::subxt(runtime_metadata_path = "src/runtime_api/metadata_v11.scale")]
#[subxt::subxt(runtime_metadata_path = "src/test_runtime_api/metadata_v11.scale")]
mod api_v11 {}

use api_v11::runtime_types::{
Expand All @@ -352,7 +354,7 @@ mod tests {
},
};

let metadata_bytes = std::fs::read("src/runtime_api/metadata_v11.scale")
let metadata_bytes = std::fs::read("src/test_runtime_api/metadata_v11.scale")
.expect("the metadata must be present");
let metadata =
Metadata::decode(&mut &*metadata_bytes).expect("the metadata must decode");
Expand Down Expand Up @@ -406,7 +408,7 @@ mod tests {
fn contract_info_v15_decode_works() {
// This version of metadata does not include the deposit_account field in
// ContractInfo
#[subxt::subxt(runtime_metadata_path = "src/runtime_api/metadata.scale")]
#[subxt::subxt(runtime_metadata_path = "src/test_runtime_api/metadata_v15.scale")]
mod api_v15 {}

use api_v15::runtime_types::{
Expand All @@ -417,7 +419,7 @@ mod tests {
pallet_contracts::storage::ContractInfo as ContractInfoV15,
};

let metadata_bytes = std::fs::read("src/runtime_api/metadata.scale")
let metadata_bytes = std::fs::read("src/test_runtime_api/metadata_v15.scale")
.expect("the metadata must be present");
let metadata =
Metadata::decode(&mut &*metadata_bytes).expect("the metadata must decode");
Expand Down
93 changes: 91 additions & 2 deletions crates/extrinsics/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use super::{
runtime_api::api::contracts::events::ContractEmitted,
Balance,
BalanceVariant,
CodeHash,
DefaultConfig,
TokenMetadata,
};
Expand All @@ -40,8 +41,96 @@ use subxt::{
self,
blocks::ExtrinsicEvents,
events::StaticEvent,
ext::{
scale_decode,
scale_encode,
},
Config,
};

/// A custom event emitted by the contract.
#[derive(
scale::Decode,
scale::Encode,
scale_decode::DecodeAsType,
scale_encode::EncodeAsType,
Debug,
)]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
pub struct ContractEmitted {
pub contract: <DefaultConfig as Config>::AccountId,
pub data: Vec<u8>,
}

impl StaticEvent for ContractEmitted {
const PALLET: &'static str = "Contracts";
const EVENT: &'static str = "ContractEmitted";
}

/// A contract was successfully instantiated.
#[derive(
Debug,
scale::Decode,
scale::Encode,
scale_decode::DecodeAsType,
scale_encode::EncodeAsType,
)]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
pub struct ContractInstantiated {
/// Account id of the deployer.
pub deployer: <DefaultConfig as Config>::AccountId,
/// Account id where the contract was instantiated to.
pub contract: <DefaultConfig as Config>::AccountId,
}

impl StaticEvent for ContractInstantiated {
const PALLET: &'static str = "Contracts";
const EVENT: &'static str = "Instantiated";
}

/// An event triggered by either the `instantiate_with_code` or the `upload_code` call.
#[derive(
Debug,
scale::Decode,
scale::Encode,
scale_decode::DecodeAsType,
scale_encode::EncodeAsType,
)]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
pub struct CodeStored {
/// Hash under which the contract code was stored.
pub code_hash: CodeHash,
}

impl StaticEvent for CodeStored {
const PALLET: &'static str = "Contracts";
const EVENT: &'static str = "CodeStored";
}

/// An event triggered by the `remove_code` call.
#[derive(
Debug,
scale::Decode,
scale::Encode,
scale_decode::DecodeAsType,
scale_encode::EncodeAsType,
)]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
pub struct CodeRemoved {
pub code_hash: CodeHash,
pub deposit_released: Balance,
pub remover: <DefaultConfig as Config>::AccountId,
}

impl StaticEvent for CodeRemoved {
const PALLET: &'static str = "Contracts";
const EVENT: &'static str = "CodeRemoved";
}

/// Field that represent data of an event from invoking a contract extrinsic.
#[derive(serde::Serialize)]
pub struct Field {
Expand All @@ -64,7 +153,7 @@ impl Field {
}
}

/// An event produced from from invoking a contract extrinsic.
/// An event produced from invoking a contract extrinsic.
#[derive(serde::Serialize)]
pub struct Event {
/// name of a pallet
Expand Down
Loading
Loading