- 
                Notifications
    
You must be signed in to change notification settings  - Fork 478
 
Add example which uses ext_transfer + ext_terminate #554
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
Changes from all commits
987cbe5
              9fdb2c9
              cdfba99
              d2878b1
              0295a97
              09b7211
              bfbc9ee
              a16c8b1
              fea6a03
              e641b8f
              d15bd4d
              9778815
              a4e81e2
              ed21715
              efa6e90
              1778b48
              96b1f91
              688faab
              d228696
              6c0cc5f
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -363,3 +363,56 @@ where | |
| Ok(callee) | ||
| }) | ||
| } | ||
| 
     | 
||
| /// The result of a successful contract termination. | ||
| #[derive(scale::Encode, scale::Decode)] | ||
| pub struct ContractTerminationResult<E> | ||
| where | ||
| E: Environment, | ||
| { | ||
| /// The beneficiary account who received the remaining value in the contract. | ||
| pub beneficiary: <E as Environment>::AccountId, | ||
| /// The value which was transferred to the `beneficiary`. | ||
| pub transferred: <E as Environment>::Balance, | ||
| } | ||
| 
     | 
||
| #[cfg(feature = "std")] | ||
| use std::panic::UnwindSafe; | ||
| 
     | 
||
| /// Tests if a contract terminates successfully after `self.env().terminate()` | ||
| /// has been called. | ||
| /// | ||
| /// # Usage | ||
| /// | ||
| /// ```no_compile | ||
| /// let should_terminate = move || your_contract.fn_which_should_terminate(); | ||
| /// ink_env::test::assert_contract_termination::<ink_env::DefaultEnvironment, _>( | ||
| /// should_terminate, | ||
| /// expected_beneficiary, | ||
| /// expected_value_transferred_to_beneficiary | ||
| /// ); | ||
| /// ``` | ||
| /// | ||
| /// See `examples/contract-terminate` for a complete usage example. | ||
| #[cfg(feature = "std")] | ||
| pub fn assert_contract_termination<T, F>( | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So much better as a function compared to a macro!  | 
||
| should_terminate: F, | ||
| expected_beneficiary: T::AccountId, | ||
| expected_balance: T::Balance, | ||
| ) where | ||
| T: Environment, | ||
| F: FnMut() + UnwindSafe, | ||
| <T as Environment>::AccountId: core::fmt::Debug, | ||
| <T as Environment>::Balance: core::fmt::Debug, | ||
| { | ||
| let value_any = ::std::panic::catch_unwind(should_terminate) | ||
| .expect_err("contract did not terminate"); | ||
| let encoded_input: &Vec<u8> = value_any | ||
| .downcast_ref::<Vec<u8>>() | ||
| .expect("panic object can not be cast"); | ||
| let res: ContractTerminationResult<T> = | ||
| scale::Decode::decode(&mut &encoded_input[..]).expect("input can not be decoded"); | ||
| 
     | 
||
| assert_eq!(res.beneficiary, expected_beneficiary); | ||
| assert_eq!(res.transferred, expected_balance); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # Ignore build artifacts from the local tests sub-crate. | ||
| /target/ | ||
| 
     | 
||
| # Ignore backup files creates by cargo fmt. | ||
| **/*.rs.bk | ||
| 
     | 
||
| # Remove Cargo.lock when creating an executable, leave it for libraries | ||
| # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock | ||
| Cargo.lock | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| [package] | ||
| name = "contract_terminate" | ||
| version = "3.0.0-rc1" | ||
| authors = ["Parity Technologies <admin@parity.io>"] | ||
| edition = "2018" | ||
| 
     | 
||
| [dependencies] | ||
| ink_primitives = { version = "3.0.0-rc1", path = "../../crates/primitives", default-features = false } | ||
| ink_metadata = { version = "3.0.0-rc1", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } | ||
| ink_env = { version = "3.0.0-rc1", path = "../../crates/env", default-features = false } | ||
| ink_storage = { version = "3.0.0-rc1", path = "../../crates/storage", default-features = false } | ||
| ink_lang = { version = "3.0.0-rc1", path = "../../crates/lang", default-features = false } | ||
| 
     | 
||
| scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] } | ||
| scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true } | ||
| 
     | 
||
| 
     | 
||
| [lib] | ||
| name = "contract_terminate" | ||
| path = "lib.rs" | ||
| crate-type = ["cdylib"] | ||
| 
     | 
||
| [features] | ||
| default = ["std"] | ||
| std = [ | ||
| "ink_primitives/std", | ||
| "ink_metadata", | ||
| "ink_metadata/std", | ||
| "ink_env/std", | ||
| "ink_storage/std", | ||
| "ink_lang/std", | ||
| "scale/std", | ||
| "scale-info", | ||
| "scale-info/std", | ||
| ] | ||
| ink-as-dependency = [] | 
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,101 @@ | ||||||||||||||
| // Copyright 2018-2020 Parity Technologies (UK) Ltd. | ||||||||||||||
| // | ||||||||||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||||||||||
| // you may not use this file except in compliance with the License. | ||||||||||||||
| // You may obtain a copy of the License at | ||||||||||||||
| // | ||||||||||||||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||||||||||||||
| // | ||||||||||||||
| // Unless required by applicable law or agreed to in writing, software | ||||||||||||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||||||||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||||||||||
| // See the License for the specific language governing permissions and | ||||||||||||||
| // limitations under the License. | ||||||||||||||
| 
     | 
||||||||||||||
| //! A smart contract which demonstrates behavior of the `self.env().terminate()` | ||||||||||||||
| //! function. It terminates itself once `terminate_me()` is called. | ||||||||||||||
| 
     | 
||||||||||||||
| #![cfg_attr(not(feature = "std"), no_std)] | ||||||||||||||
| #![allow(clippy::new_without_default)] | ||||||||||||||
| 
     | 
||||||||||||||
| use ink_lang as ink; | ||||||||||||||
| 
     | 
||||||||||||||
| #[ink::contract] | ||||||||||||||
| pub mod just_terminates { | ||||||||||||||
| /// No storage is needed for this simple contract. | ||||||||||||||
| #[ink(storage)] | ||||||||||||||
| pub struct JustTerminate {} | ||||||||||||||
| 
     | 
||||||||||||||
| impl JustTerminate { | ||||||||||||||
| /// Creates a new instance of this contract. | ||||||||||||||
| #[ink(constructor)] | ||||||||||||||
| pub fn new() -> Self { | ||||||||||||||
| Self {} | ||||||||||||||
| } | ||||||||||||||
| 
     | 
||||||||||||||
| /// Terminates with the caller as beneficiary. | ||||||||||||||
| #[ink(message)] | ||||||||||||||
| pub fn terminate_me(&mut self) { | ||||||||||||||
| self.env().terminate_contract(self.env().caller()); | ||||||||||||||
| } | ||||||||||||||
| 
         
      Comment on lines
    
      +38
     to 
      +40
    
   
  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The correct version of this would be: 
        Suggested change
       
    
 We then run into this though: Wdyt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for the explanation!  | 
||||||||||||||
| } | ||||||||||||||
| 
     | 
||||||||||||||
| #[cfg(test)] | ||||||||||||||
| mod tests { | ||||||||||||||
| use super::*; | ||||||||||||||
| 
     | 
||||||||||||||
| use ink_env::{ | ||||||||||||||
| call, | ||||||||||||||
| test, | ||||||||||||||
| }; | ||||||||||||||
| use ink_lang as ink; | ||||||||||||||
| 
     | 
||||||||||||||
| #[ink::test] | ||||||||||||||
| fn terminating_works() { | ||||||||||||||
| // given | ||||||||||||||
| let accounts = default_accounts(); | ||||||||||||||
| let contract_id = ink_env::test::get_current_contract_account_id::< | ||||||||||||||
| ink_env::DefaultEnvironment, | ||||||||||||||
| >() | ||||||||||||||
| .expect("Cannot get contract id"); | ||||||||||||||
| set_sender(accounts.alice); | ||||||||||||||
| set_balance(contract_id, 100); | ||||||||||||||
| let mut contract = JustTerminate::new(); | ||||||||||||||
| 
     | 
||||||||||||||
| // when | ||||||||||||||
| let should_terminate = move || contract.terminate_me(); | ||||||||||||||
| 
     | 
||||||||||||||
| // then | ||||||||||||||
| ink_env::test::assert_contract_termination::<ink_env::DefaultEnvironment, _>( | ||||||||||||||
| should_terminate, | ||||||||||||||
| accounts.alice, | ||||||||||||||
| 100, | ||||||||||||||
| ); | ||||||||||||||
| } | ||||||||||||||
| 
     | 
||||||||||||||
| fn default_accounts( | ||||||||||||||
| ) -> ink_env::test::DefaultAccounts<ink_env::DefaultEnvironment> { | ||||||||||||||
| ink_env::test::default_accounts::<ink_env::DefaultEnvironment>() | ||||||||||||||
| .expect("Off-chain environment should have been initialized already") | ||||||||||||||
| } | ||||||||||||||
| 
     | 
||||||||||||||
| fn set_sender(sender: AccountId) { | ||||||||||||||
| let callee = ink_env::account_id::<ink_env::DefaultEnvironment>() | ||||||||||||||
| .unwrap_or([0x0; 32].into()); | ||||||||||||||
| test::push_execution_context::<Environment>( | ||||||||||||||
| sender, | ||||||||||||||
| callee, | ||||||||||||||
| 1000000, | ||||||||||||||
| 1000000, | ||||||||||||||
| test::CallData::new(call::Selector::new([0x00; 4])), // dummy | ||||||||||||||
| ); | ||||||||||||||
| } | ||||||||||||||
| 
     | 
||||||||||||||
| fn set_balance(account_id: AccountId, balance: Balance) { | ||||||||||||||
| ink_env::test::set_account_balance::<ink_env::DefaultEnvironment>( | ||||||||||||||
| account_id, balance, | ||||||||||||||
| ) | ||||||||||||||
| .expect("Cannot set account balance"); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # Ignore build artifacts from the local tests sub-crate. | ||
| /target/ | ||
| 
     | 
||
| # Ignore backup files creates by cargo fmt. | ||
| **/*.rs.bk | ||
| 
     | 
||
| # Remove Cargo.lock when creating an executable, leave it for libraries | ||
| # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock | ||
| Cargo.lock | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What the on-chain impl would do here is set a tombstone with a code hash and remove storage. AFAIU both is not easily achievable with our current off-chain env, hence I left it out here for the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you maybe provide a small dev. note comment explaining exactly this?