-
Notifications
You must be signed in to change notification settings - Fork 2
/
lib.rs
executable file
·186 lines (168 loc) · 7.31 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// If `std` feature is disabled, we are building for Wasm target
// and we need to use `no_std` and `no_main` attributes
// to compile the contract as a Wasm binary.
// If `std` feature is enabled, we are building for native target
// and we don't need these attributes.
// ink! builds in `std` mode when running tests.
//
// `no_std` attribute disables the standard library.
// When `no_std` is enabled, the `core` and `alloc` libraries are available.
// The `ink` crate provides necessary functionality in place of the standard library.
// `no_main` attribute disables the default entry point for the binary.
// We define our own entry point using the `#[ink::contract]` attribute.
#![cfg_attr(not(feature = "std"), no_std, no_main)]
/// Docs on utilities to call or instantiate contracts on the chain:
/// https://docs.rs/ink_env/5.0.0/ink_env/call/index.html
#[ink::contract]
mod cross_contract_flipper {
/// The global call builder type for an ink! trait definition.
/// Allows us to use call_mut() which is a method of TraitCallBuilder
/// that returns an exclusive reference to the global call builder type.
use ink::codegen::TraitCallBuilder;
use ink::env::{
call::{build_call, build_create, ExecutionInput, Selector},
DefaultEnvironment,
};
use other_contract::OtherContractRef;
#[ink(storage)]
pub struct CrossContractFlipper {
other_contract: OtherContractRef,
other_contract_code_hash: Hash,
}
impl CrossContractFlipper {
/// Initializes a contract by specifying the code hash of the other contract
#[ink(constructor)]
pub fn new(other_contract_code_hash: Hash) -> Self {
let other_contract = OtherContractRef::new(true)
.code_hash(other_contract_code_hash)
// Amount transferred upon the execution of this call (instantiation).
.endowment(0)
// The salt for determining the hash for the contract account ID.
// Use to create multiple instances of the same contract code from the same account.
.salt_bytes([0xDE, 0xAD, 0xBE, 0xEF])
.instantiate();
Self {
other_contract,
other_contract_code_hash,
}
}
/// Initializes a contract by specifying the code hash of the other contract
/// using the create builder API
/// https://docs.rs/ink_env/5.0.0/ink_env/call/struct.CreateBuilder.html
#[ink(constructor)]
pub fn new_with_create_builder(other_contract_code_hash: Hash) -> Self {
let other_contract: OtherContractRef = build_create::<OtherContractRef>()
.code_hash(other_contract_code_hash)
.endowment(0)
.exec_input(
ExecutionInput::new(Selector::new(ink::selector_bytes!("new"))).push_arg(true),
)
.salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF])
.returns::<OtherContractRef>()
.instantiate();
Self {
other_contract,
other_contract_code_hash,
}
}
/// Calls the `flip` method of the other contract
/// using the call builder API
/// https://docs.rs/ink_env/5.0.0/ink_env/call/struct.CallBuilder.html
#[ink(message)]
pub fn build_call_flip_1(&mut self) {
build_call::<DefaultEnvironment>()
.call(self.get_other_contract_account_id())
// Amount of funds that are transferred to the other contract with this call.
.transferred_value(0)
.exec_input(ExecutionInput::new(Selector::new(ink::selector_bytes!(
"flip"
))))
.returns::<()>()
.invoke();
}
/// Calls the `flip` method of another contract dynamically
/// using the call builder API and specifying the account ID of the other contract
/// https://docs.rs/ink_env/5.0.0/ink_env/call/struct.CallBuilder.html
#[ink(message)]
pub fn build_call_flip_2(&mut self, other_contract_account_id: AccountId) {
build_call::<DefaultEnvironment>()
.call(other_contract_account_id)
.transferred_value(0)
.exec_input(ExecutionInput::new(Selector::new(ink::selector_bytes!(
"flip"
))))
.returns::<()>()
.invoke();
}
/// Calls `flip` method of the other contract
/// without specifying the weight and storage limits
#[ink(message)]
pub fn call_flip(&mut self) {
self.other_contract.flip();
}
/// Calls `set` method of the other contract
/// without specifying the weight and storage limits
#[ink(message)]
pub fn call_set(&mut self) {
self.other_contract.set(true);
}
/// Calls `get` method of the other contract
/// without specifying the weight and storage limits
#[ink(message)]
pub fn call_get(&mut self) -> bool {
self.other_contract.get()
}
/// Calls the `flip` method of the other contract
/// with the specified weight and storage limits
#[ink(message)]
pub fn call_flip_with_limits(
&mut self,
ref_time_limit: u64,
proof_size_limit: u64,
storage_deposit_limit: Balance,
) {
self.other_contract
.call_mut()
.flip()
.ref_time_limit(ref_time_limit)
.proof_size_limit(proof_size_limit)
.storage_deposit_limit(storage_deposit_limit)
.invoke();
}
/// Calls the `get` method of the other contract
/// with the specified weight and storage limits
#[ink(message)]
pub fn call_get_with_limits(
&mut self,
ref_time_limit: u64,
proof_size_limit: u64,
storage_deposit_limit: Balance,
) -> bool {
self.other_contract
.call_mut()
.get()
.ref_time_limit(ref_time_limit)
.proof_size_limit(proof_size_limit)
.storage_deposit_limit(storage_deposit_limit)
.invoke()
}
/// Calls `get_account_id` method of the other contract
/// without specifying the weight and storage limits
#[ink(message)]
pub fn get_other_contract_account_id(&mut self) -> AccountId {
self.other_contract.get_account_id()
}
// Delegate calls `flip` method of the other contract
// using `DelegateCall` method of the call builder API
// https://docs.rs/ink_env/5.0.0/ink_env/call/struct.DelegateCall.html
// https://docs.rs/ink_env/5.0.0/ink_env/call/fn.build_call.html#example-3-delegate-call
// https://medium.com/coinmonks/delegatecall-calling-another-contract-function-in-solidity-b579f804178c
#[ink(message)]
pub fn delegate_flip(&mut self) {
// Bonus Exercise: Delegate call to the other contract
// Submit a PR to this repo when completed
// Include steps to test the delegate call, even better would be e2e tests ;)
todo!()
}
}
}