// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of substrate-subxt. // // subxt is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // subxt is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with substrate-subxt. If not, see . //! Implements support for the pallet_contracts module. use crate::frame::{ balances::{ Balances, BalancesEventsDecoder, }, system::{ System, SystemEventsDecoder, }, }; use codec::{ Decode, Encode, }; 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(Clone, Debug, Eq, PartialEq, Call, Encode)] pub struct PutCodeCall<'a, T: Contracts> { /// Runtime marker. pub _runtime: PhantomData, /// Wasm blob. pub code: &'a [u8], } /// Creates a new contract from the `codehash` generated by `put_code`, /// optionally transferring some balance. /// /// Creation is executed as follows: /// /// - The destination address is computed based on the sender and hash of /// the code. /// - The smart-contract account is instantiated at the computed address. /// - The `ctor_code` is executed in the context of the newly-instantiated /// account. Buffer returned after the execution is saved as the `code`https://www.bbc.co.uk/ /// of the account. That code will be invoked upon any call received by /// this account. /// - The contract is initialized. #[derive(Clone, Debug, Eq, PartialEq, Call, Encode)] pub struct InstantiateCall<'a, T: Contracts> { /// Initial balance transfered to the contract. #[codec(compact)] pub endowment: ::Balance, /// Gas limit. #[codec(compact)] pub gas_limit: Gas, /// Code hash returned by the put_code call. pub code_hash: &'a ::Hash, /// Data to initialize the contract with. pub data: &'a [u8], } /// Makes a call to an account, optionally transferring some balance. /// /// * If the account is a smart-contract account, the associated code will /// be executed and any value will be transferred. /// * If the account is a regular account, any value will be transferred. /// * 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(Clone, Debug, PartialEq, Call, Encode)] pub struct CallCall<'a, T: Contracts> { /// Address of the contract. pub dest: &'a ::Address, /// Value to transfer to the contract. pub value: ::Balance, /// Gas limit. #[codec(compact)] pub gas_limit: Gas, /// Data to send to the contract. pub data: &'a [u8], } /// Code stored event. #[derive(Clone, Debug, Eq, PartialEq, Event, Decode)] pub struct CodeStoredEvent { /// Code hash of the contract. pub code_hash: T::Hash, } /// Instantiated event. #[derive(Clone, Debug, Eq, PartialEq, Event, Decode)] pub struct InstantiatedEvent { /// Caller that instantiated the contract. pub caller: ::AccountId, /// The address of the contract. pub contract: ::AccountId, } #[cfg(test)] mod tests { use super::*; 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 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(), }, }, }); }