use crate::{
call::{
common::{
ReturnType,
Set,
Unset,
},
execution::EmptyArgumentList,
utils::DecodeMessageResult,
CallBuilder,
CallParams,
ExecutionInput,
},
types::{
Environment,
Gas,
},
Error,
};
use ink_primitives::{
reflect::{
AbiDecodeWith,
AbiEncodeWith,
},
Address,
U256,
};
use pallet_revive_uapi::CallFlags;
#[derive(Clone)]
pub struct Call {
callee: Address,
ref_time_limit: u64,
proof_size_limit: u64,
storage_deposit_limit: Option<U256>,
transferred_value: U256,
call_flags: CallFlags,
}
impl Call {
pub fn new(callee: Address) -> Self {
Self {
callee,
ref_time_limit: u64::MAX,
proof_size_limit: u64::MAX,
storage_deposit_limit: None,
transferred_value: U256::zero(),
call_flags: CallFlags::empty(),
}
}
}
impl<E, Args, RetType> CallBuilder<E, Set<Call>, Args, RetType>
where
E: Environment,
{
pub fn ref_time_limit(self, ref_time_limit: Gas) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
ref_time_limit,
..call_type
}),
..self
}
}
pub fn proof_size_limit(self, proof_size_limit: Gas) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
proof_size_limit,
..call_type
}),
..self
}
}
pub fn storage_deposit_limit(self, storage_deposit_limit: U256) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
storage_deposit_limit: Some(storage_deposit_limit),
..call_type
}),
..self
}
}
pub fn transferred_value(self, transferred_value: U256) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
transferred_value,
..call_type
}),
..self
}
}
pub fn call_flags(self, call_flags: CallFlags) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
call_flags,
..call_type
}),
..self
}
}
}
impl<E, Args, RetType, Abi>
CallBuilder<E, Set<Call>, Set<ExecutionInput<Args, Abi>>, Set<ReturnType<RetType>>>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, Call, 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<Call>,
Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
Unset<RetType>,
>
where
E: Environment,
Abi: Default,
{
pub fn params(self) -> CallParams<E, Call, 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<Call>,
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<Call>, Set<ExecutionInput<Args, Abi>>, Set<ReturnType<R>>>
where
E: Environment,
Args: AbiEncodeWith<Abi>,
R: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
Abi: Default,
{
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, Call, Args, R, Abi>
where
E: Environment,
{
#[inline]
pub fn callee(&self) -> &Address {
&self.call_type.callee
}
#[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 storage_deposit_limit(&self) -> Option<U256> {
self.call_type.storage_deposit_limit
}
#[inline]
pub fn transferred_value(&self) -> &U256 {
&self.call_type.transferred_value
}
#[inline]
pub fn call_flags(&self) -> &CallFlags {
&self.call_type.call_flags
}
}
impl<E, Args, R, Abi> CallParams<E, Call, Args, R, Abi>
where
E: Environment,
Args: AbiEncodeWith<Abi>,
R: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
{
pub fn invoke(&self) -> R {
crate::invoke_contract(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(self)
}
}