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

Commit

Permalink
Address @HCastano's comments
Browse files Browse the repository at this point in the history
  • Loading branch information
yarikbratashchuk committed Feb 1, 2022
1 parent 49ea4b8 commit b6e7948
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 21 deletions.
10 changes: 5 additions & 5 deletions frame/contracts/fixtures/delegate_call.wat
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@
;; Call deployed library contract code.
(set_local $exit_code
(call $seal_delegate_call
(i32.const 0) ;; Set no call flags
(i32.const 0) ;; Set no call flags
(i32.const 64) ;; Pointer to "callee" code_hash.
(i32.const 0) ;; Input is ignored
(i32.const 0) ;; Length of the input
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; Input is ignored
(i32.const 0) ;; Length of the input
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)

Expand Down
10 changes: 5 additions & 5 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,6 @@ pub struct Stack<'a, T: Config, E> {
/// This is an internal data structure. It is exposed to the public for the sole reason
/// of specifying [`Config::CallStack`].
pub struct Frame<T: Config> {
/// The caller of the currently executing frame which was spawned by `delegate_call`.
delegate_caller: Option<T::AccountId>,
/// The account id of the executing contract.
account_id: T::AccountId,
/// The cached in-storage data of the contract.
Expand All @@ -353,6 +351,8 @@ pub struct Frame<T: Config> {
nested_storage: storage::meter::NestedMeter<T>,
/// If `false` the contract enabled its defense against reentrance attacks.
allows_reentry: bool,
/// The caller of the currently executing frame which was spawned by `delegate_call`.
delegate_caller: Option<T::AccountId>,
}

/// Used in a delegate call frame arguments in order to override the executable and caller.
Expand All @@ -372,9 +372,9 @@ 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>>,
/// This frame was created by `seal_delegate_call` and hence uses a different code than
/// what is stored at [`Self::dest`]. Its caller (`delegated_caller`) is a caller of the
/// caller contract
/// This frame was created by `seal_delegate_call` and hence uses different code than
/// what is stored at [`Self::dest`]. Its caller ([`Frame::delegated_caller`]) is the
/// account which called the caller contract
delegated_call: Option<DelegatedCall<T, E>>,
},
Instantiate {
Expand Down
25 changes: 14 additions & 11 deletions frame/contracts/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ bitflags! {
/// Without this flag any reentrancy into the current contract that originates from
/// the callee (or any of its callees) is denied. This includes the first callee:
/// You cannot call into yourself with this flag set.
///
/// # Note
///
/// For `seal_delegate_call` should be always unset, otherwise
/// [`Error::InvalidCallFlags`] is returned.
const ALLOW_REENTRY = 0b0000_1000;
Expand All @@ -367,10 +370,10 @@ bitflags! {

/// The kind of call that should be performed.
enum CallType {
/// Call is to call to another instantiated contract
/// Execute another instantiated contract
Call { callee_ptr: u32, value_ptr: u32, gas: u64 },
#[cfg(feature = "unstable-interface")]
/// DelegateCall is to execute deployed code in caller contract context
/// Execute deployed code in the context (storage, account ID, value) of the caller contract
DelegateCall { code_hash_ptr: u32 },
}

Expand Down Expand Up @@ -738,14 +741,6 @@ where
};

let call_outcome = match call_type {
#[cfg(feature = "unstable-interface")]
CallType::DelegateCall { code_hash_ptr } => {
if flags.contains(CallFlags::ALLOW_REENTRY) {
return Err(Error::<E::T>::InvalidCallFlags.into())
}
let code_hash = self.read_sandbox_memory_as(code_hash_ptr)?;
self.ext.delegate_call(code_hash, input_data)
},
CallType::Call { callee_ptr, value_ptr, gas } => {
let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
self.read_sandbox_memory_as(callee_ptr)?;
Expand All @@ -761,6 +756,14 @@ where
flags.contains(CallFlags::ALLOW_REENTRY),
)
},
#[cfg(feature = "unstable-interface")]
CallType::DelegateCall { code_hash_ptr } => {
if flags.contains(CallFlags::ALLOW_REENTRY) {
return Err(Error::<E::T>::InvalidCallFlags.into())
}
let code_hash = self.read_sandbox_memory_as(code_hash_ptr)?;
self.ext.delegate_call(code_hash, input_data)
},
};

// `TAIL_CALL` only matters on an `OK` result. Otherwise the call stack comes to
Expand Down Expand Up @@ -1092,7 +1095,7 @@ define_env!(Env, <E: Ext>,
)
},

// Execute code in the context of the current contract.
// Execute code in the context (storage, caller, value) of the current contract.
//
// Reentrancy protection is always disabled since the callee is allowed
// to modify the callers storage. This makes going through a reentrancy attack
Expand Down

0 comments on commit b6e7948

Please sign in to comment.