Skip to content
This repository was archived by the owner on Dec 8, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ parent-vars:

.build-ink-example-contracts: &build-ink-example-contracts
- set -o pipefail
# Copy the local `ink-waterfall` example contracts into `INK_EXAMPLES_PATH`
# so that they are build and can be tested as well. They'll also show up
# in the regression bot statistics then.
- find ./examples/ -name 'Cargo.toml' -exec sed -i "s|../ink|../../|g" {} \;
- cp -r ./examples/* ${INK_EXAMPLES_PATH}
# delete old list items if the key has existed previously
- redis-cli -u $GITLAB_REDIS_URI del $REDIS_SIZES_KEY
- echo "Data will be written to $REDIS_SIZES_KEY"
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ requirement. By default the published versions of those projects are used
## Run it locally

```bash
# Create a link to ink! in the local examples of the `ink-waterfall`.
ln -s /path/to/ink/ ./examples/ink
Comment on lines +55 to +56
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use a released version of ink? The CI will replace it with current master anyways.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI will replace it with current master anyways.

Huh, how so?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line:
find ./examples/ -name 'Cargo.toml' -exec sed -i "s|../ink|../$INK_EXAMPLES_PATH|g" {} \;

But I see why now. We want to run it against a custom version locally, too.


export INK_EXAMPLES_PATH=/path/to/ink/examples/
substrate-contracts-node --tmp --dev > /tmp/substrate-contracts-node.log 2>&1 &

Expand Down Expand Up @@ -100,8 +103,8 @@ supply `--features polkadot-js-ui` to `cargo test`.

* `INK_EXAMPLES_PATH` ‒ Path to the ink! examples folder. Must be set.
* `UI_URL` ‒ URL of the UI to use. Defaults to the live interface for the chosen UI.
* `WATERFALL_CLOSE_BROWSER` ‒ Do not close browser window at the end of a test run.
Defaults to `true`. Set it to `false` to prevent closing .
* `WATERFALL_CLOSE_BROWSER` ‒ Close browser window at the end of a test run.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lil typo fix here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! No biggie, but going forward please avoid pushing to someone else's PR without talking to them first.

Defaults to `true`. Set it to `false` to prevent closing.
* `WATERFALL_SKIP_CONTRACT_BUILD` ‒ Do not build the contracts, re-use existing artifacts
from their `target` folder. Defaults to `false`. Set it to `true` to skip building.
* `NODE_PORT` ‒ Port under which the `substrate-contracts-node` is running. Defaults to `9944`.
Expand All @@ -117,4 +120,4 @@ before the test is finished processing them.

The test will then fail with a `NoSucheElement` error, indicating that
the DOM element is no longer available. The easiest fix for this is to
limit the number of concurrent test threads via e.g. `cargo test --jobs 4`.
limit the number of concurrent test threads via e.g. `cargo test --jobs 4`.
9 changes: 9 additions & 0 deletions examples/contract-introspection/.gitignore
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it asks a newline ^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's a GitHub thing, we can safely ignore it.

35 changes: 35 additions & 0 deletions examples/contract-introspection/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "contract_introspection"
version = "3.0.0-rc9"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"

[dependencies]
ink_primitives = { path = "../ink/crates/primitives", default-features = false }
ink_metadata = { path = "../ink/crates/metadata", default-features = false, features = ["derive"], optional = true }
ink_env = { path = "../ink/crates/env", default-features = false }
ink_storage = { path = "../ink/crates/storage", default-features = false }
ink_lang = { path = "../ink/crates/lang", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }

[lib]
name = "contract_introspection"
path = "lib.rs"
crate-type = ["cdylib"]

[features]
default = ["std"]
std = [
"ink_primitives/std",
"ink_metadata/std",
"ink_env/std",
"ink_storage/std",
"ink_lang/std",
"scale/std",
"scale-info/std",
]
ink-as-dependency = []

[workspace]
65 changes: 65 additions & 0 deletions examples/contract-introspection/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

#[ink::contract]
mod contract_introspection {
use ink_env::{
call::{
build_call,
utils::ReturnType,
ExecutionInput,
Selector,
},
CallFlags,
DefaultEnvironment,
};

#[ink(storage)]
pub struct ContractInspection {}

impl ContractInspection {
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}

/// Returns `true` if the caller is a contract.
#[ink(message, selector = 1)]
pub fn is_caller_contract(&self) -> bool {
self.env().is_contract(&self.env().caller())
}

/// Returns `true` if the caller is the origin of this call.
#[ink(message, selector = 2)]
pub fn is_caller_origin(&self) -> bool {
self.env().caller_is_origin()
}

/// Calls into this contract to the [`is_caller_contract`] function
/// and returns the return value of that function.
#[ink(message)]
pub fn calls_is_caller_contract(&self) -> bool {
build_call::<DefaultEnvironment>()
.callee(self.env().account_id())
.exec_input(ExecutionInput::new(Selector::new([0x00, 0x00, 0x00, 0x01])))
.returns::<ReturnType<bool>>()
.call_flags(CallFlags::default().set_allow_reentry(true))
.fire()
.expect("failed executing call")
}

/// Calls into this contract to the [`is_caller_origin`] function
/// and returns the return value of that function.
#[ink(message)]
pub fn calls_is_caller_origin(&self) -> bool {
build_call::<DefaultEnvironment>()
.callee(self.env().account_id())
.exec_input(ExecutionInput::new(Selector::new([0x00, 0x00, 0x00, 0x02])))
.returns::<ReturnType<bool>>()
.call_flags(CallFlags::default().set_allow_reentry(true))
.fire()
.expect("failed executing call")
}
}
}
68 changes: 68 additions & 0 deletions src/tests/contract_introspection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2018-2021 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.

//! Tests for the `contract_introspection `example.

use crate::{
uis::{
Call,
Result,
Ui,
Upload,
},
utils::{
self,
cargo_contract,
},
};
use lang_macro::waterfall_test;

#[waterfall_test(example = "contract_introspection")]
async fn delegator_works(mut ui: Ui) -> Result<()> {
// given
let contract_path =
cargo_contract::build(&utils::example_path("contract-introspection/Cargo.toml"))
.expect("contract build failed");

// when
let addr = ui.execute_upload(Upload::new(contract_path)).await?;

// then
// the method is called directly via the ui.
assert_eq!(
ui.execute_rpc(Call::new(&addr, "is_caller_contract"))
.await?,
"false"
);
// the `is_caller_contract` method is called indirectly from this contract method.
assert_eq!(
ui.execute_rpc(Call::new(&addr, "calls_is_caller_contract"))
.await?,
"true"
);

// the method is called directly via the ui.
assert_eq!(
ui.execute_rpc(Call::new(&addr, "is_caller_origin")).await?,
"true"
);
// the `is_caller_origin` method is called indirectly from this contract method.
assert_eq!(
ui.execute_rpc(Call::new(&addr, "calls_is_caller_origin"))
.await?,
"false"
);

Ok(())
}
1 change: 1 addition & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

mod contract_introspection;
mod contract_terminate;
mod contract_transfer;
mod delegator;
Expand Down
15 changes: 13 additions & 2 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,22 @@ pub fn test_name() -> String {
}

/// Returns the full path to the ink! example directory for `example`.
///
/// This method will first try to look the example up in `INK_EXAMPLES_PATH`.
/// If not found there, it will fall back to `./examples/` ++ `example`.
pub fn example_path(example: &str) -> PathBuf {
let examples_path = std::env::var("INK_EXAMPLES_PATH")
.expect("env variable `INK_EXAMPLES_PATH` must be set");
let path = PathBuf::from(examples_path);
path.join(example)
let mut path = PathBuf::from(examples_path).join(example);

// Check if path exists, if not assume it's a local example to `ink-waterfall`.
// This is done as a fallback if the waterfall tests are run locally.
// For the CI we copy all `ink-waterfall/examples/` to the `INK_EXAMPLES_PATH`.
if !path.exists() {
path = PathBuf::from("./examples/").join(example);
}

path
}

/// Extracts the `source.hash` field from the contract bundle.
Expand Down