Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Same seal_caller and seal_value_transferred for lib contract
Browse files Browse the repository at this point in the history
- test
- refactor frame args due to review
- logic for seal_caller (please review)
  • Loading branch information
yarikbratashchuk committed Jan 19, 2022
1 parent dcbce24 commit 378ddd7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 9 deletions.
61 changes: 61 additions & 0 deletions frame/contracts/fixtures/delegate_call_lib.wat
Original file line number Diff line number Diff line change
@@ -1,17 +1,78 @@
(module
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_caller" (func $seal_caller (param i32 i32)))
(import "seal0" "seal_value_transferred" (func $seal_value_transferred (param i32 i32)))
(import "env" "memory" (memory 1 1))

;; [0, 32) storage key
(data (i32.const 0) "\01")

;; [32, 64) buffer for transferred value

;; [64, 96) size of the buffer for transferred value
(data (i32.const 64) "\20")

;; [96, 128) buffer for the caller

;; [128, 160) size of the buffer for caller
(data (i32.const 128) "\20")

(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)

(func (export "call")
;; place a value in storage
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.const 32) ;; Size of value
)

;; This stores the value transferred in the buffer
(call $seal_value_transferred (i32.const 32) (i32.const 64))

;; assert len == 8
(call $assert
(i32.eq
(i32.load (i32.const 64))
(i32.const 8)
)
)

;; assert that contents of the buffer is equal to the value
;; passed to the `caller` contract: 1337
(call $assert
(i64.eq
(i64.load (i32.const 32))
(i64.const 1337)
)
)

;; fill the buffer with the caller.
(call $seal_caller (i32.const 96) (i32.const 128))

;; assert len == 32
(call $assert
(i32.eq
(i32.load (i32.const 128))
(i32.const 32)
)
)

;; assert that the first 64 byte are the beginning of "ALICE",
;; who is the caller of the `caller` contract
(call $assert
(i64.eq
(i64.load (i32.const 96))
(i64.const 0x0101010101010101)
)
)
)

(func (export "deploy"))
Expand Down
29 changes: 21 additions & 8 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,10 @@ enum FrameArgs<'a, T: Config, E> {
dest: T::AccountId,
/// If `None` the contract info needs to be reloaded from storage.
cached_info: Option<ContractInfo<T>>,
/// The executable whose `call` function is run.
executable: Option<E>,
/// This frame was created by `seal_delegate_call` and hence uses a different code than
/// what is stored at [`Self::dest`]. It also uses a different caller than the previous
/// frames [`Self::dest`].
delegated_call: Option<E>,
},
Instantiate {
/// The contract or signed origin which instantiates the new contract.
Expand Down Expand Up @@ -519,7 +521,7 @@ where
debug_message: Option<&'a mut Vec<u8>>,
) -> Result<ExecReturnValue, ExecError> {
let (mut stack, executable) = Self::new(
FrameArgs::Call { dest, cached_info: None, executable: None },
FrameArgs::Call { dest, cached_info: None, delegated_call: None },
origin,
gas_meter,
storage_meter,
Expand Down Expand Up @@ -612,14 +614,14 @@ where
) -> Result<(Frame<T>, E, Option<u64>), ExecError> {
let (account_id, contract_info, executable, entry_point, account_counter) = match frame_args
{
FrameArgs::Call { dest, cached_info, executable } => {
FrameArgs::Call { dest, cached_info, delegated_call } => {
let contract = if let Some(contract) = cached_info {
contract
} else {
<ContractInfoOf<T>>::get(&dest).ok_or(<Error<T>>::ContractNotFound)?
};

let executable = if let Some(executable) = executable {
let executable = if let Some(executable) = delegated_call {
executable
} else {
E::from_storage(contract.code_hash, schedule, gas_meter)?
Expand Down Expand Up @@ -947,7 +949,7 @@ where
_ => None,
});
let executable = self.push_frame(
FrameArgs::Call { dest: to, cached_info, executable: None },
FrameArgs::Call { dest: to, cached_info, delegated_call: None },
value,
gas_limit,
)?;
Expand Down Expand Up @@ -977,7 +979,7 @@ where
FrameArgs::Call {
dest: account_id,
cached_info: Some(contract_info),
executable: Some(executable),
delegated_call: Some(executable),
},
value,
0,
Expand Down Expand Up @@ -1065,7 +1067,18 @@ where
}

fn caller(&self) -> &T::AccountId {
self.frames().nth(1).map(|f| &f.account_id).unwrap_or(&self.origin)
let caller_frame = self.frames().nth(1);
let callee_frame = self.frames().nth(0);
let caller = if caller_frame.map(|f| &f.account_id) == callee_frame.map(|f| &f.account_id) &&
caller_frame.map(|f| &f.nested_gas).unwrap_or(&self.gas_meter).gas_left() == 0
{
// in the case of `delegate_call` the caller and callee are the same and all gas is
// passed to the callee
self.frames().nth(2)
} else {
caller_frame
};
caller.map(|f| &f.account_id).unwrap_or(&self.origin)
}

fn balance(&self) -> BalanceOf<T> {
Expand Down
2 changes: 1 addition & 1 deletion frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ fn delegate_call() {
assert_ok!(Contracts::call(
Origin::signed(ALICE),
caller_addr.clone(),
0,
1337,
GAS_LIMIT,
None,
callee_code_hash.as_ref().to_vec(),
Expand Down

0 comments on commit 378ddd7

Please sign in to comment.