Skip to content

Commit 44993ed

Browse files
committed
try delegate call
1 parent 36a32f1 commit 44993ed

16 files changed

Lines changed: 659 additions & 42 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chain-extensions/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pallet-drand.workspace = true
3535
subtensor-swap-interface.workspace = true
3636
num_enum.workspace = true
3737
substrate-fixed.workspace = true
38+
sp-debug-derive = { workspace = true, features = ["force-debug"] }
3839

3940
[lints]
4041
workspace = true

chain-extensions/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,15 @@ where
739739

740740
Ok(RetVal::Converging(Output::Success as u32))
741741
}
742+
FunctionId::DummyV1 => {
743+
let weight = Weight::from_parts(1_000, 0);
744+
let caller = env.caller();
745+
let origin = env.origin();
746+
log::error!("dummy: contract address as caller = {:?}", caller);
747+
log::error!("dummy: original account as origin = {:?}", origin);
748+
env.charge_weight(weight)?;
749+
Ok(RetVal::Converging(Output::Success as u32))
750+
}
742751
}
743752
}
744753
}
@@ -817,6 +826,9 @@ where
817826
}
818827

819828
fn origin(&mut self) -> pallet_contracts::Origin<T> {
829+
if let pallet_contracts::Origin::Signed(account_id) = self.env.ext().caller() {
830+
log::error!("origin: signed account id = {:?}", account_id);
831+
}
820832
self.env.ext().caller()
821833
}
822834
}

chain-extensions/src/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ pub enum FunctionId {
3535
CallerSetColdkeyAutoStakeHotkeyV1 = 27,
3636
CallerAddProxyV1 = 28,
3737
CallerRemoveProxyV1 = 29,
38+
/// No-op extension for ink integration tests (`direct_call` / `delegate_call` contracts).
39+
DummyV1 = 100,
3840
}
3941

4042
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Debug)]
@@ -134,6 +136,7 @@ mod function_id_tests {
134136
assert_eq!(FunctionId::CallerSetColdkeyAutoStakeHotkeyV1 as u16, 27);
135137
assert_eq!(FunctionId::CallerAddProxyV1 as u16, 28);
136138
assert_eq!(FunctionId::CallerRemoveProxyV1 as u16, 29);
139+
assert_eq!(FunctionId::DummyV1 as u16, 100);
137140
}
138141

139142
#[test]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Ignore build artifacts from the local tests sub-crate.
2+
/target/
3+
4+
# Ignore backup files creates by cargo fmt.
5+
**/*.rs.bk
6+
7+
# Remove Cargo.lock when creating an executable, leave it for libraries
8+
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
9+
Cargo.lock
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[workspace]
2+
3+
[package]
4+
name = "delegate_call"
5+
version = "0.1.0"
6+
authors = ["[your_name] <[your_email]>"]
7+
edition = "2021"
8+
9+
[dependencies]
10+
ink = { version = "5.1.1", default-features = false }
11+
parity-scale-codec = { version = "3.0.0", default-features = false }
12+
serde = { version = "1.0.228", default-features = false }
13+
[dev-dependencies]
14+
ink_e2e = { version = "5.1.1" }
15+
16+
[lib]
17+
path = "lib.rs"
18+
19+
[features]
20+
default = ["std"]
21+
std = [
22+
"ink/std",
23+
"parity-scale-codec/std",
24+
"serde/std",
25+
]
26+
27+
ink-as-dependency = []
28+
e2e-tests = []
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#![cfg_attr(not(feature = "std"), no_std, no_main)]
2+
3+
use ink::env::call::{ExecutionInput, Selector, build_call};
4+
#[derive(Debug, Clone)]
5+
pub struct CustomEnvironment;
6+
7+
pub enum FunctionId {
8+
Dummy = 100,
9+
}
10+
11+
#[ink::chain_extension(extension = 0x1000)]
12+
pub trait RuntimeReadWrite {
13+
type ErrorCode = ReadWriteErrorCode;
14+
15+
#[ink(function = 100)]
16+
fn dummy();
17+
}
18+
19+
#[ink::scale_derive(Encode, Decode, TypeInfo)]
20+
pub enum ReadWriteErrorCode {
21+
ReadFailed,
22+
WriteFailed,
23+
}
24+
25+
impl ink::env::chain_extension::FromStatusCode for ReadWriteErrorCode {
26+
fn from_status_code(status_code: u32) -> Result<(), Self> {
27+
match status_code {
28+
0 => Ok(()),
29+
1 => Err(ReadWriteErrorCode::ReadFailed),
30+
2 => Err(ReadWriteErrorCode::WriteFailed),
31+
_ => Err(ReadWriteErrorCode::ReadFailed),
32+
}
33+
}
34+
}
35+
36+
impl ink::env::Environment for CustomEnvironment {
37+
const MAX_EVENT_TOPICS: usize = 4;
38+
39+
type AccountId = ink::primitives::AccountId;
40+
type Balance = u64;
41+
type Hash = ink::primitives::Hash;
42+
type BlockNumber = u32;
43+
type Timestamp = u64;
44+
45+
type ChainExtension = RuntimeReadWrite;
46+
}
47+
48+
#[ink::contract(env = crate::CustomEnvironment)]
49+
mod delegate_call {
50+
use super::*;
51+
52+
#[ink(storage)]
53+
pub struct Bittensor {}
54+
55+
impl Bittensor {
56+
#[ink(constructor)]
57+
pub fn new() -> Self {
58+
Self {}
59+
}
60+
61+
/// Constructor
62+
#[ink(constructor)]
63+
pub fn default() -> Self {
64+
Self::new()
65+
}
66+
67+
#[ink(message)]
68+
pub fn dummy(&self, code_hash: [u8; 32]) -> Result<(), ReadWriteErrorCode> {
69+
// let code_hash = self
70+
// .delegate_code_hash
71+
// .unwrap_or(ink::primitives::Hash::from(hash));
72+
let my_return_value = build_call::<CustomEnvironment>()
73+
.delegate(ink::primitives::Hash::from(code_hash))
74+
.exec_input(ExecutionInput::new(Selector::new(ink::selector_bytes!(
75+
"dummy"
76+
))))
77+
.returns::<Result<(), ReadWriteErrorCode>>()
78+
.invoke();
79+
80+
my_return_value.map_err(|_e| ReadWriteErrorCode::WriteFailed)
81+
}
82+
}
83+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Ignore build artifacts from the local tests sub-crate.
2+
/target/
3+
4+
# Ignore backup files creates by cargo fmt.
5+
**/*.rs.bk
6+
7+
# Remove Cargo.lock when creating an executable, leave it for libraries
8+
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
9+
Cargo.lock
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[workspace]
2+
3+
[package]
4+
name = "direct_call"
5+
version = "0.1.0"
6+
authors = ["[your_name] <[your_email]>"]
7+
edition = "2021"
8+
9+
[dependencies]
10+
ink = { version = "5.1.1", default-features = false }
11+
parity-scale-codec = { version = "3.0.0", default-features = false }
12+
serde = { version = "1.0.228", default-features = false }
13+
[dev-dependencies]
14+
ink_e2e = { version = "5.1.1" }
15+
16+
[lib]
17+
path = "lib.rs"
18+
19+
[features]
20+
default = ["std"]
21+
std = [
22+
"ink/std",
23+
"parity-scale-codec/std",
24+
"serde/std",
25+
]
26+
27+
ink-as-dependency = []
28+
e2e-tests = []

