Skip to content

Commit 011aac6

Browse files
Dry running contract interactions (#106)
1 parent b4c49c3 commit 011aac6

File tree

16 files changed

+6258
-78
lines changed

16 files changed

+6258
-78
lines changed

CHANGELOG.md

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
## [0.12.0]
10+
## [0.12.1]
1111

12-
### Pull requests
12+
### Added
1313

14-
- https://github.com/inkdevhub/drink/pull/110
14+
- Support dry running contract interactions
15+
16+
## [0.12.0]
1517

1618
### Changed
1719

@@ -20,20 +22,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2022

2123
## [0.11.1]
2224

23-
### Pull requests
24-
25-
- https://github.com/inkdevhub/drink/pull/104
26-
2725
### Added
2826

2927
- Respect features for the contract dependencies when building contracts via drink macros
3028

3129
## [0.11.0]
3230

33-
### Pull requests
34-
35-
- https://github.com/inkdevhub/drink/pull/109
36-
3731
### Changed
3832

3933
- Support `[email protected]`
@@ -43,11 +37,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4337

4438
## [0.10.0]
4539

46-
### Pull requests
47-
48-
- https://github.com/inkdevhub/drink/pull/100
49-
- https://github.com/inkdevhub/drink/pull/101
50-
5140
### Changed
5241

5342
- Update toolchain to `1.74.0`
@@ -56,20 +45,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5645

5746
## [0.9.0]
5847

59-
### Pull requests
60-
61-
- https://github.com/inkdevhub/drink/pull/99
62-
6348
### Changed
6449

6550
- Rework `Sandbox` API to ease working with custom runtimes
6651

6752
## [0.8.7]
6853

69-
### Pull requests
70-
71-
- https://github.com/inkdevhub/drink/pull/112
72-
7354
### Changed
7455

7556
- Migrate examples back to `[email protected]`
@@ -82,33 +63,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8263

8364
## [0.8.6] [YANKED]
8465

85-
### Pull requests
86-
87-
- https://github.com/inkdevhub/drink/pull/92
88-
- https://github.com/inkdevhub/drink/pull/94
89-
9066
### Added
9167

9268
- Accessing events emitted by contracts
9369
- `#[drink::test]` creates and adds a `session: Session` argument to the test function
9470

9571
## [0.8.5] [YANKED]
9672

97-
### Pull requests
98-
99-
- https://github.com/inkdevhub/drink/pull/91
100-
10173
### Changed
10274

10375
- Update `contract-*` crates from `3.x.x` to `4.0.0-rc.1`
10476
- Migrate examples from `[email protected]` to `[email protected]`
10577

10678
## [0.8.4]
10779

108-
### Pull requests
109-
110-
- https://github.com/inkdevhub/drink/pull/90
111-
11280
### Added
11381

11482
- `NO_SALT`, `NO_ENDOWMENT` contstants added

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ homepage = "https://github.com/Cardinal-Cryptography/drink"
1818
license = "Apache-2.0"
1919
readme = "README.md"
2020
repository = "https://github.com/Cardinal-Cryptography/drink"
21-
version = "0.12.0"
21+
version = "0.12.1"
2222

2323
[workspace.dependencies]
2424
anyhow = { version = "1.0.71" }
@@ -57,5 +57,5 @@ sp-runtime-interface = { version = "24.0.0" }
5757

5858
# Local dependencies
5959

60-
drink = { version = "=0.12.0", path = "drink" }
61-
drink-test-macro = { version = "=0.12.0", path = "drink/test-macro" }
60+
drink = { version = "=0.12.1", path = "drink" }
61+
drink-test-macro = { version = "=0.12.1", path = "drink/test-macro" }

drink/src/lib.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,44 @@ pub mod session;
1313
#[cfg(feature = "macros")]
1414
pub use drink_test_macro::{contract_bundle_provider, test};
1515
pub use errors::Error;
16+
use frame_support::traits::fungible::Inspect;
1617
pub use frame_support::{
1718
sp_runtime::{AccountId32, DispatchError},
1819
weights::Weight,
1920
};
2021
use frame_system::EventRecord;
22+
use pallet_contracts::{ContractExecResult, ContractInstantiateResult};
2123
#[cfg(feature = "session")]
2224
pub use session::mock::{mock_message, ContractMock, MessageMock, MockedCallResult, Selector};
2325
/// Export pallets that are used in the minimal runtime.
2426
pub use {frame_support, frame_system, pallet_balances, pallet_contracts, pallet_timestamp};
2527

2628
pub use crate::runtime::minimal::{self, MinimalRuntime};
29+
use crate::runtime::AccountIdFor;
2730

2831
/// Alias for `frame-system`'s `RuntimeCall` type.
29-
pub type RuntimeCall<R> = <R as frame_system::Config>::RuntimeCall;
32+
pub type RuntimeCall<Runtime> = <Runtime as frame_system::Config>::RuntimeCall;
3033

3134
/// Alias for `pallet-balances`'s Balance type.
32-
pub type BalanceOf<R> = <R as pallet_balances::Config>::Balance;
35+
pub type BalanceOf<Runtime> =
36+
<<Runtime as pallet_contracts::Config>::Currency as Inspect<AccountIdFor<Runtime>>>::Balance;
3337

3438
/// Main result type for the drink crate.
3539
pub type DrinkResult<T> = std::result::Result<T, Error>;
3640

3741
/// Copied from pallet-contracts.
38-
pub type EventRecordOf<T> =
39-
EventRecord<<T as frame_system::Config>::RuntimeEvent, <T as frame_system::Config>::Hash>;
42+
pub type EventRecordOf<Runtime> = EventRecord<
43+
<Runtime as frame_system::Config>::RuntimeEvent,
44+
<Runtime as frame_system::Config>::Hash,
45+
>;
46+
47+
/// Copied from pallet-contracts.
48+
pub type ContractInstantiateResultFor<Runtime> =
49+
ContractInstantiateResult<AccountIdFor<Runtime>, BalanceOf<Runtime>, EventRecordOf<Runtime>>;
50+
51+
/// Copied from pallet-contracts.
52+
pub type ContractExecResultFor<Runtime> =
53+
ContractExecResult<BalanceOf<Runtime>, EventRecordOf<Runtime>>;
4054

4155
/// Default gas limit.
4256
pub const DEFAULT_GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);

