From 55fb1e6c5e4ab1a255a3d5678e0b56a5fc167955 Mon Sep 17 00:00:00 2001 From: ascjones Date: Thu, 31 Mar 2022 12:31:52 +0100 Subject: [PATCH 1/2] Dry run instantiate gas estimation --- src/cmd/extrinsics/instantiate.rs | 34 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/cmd/extrinsics/instantiate.rs b/src/cmd/extrinsics/instantiate.rs index 57a984ed..cf721a69 100644 --- a/src/cmd/extrinsics/instantiate.rs +++ b/src/cmd/extrinsics/instantiate.rs @@ -57,9 +57,10 @@ pub struct InstantiateCommand { /// Transfers an initial balance to the instantiated contract #[clap(name = "value", long, default_value = "0", parse(try_from_str = parse_balance))] value: Balance, - /// Maximum amount of gas to be used for this command - #[clap(name = "gas", long, default_value = "50000000000")] - gas_limit: u64, + /// Maximum amount of gas to be used for this command. + /// Skips the dry-run to estimate the gas consumed for the instantiation. + #[clap(name = "gas", long)] + gas_limit: Option, /// A salt used in the address derivation of the new contract. Use to create multiple instances /// of the same contract code from the same account. #[clap(long, parse(try_from_str = parse_hex_bytes))] @@ -141,7 +142,7 @@ impl InstantiateCommand { struct InstantiateArgs { value: super::Balance, - gas_limit: u64, + gas_limit: Option, storage_deposit_limit: Option, data: Vec, salt: Bytes, @@ -219,12 +220,18 @@ impl<'a> Exec<'a> { async fn instantiate_with_code(&self, code: Bytes) -> Result<(CodeHash, ContractAccount)> { let api = self.subxt_api().await?; + let gas_limit = if let Some(gas_limit) = self.args.gas_limit { + gas_limit + } else { + let instantiate_result = self.instantiate_dry_run(Code::Upload(code.clone())).await?; + instantiate_result.gas_required + }; let tx_progress = api .tx() .contracts() .instantiate_with_code( self.args.value, - self.args.gas_limit, + gas_limit, self.args.storage_deposit_limit, code.to_vec(), self.args.data.clone(), @@ -251,12 +258,13 @@ impl<'a> Exec<'a> { async fn instantiate(&self, code_hash: CodeHash) -> Result { let api = self.subxt_api().await?; + let gas_limit = self.gas_limit(Code::Existing(code_hash)).await?; let tx_progress = api .tx() .contracts() .instantiate( self.args.value, - self.args.gas_limit, + gas_limit, self.args.storage_deposit_limit, code_hash, self.args.data.clone(), @@ -280,6 +288,7 @@ impl<'a> Exec<'a> { async fn instantiate_dry_run(&self, code: Code) -> Result { let url = self.url.to_string(); let cli = WsClientBuilder::default().build(&url).await?; + let gas_limit = self.args.gas_limit.as_ref().unwrap_or(&50000000000); let storage_deposit_limit = self .args .storage_deposit_limit @@ -288,7 +297,7 @@ impl<'a> Exec<'a> { let call_request = InstantiateRequest { origin: self.signer.account_id().clone(), value: NumberOrHex::Hex(self.args.value.into()), - gas_limit: NumberOrHex::Number(self.args.gas_limit), + gas_limit: NumberOrHex::Number(*gas_limit), storage_deposit_limit, code, data: self.args.data.clone().into(), @@ -299,6 +308,17 @@ impl<'a> Exec<'a> { cli.request("contracts_instantiate", params).await?; Ok(result) } + + /// Dry run the instantiation to calculate the gas required, unless the gas limit is explicitly + /// set by the user. + async fn gas_limit(&self, code: Code) -> Result { + if let Some(gas_limit) = self.args.gas_limit { + Ok(gas_limit) + } else { + let instantiate_result = self.instantiate_dry_run(code).await?; + Ok(instantiate_result.gas_required) + } + } } /// A struct that encodes RPC parameters required to instantiate a new smart contract. -- GitLab From 4348cc59bd747dca1df2d2641b90cc66183425fd Mon Sep 17 00:00:00 2001 From: ascjones Date: Tue, 12 Apr 2022 17:16:27 +0100 Subject: [PATCH 2/2] Fmt --- src/cmd/extrinsics/instantiate.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/extrinsics/instantiate.rs b/src/cmd/extrinsics/instantiate.rs index b7d6c039..6e829d33 100644 --- a/src/cmd/extrinsics/instantiate.rs +++ b/src/cmd/extrinsics/instantiate.rs @@ -263,7 +263,8 @@ impl<'a> Exec<'a> { let gas_limit = if let Some(gas_limit) = self.args.gas_limit { gas_limit } else { - let instantiate_result = self.instantiate_dry_run(Code::Upload(code.clone())).await?; + let instantiate_result = + self.instantiate_dry_run(Code::Upload(code.clone())).await?; instantiate_result.gas_required }; let tx_progress = api -- GitLab