contract-tests/direct-call/lib.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#![cfg_attr(not(feature = "std"), no_std, no_main)]
2+
3+
use parity_scale_codec::Compact;
4+
5+
#[derive(Debug, Clone)]
6+
pub struct CustomEnvironment;
7+
8+
pub enum FunctionId {
9+
Dummy = 100,
10+
}
11+
12+
#[ink::chain_extension(extension = 0x1000)]
13+
pub trait RuntimeReadWrite {
14+
type ErrorCode = ReadWriteErrorCode;
15+
16+
#[ink(function = 100)]
17+
fn dummy();
18+
}
19+
20+
#[ink::scale_derive(Encode, Decode, TypeInfo)]
21+
pub enum ReadWriteErrorCode {
22+
ReadFailed,
23+
WriteFailed,
24+
}
25+
26+
impl ink::env::chain_extension::FromStatusCode for ReadWriteErrorCode {
27+
fn from_status_code(status_code: u32) -> Result<(), Self> {
28+
match status_code {
29+
0 => Ok(()),
30+
1 => Err(ReadWriteErrorCode::ReadFailed),
31+
2 => Err(ReadWriteErrorCode::WriteFailed),
32+
_ => Err(ReadWriteErrorCode::ReadFailed),
33+
}
34+
}
35+
}
36+
37+
impl ink::env::Environment for CustomEnvironment {
38+
const MAX_EVENT_TOPICS: usize = 4;
39+
40+
type AccountId = ink::primitives::AccountId;
41+
type Balance = u64;
42+
type Hash = ink::primitives::Hash;
43+
type BlockNumber = u32;
44+
type Timestamp = u64;
45+
46+
type ChainExtension = RuntimeReadWrite;
47+
}
48+
49+
#[ink::contract(env = crate::CustomEnvironment)]
50+
mod direct_call {
51+
use super::*;
52+
53+
/// Defines the storage of your contract.
54+
/// Add new fields to the below struct in order
55+
/// to add new static storage fields to your contract.
56+
#[ink(storage)]
57+
pub struct Bittensor {}
58+
59+
impl Bittensor {
60+
/// Constructor
61+
#[ink(constructor)]
62+
pub fn new() -> Self {
63+
Self {}
64+
}
65+
66+
/// Constructor
67+
#[ink(constructor)]
68+
pub fn default() -> Self {
69+
Self::new()
70+
}
71+
72+
#[ink(message)]
73+
pub fn dummy(&self) -> Result<(), ReadWriteErrorCode> {
74+
self.env()
75+
.extension()
76+
.dummy()
77+
.map_err(|_e| ReadWriteErrorCode::WriteFailed)
78+
}
79+
}
80+
}

0 commit comments

Comments
 (0)