use crate::{
call::{
common::{
ReturnType,
Set,
Unset,
},
execution::EmptyArgumentList,
utils::DecodeMessageResult,
CallBuilder,
CallParams,
ExecutionInput,
},
types::Environment,
Error,
};
use ink_primitives::{
reflect::{
AbiDecodeWith,
AbiEncodeWith,
},
Address,
};
use pallet_revive_uapi::CallFlags;
#[derive(Clone)]
pub struct DelegateCall {
address: Address,
flags: CallFlags,
ref_time_limit: u64,
proof_size_limit: u64,
deposit_limit: Option<[u8; 32]>,
}
impl DelegateCall {
pub const fn new(address: Address) -> Self {
DelegateCall {
address,
flags: CallFlags::empty(),
ref_time_limit: u64::MAX,
proof_size_limit: u64::MAX,
deposit_limit: None,
}
}
pub fn address(self, address: Address) -> Self {
DelegateCall {
address,
flags: CallFlags::empty(),
ref_time_limit: u64::MAX,
proof_size_limit: u64::MAX,
deposit_limit: None,
}
}
}
impl<E, Args, RetType> CallBuilder<E, Set<DelegateCall>, Args, RetType>
where
E: Environment,
{
pub fn address(self, address: Address) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(DelegateCall {
address,
..call_type
}),
..self
}
}
pub fn call_flags(self, call_flags: CallFlags) -> Self {
CallBuilder {
call_type: Set(DelegateCall {
flags: call_flags,
..self.call_type.value()
}),
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, Args, RetType, Abi>
CallBuilder<
E,
Set<DelegateCall>,
Set<ExecutionInput<Args, Abi>>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, DelegateCall, Args, RetType, Abi> {
CallParams {
call_type: self.call_type.value(),
_return_type: Default::default(),
exec_input: self.exec_input.value(),
_phantom: self._phantom,
}
}
}
impl<E, RetType, Abi>
CallBuilder<
E,
Set<DelegateCall>,
Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
Unset<RetType>,
>
where
E: Environment,
EmptyArgumentList<Abi>: AbiEncodeWith<Abi>,
(): AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
Abi: Default,
{
pub fn params(self) -> CallParams<E, DelegateCall, EmptyArgumentList<Abi>, (), Abi> {
CallParams {
call_type: self.call_type.value(),
_return_type: Default::default(),
exec_input: Default::default(),
_phantom: self._phantom,
}
}
}
impl<E, Abi>
CallBuilder<
E,
Set<DelegateCall>,
Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
Unset<ReturnType<()>>,
>
where
E: Environment,
EmptyArgumentList<Abi>: AbiEncodeWith<Abi>,
(): AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
Abi: Default,
{
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, Abi>
CallBuilder<E, Set<DelegateCall>, Set<ExecutionInput<Args, Abi>>, Set<ReturnType<R>>>
where
E: Environment,
Args: AbiEncodeWith<Abi>,
R: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
{
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, Abi> CallParams<E, DelegateCall, Args, R, Abi>
where
E: Environment,
{
#[inline]
pub fn call_flags(&self) -> &CallFlags {
&self.call_type.flags
}
#[inline]
pub fn address(&self) -> &Address {
&self.call_type.address
}
#[inline]
pub fn ref_time_limit(&self) -> u64 {
self.call_type.ref_time_limit
}
#[inline]
pub fn proof_size_limit(&self) -> u64 {
self.call_type.proof_size_limit
}
#[inline]
pub fn deposit_limit(&self) -> &Option<[u8; 32]> {
&self.call_type.deposit_limit
}
}
impl<E, Args, R, Abi> CallParams<E, DelegateCall, Args, R, Abi>
where
E: Environment,
Args: AbiEncodeWith<Abi>,
R: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
{
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)
}
}