Parcourir la source

Add basic `ink!` to solidity call integration test (#1087)

Cyrill Leutwiler il y a 3 ans
Parent
commit
b52cb401ab

+ 3 - 0
.github/workflows/test.yml

@@ -320,6 +320,9 @@ jobs:
         echo "$(pwd)/bin" >> $GITHUB_PATH
     - run: npm install
       working-directory: ./integration/substrate
+    - name: Build ink! contracts
+      run: npm run build-ink
+      working-directory: ./integration/substrate
     - name: Build Solang contracts
       run: npm run build
       working-directory: ./integration/substrate

+ 9 - 0
integration/substrate/ink/caller/.gitignore

@@ -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

+ 30 - 0
integration/substrate/ink/caller/Cargo.toml

@@ -0,0 +1,30 @@
+[package]
+name = "caller"
+version = "0.1.0"
+authors = ["Cyrill Leutwiler <cyrill@parity.io>"]
+edition = "2021"
+
+[dependencies]
+ink = { version = "4.0.0-beta", default-features = false }
+
+scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
+scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true }
+
+[lib]
+name = "caller"
+path = "lib.rs"
+crate-type = [
+	# Used for normal contract Wasm blobs.
+	"cdylib",
+]
+
+[features]
+default = ["std"]
+std = [
+    "ink/std",
+    "scale/std",
+    "scale-info/std",
+]
+ink-as-dependency = []
+
+[workspace]

+ 46 - 0
integration/substrate/ink/caller/lib.rs

@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[ink::contract]
+mod caller {
+    use ink::env::{
+        call::{build_call, Call, ExecutionInput, Selector},
+        DefaultEnvironment,
+    };
+
+    #[ink(storage)]
+    #[derive(Default)]
+    pub struct Caller {}
+
+    impl Caller {
+        #[ink(constructor)]
+        pub fn new() -> Self {
+            Default::default()
+        }
+
+        /// Do a proxy call to `callee` and return its result.
+        /// The message under `selector` should have exactly one `u32` arguemnt and return a `u32`.
+        #[ink(message)]
+        pub fn u32_proxy(
+            &self,
+            callee: AccountId,
+            selector: [u8; 4],
+            arg: u32,
+            max_gas: Option<u64>,
+            transfer_value: Option<u128>,
+        ) -> u32 {
+            let my_return_value = build_call::<DefaultEnvironment>()
+                .call_type(
+                    Call::new()
+                        .callee(callee)
+                        .gas_limit(max_gas.unwrap_or_default()),
+                )
+                .transferred_value(transfer_value.unwrap_or_default())
+                .exec_input(ExecutionInput::new(Selector::new(selector)).push_arg(arg))
+                .returns::<u32>() // FIXME: This should be Result<u32, u8> to respect LanguageError
+                .fire();
+            my_return_value.unwrap()
+        }
+    }
+}

+ 44 - 0
integration/substrate/ink_cross_calls.spec.ts

@@ -0,0 +1,44 @@
+import expect from 'expect';
+import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index';
+import { ContractPromise } from '@polkadot/api-contract';
+import { ApiPromise } from '@polkadot/api';
+import { KeyringPair } from '@polkadot/keyring/types';
+
+describe('Test cross contract calls between ink and solidity', () => {
+    let conn: ApiPromise;
+    let alice: KeyringPair;
+
+    let ink_contract: ContractPromise;
+
+    let sol_contract: ContractPromise;
+    let inkee_echo = [1, 2, 3, 4];
+
+    before(async function () {
+        conn = await createConnection();
+        alice = aliceKeypair();
+
+        let ink_deployment = await deploy(conn, alice, 'ink/caller/target/ink/caller.contract', 0n);
+        ink_contract = new ContractPromise(conn, ink_deployment.abi, ink_deployment.address);
+
+        let sol_deployment = await deploy(conn, alice, 'Inkee.contract', 0n);
+        sol_contract = new ContractPromise(conn, sol_deployment.abi, sol_deployment.address);
+    });
+
+    it('calls solidity from ink', async function () {
+        this.timeout(50000);
+
+        async function proxy(goes_in: number) {
+            const comes_out = await query(conn, alice, ink_contract, "u32_proxy", [sol_contract.address, inkee_echo, goes_in, null, null]);
+            expect(comes_out.output?.toJSON()).toEqual({ "ok": goes_in });
+        }
+
+        await proxy(0);
+        await proxy(1);
+        await proxy(1337);
+        await proxy(0xffffffff);
+    });
+
+    after(async function () {
+        await conn.disconnect();
+    });
+});

+ 5 - 0
integration/substrate/inkee.sol

@@ -0,0 +1,5 @@
+contract Inkee {
+    function echo(uint32 v) selector=hex"01020304" public pure returns (uint32) {
+        return v;
+    }
+}

+ 2 - 1
integration/substrate/package.json

@@ -5,7 +5,8 @@
   "main": "index.js",
   "scripts": {
     "test": "tsc; ts-mocha -t 20000 *.spec.ts",
-    "build": "parallel solang compile -v --target substrate ::: *.sol test/*.sol"
+    "build": "parallel solang compile -v --target substrate ::: *.sol test/*.sol",
+    "build-ink": "docker run --rm -v $(pwd)/ink/caller:/opt/contract paritytech/contracts-ci-linux:latest cargo contract build --manifest-path /opt/contract/Cargo.toml"
   },
   "contributors": [
     {