mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 18:21:02 +00:00
Split subxt (#102)
* Proc macro improvements. * Use proc-macros. * Update examples. * Fix build. * Run rustfmt. * Fix total issuance test. * Remove gas limit from put code call. * Handle runtime errors. * Fix tests. * Make test more reliable. * Revert "Handle runtime errors." This reverts commit 26f30a9f4cfcfddfb3e49308cded46cfe6468697. * Use expect instead of unwrap. * Parse marker type. * Fetch doesn't fail.
This commit is contained in:
+55
-131
@@ -17,39 +17,40 @@
|
||||
//! Implements support for the pallet_contracts module.
|
||||
|
||||
use crate::frame::{
|
||||
balances::Balances,
|
||||
system::System,
|
||||
Call,
|
||||
Event,
|
||||
balances::{
|
||||
Balances,
|
||||
BalancesEventsDecoder,
|
||||
},
|
||||
system::{
|
||||
System,
|
||||
SystemEventsDecoder,
|
||||
},
|
||||
};
|
||||
use codec::{
|
||||
Decode,
|
||||
Encode,
|
||||
};
|
||||
|
||||
const MODULE: &str = "Contracts";
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Gas units are chosen to be represented by u64 so that gas metering
|
||||
/// instructions can operate on them efficiently.
|
||||
pub type Gas = u64;
|
||||
|
||||
/// The subset of the `pallet_contracts::Trait` that a client must implement.
|
||||
#[module]
|
||||
pub trait Contracts: System + Balances {}
|
||||
|
||||
/// Stores the given binary Wasm code into the chain's storage and returns
|
||||
/// its `codehash`.
|
||||
/// You can instantiate contracts only with stored code.
|
||||
#[derive(Debug, Encode)]
|
||||
pub struct PutCodeCall<'a> {
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Call, Encode)]
|
||||
pub struct PutCodeCall<'a, T: Contracts> {
|
||||
/// Runtime marker.
|
||||
pub _runtime: PhantomData<T>,
|
||||
/// Wasm blob.
|
||||
pub code: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a, T: Contracts> Call<T> for PutCodeCall<'a> {
|
||||
const MODULE: &'static str = MODULE;
|
||||
const FUNCTION: &'static str = "put_code";
|
||||
}
|
||||
|
||||
/// Creates a new contract from the `codehash` generated by `put_code`,
|
||||
/// optionally transferring some balance.
|
||||
///
|
||||
@@ -63,7 +64,7 @@ impl<'a, T: Contracts> Call<T> for PutCodeCall<'a> {
|
||||
/// of the account. That code will be invoked upon any call received by
|
||||
/// this account.
|
||||
/// - The contract is initialized.
|
||||
#[derive(Debug, Encode)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Call, Encode)]
|
||||
pub struct InstantiateCall<'a, T: Contracts> {
|
||||
/// Initial balance transfered to the contract.
|
||||
#[codec(compact)]
|
||||
@@ -77,11 +78,6 @@ pub struct InstantiateCall<'a, T: Contracts> {
|
||||
pub data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a, T: Contracts> Call<T> for InstantiateCall<'a, T> {
|
||||
const MODULE: &'static str = MODULE;
|
||||
const FUNCTION: &'static str = "instantiate";
|
||||
}
|
||||
|
||||
/// Makes a call to an account, optionally transferring some balance.
|
||||
///
|
||||
/// * If the account is a smart-contract account, the associated code will
|
||||
@@ -90,7 +86,7 @@ impl<'a, T: Contracts> Call<T> for InstantiateCall<'a, T> {
|
||||
/// * If no account exists and the call value is not less than
|
||||
/// `existential_deposit`, a regular account will be created and any value
|
||||
/// will be transferred.
|
||||
#[derive(Debug, Encode)]
|
||||
#[derive(Clone, Debug, PartialEq, Call, Encode)]
|
||||
pub struct CallCall<'a, T: Contracts> {
|
||||
/// Address of the contract.
|
||||
pub dest: &'a <T as System>::Address,
|
||||
@@ -103,133 +99,61 @@ pub struct CallCall<'a, T: Contracts> {
|
||||
pub data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a, T: Contracts> Call<T> for CallCall<'a, T> {
|
||||
const MODULE: &'static str = MODULE;
|
||||
const FUNCTION: &'static str = "call";
|
||||
}
|
||||
|
||||
/// Code stored event.
|
||||
#[derive(Debug, Decode)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Event, Decode)]
|
||||
pub struct CodeStoredEvent<T: Contracts> {
|
||||
/// Code hash of the contract.
|
||||
pub code_hash: T::Hash,
|
||||
}
|
||||
|
||||
impl<T: Contracts> Event<T> for CodeStoredEvent<T> {
|
||||
const MODULE: &'static str = MODULE;
|
||||
const EVENT: &'static str = "CodeStored";
|
||||
}
|
||||
|
||||
/// Instantiated event.
|
||||
#[derive(Debug, Decode)]
|
||||
pub struct InstantiatedEvent<T: Contracts>(
|
||||
pub <T as System>::AccountId,
|
||||
pub <T as System>::AccountId,
|
||||
);
|
||||
|
||||
impl<T: Contracts> Event<T> for InstantiatedEvent<T> {
|
||||
const MODULE: &'static str = MODULE;
|
||||
const EVENT: &'static str = "Instantiated";
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Event, Decode)]
|
||||
pub struct InstantiatedEvent<T: Contracts> {
|
||||
/// Caller that instantiated the contract.
|
||||
pub caller: <T as System>::AccountId,
|
||||
/// The address of the contract.
|
||||
pub contract: <T as System>::AccountId,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use codec::Codec;
|
||||
use sp_core::Pair;
|
||||
use sp_keyring::AccountKeyring;
|
||||
use sp_runtime::traits::{
|
||||
IdentifyAccount,
|
||||
Verify,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
tests::test_client,
|
||||
Client,
|
||||
Error,
|
||||
};
|
||||
|
||||
async fn put_code<T, P, S>(client: &Client<T, S>, signer: P) -> Result<T::Hash, Error>
|
||||
where
|
||||
T: Contracts + Send + Sync,
|
||||
T::Address: From<T::AccountId>,
|
||||
P: Pair,
|
||||
P::Signature: Codec,
|
||||
S: Verify + Codec + From<P::Signature> + 'static,
|
||||
S::Signer: From<P::Public> + IdentifyAccount<AccountId = T::AccountId>,
|
||||
{
|
||||
const CONTRACT: &str = r#"
|
||||
subxt_test!({
|
||||
name: test_put_code_and_instantiate,
|
||||
prelude: {
|
||||
const CONTRACT: &str = r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
let wasm = wabt::wat2wasm(CONTRACT).expect("invalid wabt");
|
||||
|
||||
let xt = client.xt(signer, None).await?;
|
||||
|
||||
let result = xt.watch().submit(PutCodeCall { code: &wasm }).await?;
|
||||
let code_hash = result
|
||||
.find_event::<CodeStoredEvent<T>>()?
|
||||
.ok_or(Error::Other("Failed to find CodeStored event".into()))?
|
||||
.code_hash;
|
||||
|
||||
Ok(code_hash)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // requires locally running substrate node
|
||||
fn tx_put_code() {
|
||||
env_logger::try_init().ok();
|
||||
let code_hash_result: Result<_, Error> = async_std::task::block_on(async move {
|
||||
let signer = AccountKeyring::Alice.pair();
|
||||
let client = test_client().await;
|
||||
let code_hash = put_code(&client, signer).await?;
|
||||
Ok(code_hash)
|
||||
});
|
||||
|
||||
assert!(
|
||||
code_hash_result.is_ok(),
|
||||
format!(
|
||||
"Error calling put_code and receiving CodeStored Event: {:?}",
|
||||
code_hash_result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // requires locally running substrate node
|
||||
fn tx_instantiate() {
|
||||
env_logger::try_init().ok();
|
||||
let result: Result<_, Error> = async_std::task::block_on(async move {
|
||||
let signer = AccountKeyring::Bob.pair();
|
||||
let client = test_client().await;
|
||||
|
||||
let code_hash = put_code(&client, signer.clone()).await?;
|
||||
|
||||
log::info!("Code hash: {:?}", code_hash);
|
||||
|
||||
let xt = client.xt(signer, None).await?;
|
||||
let result = xt
|
||||
.watch()
|
||||
.submit(InstantiateCall {
|
||||
endowment: 100_000_000_000_000,
|
||||
gas_limit: 500_000_000,
|
||||
code_hash: &code_hash,
|
||||
data: &[],
|
||||
})
|
||||
.await?;
|
||||
let event = result
|
||||
.find_event::<InstantiatedEvent<_>>()?
|
||||
.ok_or(Error::Other("Failed to find Instantiated event".into()))?;
|
||||
Ok(event)
|
||||
});
|
||||
|
||||
log::info!("Instantiate result: {:?}", result);
|
||||
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
format!("Error instantiating contract: {:?}", result)
|
||||
);
|
||||
}
|
||||
let wasm = wabt::wat2wasm(CONTRACT).expect("invalid wabt");
|
||||
let code_hash;
|
||||
},
|
||||
step: {
|
||||
call: PutCodeCall {
|
||||
_runtime: PhantomData,
|
||||
code: &wasm,
|
||||
},
|
||||
event: CodeStoredEvent {
|
||||
code_hash: {
|
||||
code_hash = event.code_hash.clone();
|
||||
event.code_hash.clone()
|
||||
},
|
||||
},
|
||||
},
|
||||
step: {
|
||||
call: InstantiateCall {
|
||||
endowment: 100_000_000_000_000,
|
||||
gas_limit: 500_000_000,
|
||||
code_hash: &code_hash,
|
||||
data: &[],
|
||||
},
|
||||
event: InstantiatedEvent {
|
||||
caller: alice.clone(),
|
||||
contract: event.contract.clone(),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user