drink/src/sandbox/balance_api.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
use frame_support::{sp_runtime::DispatchError, traits::fungible::Mutate};
33

44
use super::Sandbox;
5-
use crate::{runtime::AccountIdFor, BalanceOf, SandboxConfig};
5+
use crate::{runtime::AccountIdFor, SandboxConfig};
6+
7+
type BalanceOf<R> = <R as pallet_balances::Config>::Balance;
68

79
impl<Config: SandboxConfig> Sandbox<Config>
810
where

drink/src/sandbox/contracts_api.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
//! Contracts API for the sandbox.
22
use std::ops::Not;
33

4-
use frame_support::{traits::fungible::Inspect, weights::Weight};
4+
use frame_support::weights::Weight;
55
use frame_system::Config as SysConfig;
66
use pallet_contracts::{
7-
Code, CodeUploadResult, CollectEvents, ContractExecResult, ContractInstantiateResult,
8-
DebugInfo, Determinism,
7+
Code, CodeUploadResult, CollectEvents, ContractInstantiateResult, DebugInfo, Determinism,
98
};
109
use parity_scale_codec::Decode as _;
1110

12-
use crate::{runtime::AccountIdFor, EventRecordOf, Sandbox};
13-
14-
type BalanceOf<R> =
15-
<<R as pallet_contracts::Config>::Currency as Inspect<AccountIdFor<R>>>::Balance;
11+
use crate::{
12+
runtime::AccountIdFor, BalanceOf, ContractExecResultFor, ContractInstantiateResultFor,
13+
EventRecordOf, Sandbox,
14+
};
1615

