use crate::{
call::{
common::{
ReturnType,
Set,
Unset,
},
execution::EmptyArgumentList,
CallBuilder,
CallParams,
ExecutionInput,
},
Environment,
Error,
};
use pallet_contracts_uapi::CallFlags;
#[derive(Clone)]
pub struct DelegateCall<E: Environment> {
code_hash: E::Hash,
call_flags: CallFlags,
}
impl<E: Environment> DelegateCall<E> {
pub const fn new(code_hash: E::Hash) -> Self {
DelegateCall {
code_hash,
call_flags: CallFlags::empty(),
}
}
pub fn code_hash(self, code_hash: E::Hash) -> Self {
DelegateCall {
code_hash,
call_flags: CallFlags::empty(),
}
}
}
impl<E, Args, RetType> CallBuilder<E, Set<DelegateCall<E>>, Args, RetType>
where
E: Environment,
{
pub fn code_hash(self, code_hash: E::Hash) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(DelegateCall {
code_hash,
..call_type
}),
..self
}
}
pub fn call_flags(self, call_flags: CallFlags) -> Self {
CallBuilder {
call_type: Set(DelegateCall {
call_flags,
..self.call_type.value()
}),
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, Args, RetType>
CallBuilder<
E,
Set<DelegateCall<E>>,
Set<ExecutionInput<Args>>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, DelegateCall<E>, Args, RetType> {
CallParams {
call_type: self.call_type.value(),
_return_type: Default::default(),
exec_input: self.exec_input.value(),
_phantom: self._phantom,
}
}
}
impl<E, RetType>
CallBuilder<
E,
Set<DelegateCall<E>>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<RetType>,
>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, DelegateCall<E>, EmptyArgumentList, ()> {
CallParams {
call_type: self.call_type.value(),
_return_type: Default::default(),
exec_input: Default::default(),
_phantom: self._phantom,
}
}
}
impl<E>
CallBuilder<
E,
Set<DelegateCall<E>>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<ReturnType<()>>,
>
where
E: Environment,
{
pub fn invoke(self) {
self.params().invoke()
}
pub fn try_invoke(self) -> Result<ink_primitives::MessageResult<()>, Error> {
self.params().try_invoke()
}
}
impl<E, Args, R>
CallBuilder<E, Set<DelegateCall<E>>, Set<ExecutionInput<Args>>, Set<ReturnType<R>>>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn invoke(self) -> R {
self.params().invoke()
}
pub fn try_invoke(self) -> Result<ink_primitives::MessageResult<R>, Error> {
self.params().try_invoke()
}
}
impl<E, Args, R> CallParams<E, DelegateCall<E>, Args, R>
where
E: Environment,
{
#[inline]
pub fn code_hash(&self) -> &E::Hash {
&self.call_type.code_hash
}
#[inline]
pub fn call_flags(&self) -> &CallFlags {
&self.call_type.call_flags
}
}
impl<E, Args, R> CallParams<E, DelegateCall<E>, Args, R>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn invoke(&self) -> R {
crate::invoke_contract_delegate(self)
.unwrap_or_else(|env_error| {
panic!("Cross-contract call failed with {env_error:?}")
})
.unwrap_or_else(|lang_error| {
panic!("Cross-contract call failed with {lang_error:?}")
})
}
pub fn try_invoke(&self) -> Result<ink_primitives::MessageResult<R>, crate::Error> {
crate::invoke_contract_delegate(self)
}
}