1716
impl<Config: crate::SandboxConfig> Sandbox<Config>
1817
where
@@ -39,11 +38,7 @@ where
3938
origin: AccountIdFor<Config::Runtime>,
4039
gas_limit: Weight,
4140
storage_deposit_limit: Option<BalanceOf<Config::Runtime>>,
42-
) -> ContractInstantiateResult<
43-
AccountIdFor<Config::Runtime>,
44-
BalanceOf<Config::Runtime>,
45-
EventRecordOf<Config::Runtime>,
46-
> {
41+
) -> ContractInstantiateResultFor<Config::Runtime> {
4742
self.externalities.execute_with(|| {
4843
pallet_contracts::Pallet::<Config::Runtime>::bare_instantiate(
4944
origin,
@@ -149,7 +144,7 @@ where
149144
gas_limit: Weight,
150145
storage_deposit_limit: Option<BalanceOf<Config::Runtime>>,
151146
determinism: Determinism,
152-
) -> ContractExecResult<BalanceOf<Config::Runtime>, EventRecordOf<Config::Runtime>> {
147+
) -> ContractExecResultFor<Config::Runtime> {
153148
self.externalities.execute_with(|| {
154149
pallet_contracts::Pallet::<Config::Runtime>::bare_call(
155150
origin,

drink/src/session.rs

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,21 @@ use std::{
99

1010
pub use contract_transcode;
1111
use contract_transcode::ContractMessageTranscoder;
12+
use error::SessionError;
1213
use frame_support::{traits::fungible::Inspect, weights::Weight};
1314
use pallet_contracts::Determinism;
1415
use parity_scale_codec::Decode;
1516
pub use record::{EventBatch, Record};
1617

18+
use self::mocking_api::MockingApi;
1719
use crate::{
1820
runtime::{
1921
pallet_contracts_debugging::{InterceptingExt, TracingExt},
20-
AccountIdFor, HashFor,
22+
AccountIdFor, HashFor, MinimalRuntime,
2123
},
2224
sandbox::SandboxConfig,
2325
session::mock::MockRegistry,
24-
Sandbox, DEFAULT_GAS_LIMIT,
26+
ContractExecResultFor, ContractInstantiateResultFor, Sandbox, DEFAULT_GAS_LIMIT,
2527
};
2628

2729
pub mod mock;
@@ -33,12 +35,8 @@ mod record;
3335
mod transcoding;
3436

3537
pub use bundle::ContractBundle;
36-
use error::SessionError;
3738

38-
use self::mocking_api::MockingApi;
39-
use crate::{
40-
errors::MessageResult, runtime::MinimalRuntime, session::transcoding::TranscoderRegistry,
41-
};
39+
use crate::{errors::MessageResult, session::transcoding::TranscoderRegistry};
4240

4341
type BalanceOf<R> =
4442
<<R as pallet_contracts::Config>::Currency as Inspect<AccountIdFor<R>>>::Balance;
@@ -272,6 +270,7 @@ where
272270
)
273271
.map(|_| self)
274272
}
273+
275274
fn record_events<T>(&mut self, recording: impl FnOnce(&mut Self) -> T) -> T {
276275
let start = self.sandbox.events().len();
277276
let result = recording(self);
@@ -346,6 +345,33 @@ where
346345
)
347346
}
348347

348+
/// Performs a dry run of the deployment of a contract.
349+
pub fn dry_run_deployment<S: AsRef<str> + Debug>(
350+
&mut self,
351+
contract_file: ContractBundle,
352+
constructor: &str,
353+
args: &[S],
354+
salt: Vec<u8>,
355+
endowment: Option<BalanceOf<Config::Runtime>>,
356+
) -> Result<ContractInstantiateResultFor<Config::Runtime>, SessionError> {
357+
let data = contract_file
358+
.transcoder
359+
.encode(constructor, args)
360+
.map_err(|err| SessionError::Encoding(err.to_string()))?;
361+
362+
Ok(self.sandbox.dry_run(|sandbox| {
363+
sandbox.deploy_contract(
364+
contract_file.wasm,
365+
endowment.unwrap_or_default(),
366+
data,
367+
salt,
368+
self.actor.clone(),
369+
self.gas_limit,
370+
None,
371+
)
372+
}))
373+
}
374+
349375
/// Similar to `deploy_and` but takes the parsed contract file (`ContractBundle`) as a first argument.
350376
///
351377
/// You can get it with `ContractBundle::load("some/path/your.contract")` or `local_contract_file!()`
@@ -449,6 +475,35 @@ where
449475
self.call_internal(Some(address), message, args, endowment)
450476
}
451477

478+
/// Performs a dry run of a contract call.
479+
pub fn dry_run_call<S: AsRef<str> + Debug>(
480+
&mut self,
481+
address: AccountIdFor<Config::Runtime>,
482+
message: &str,
483+
args: &[S],
484+
endowment: Option<BalanceOf<Config::Runtime>>,
485+
) -> Result<ContractExecResultFor<Config::Runtime>, SessionError> {
486+
let data = self
487+
.transcoders
488+
.get(&address)
489+
.as_ref()
490+
.ok_or(SessionError::NoTranscoder)?
491+
.encode(message, args)
492+
.map_err(|err| SessionError::Encoding(err.to_string()))?;
493+
494+
Ok(self.sandbox.dry_run(|sandbox| {
495+
sandbox.call_contract(
496+
address,
497+
endowment.unwrap_or_default(),
498+
data,
499+
self.actor.clone(),
500+
self.gas_limit,
501+
None,
502+
self.determinism,
503+
)
504+
}))
505+
}
506+
452507
fn call_internal<S: AsRef<str> + Debug, T: Decode>(
453508
&mut self,
454509
address: Option<AccountIdFor<Config::Runtime>>,

examples/chain-extension/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)