use core::marker::PhantomData;
use ink_primitives::{
reflect::{
AbiEncodeWith,
ScaleEncoding,
},
Address,
H256,
U256,
};
#[cfg(feature = "unstable-hostfn")]
use crate::Error;
use crate::{
call::{
utils::{
EmptyArgumentList,
ReturnType,
Set,
Unset,
},
ExecutionInput,
Selector,
},
types::Environment,
ContractEnv,
};
pub mod state {
}
pub trait FromAddr {
fn from_addr(addr: Address) -> Self;
}
pub trait ConstructorReturnType<C> {
const IS_RESULT: bool = false;
type Output;
type Error: scale::Decode;
fn ok(value: C) -> Self::Output;
fn err(_err: Self::Error) -> Option<Self::Output> {
None
}
}
impl<C> ConstructorReturnType<C> for C
where
C: ContractEnv + FromAddr,
{
type Output = C;
type Error = ();
fn ok(value: C) -> Self::Output {
value
}
}
impl<C, E> ConstructorReturnType<C> for core::result::Result<C, E>
where
C: ContractEnv + FromAddr,
E: scale::Decode,
{
const IS_RESULT: bool = true;
type Output = core::result::Result<C, E>;
type Error = E;
fn ok(value: C) -> Self::Output {
Ok(value)
}
fn err(err: Self::Error) -> Option<Self::Output> {
Some(Err(err))
}
}
#[derive(Clone, Debug)]
pub struct LimitParamsV2 {
ref_time_limit: u64,
proof_size_limit: u64,
storage_deposit_limit: Option<U256>,
}
#[derive(Debug)]
pub struct CreateParams<E, ContractRef, Limits, Args, R> {
code_hash: H256,
limits: Limits,
endowment: U256,
exec_input: ExecutionInput<Args, ScaleEncoding>,
salt_bytes: Option<[u8; 32]>,
_return_type: ReturnType<R>,
_phantom: PhantomData<fn() -> (E, ContractRef)>,
}
impl<E, ContractRef, Limits, Args, R> CreateParams<E, ContractRef, Limits, Args, R>
where
E: Environment,
{
#[inline]
pub fn code_hash(&self) -> &H256 {
&self.code_hash
}
#[inline]
pub fn endowment(&self) -> &U256 {
&self.endowment
}
#[inline]
pub fn exec_input(&self) -> &ExecutionInput<Args, ScaleEncoding> {
&self.exec_input
}
pub fn update_selector(&mut self, selector: Selector) {
self.exec_input.update_selector(selector)
}
}
impl<E, ContractRef, Args, R> CreateParams<E, ContractRef, LimitParamsV2, Args, R>
where
E: Environment,
{
#[inline]
pub fn ref_time_limit(&self) -> u64 {
self.limits.ref_time_limit
}
#[inline]
pub fn proof_size_limit(&self) -> u64 {
self.limits.proof_size_limit
}
#[inline]
pub fn storage_deposit_limit(&self) -> Option<&U256> {
self.limits.storage_deposit_limit.as_ref()
}
}
impl<E, ContractRef, Limits, Args, R> CreateParams<E, ContractRef, Limits, Args, R>
where
E: Environment,
{
#[inline]
pub fn salt_bytes(&self) -> &Option<[u8; 32]> {
&self.salt_bytes
}
}
impl<E, ContractRef, Args, R> CreateParams<E, ContractRef, LimitParamsV2, Args, R>
where
E: Environment,
ContractRef: FromAddr + crate::ContractReverseReference,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractConstructorDecoder,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractMessageDecoder,
Args: AbiEncodeWith<ScaleEncoding>,
R: ConstructorReturnType<ContractRef>,
{
#[inline]
#[cfg(feature = "unstable-hostfn")]
pub fn instantiate(&self) -> <R as ConstructorReturnType<ContractRef>>::Output {
crate::instantiate_contract(self)
.unwrap_or_else(|env_error| {
panic!("Cross-contract instantiation failed with {env_error:?}")
})
.unwrap_or_else(|lang_error| {
panic!("Received a `LangError` while instantiating: {lang_error:?}")
})
}
#[inline]
#[cfg(feature = "unstable-hostfn")]
pub fn try_instantiate(
&self,
) -> Result<
ink_primitives::ConstructorResult<
<R as ConstructorReturnType<ContractRef>>::Output,
>,
Error,
> {
crate::instantiate_contract(self)
}
}
#[derive(Clone)]
pub struct CreateBuilder<E, ContractRef, Limits, Args, RetType>
where
E: Environment,
{
code_hash: H256,
limits: Limits,
endowment: U256,
exec_input: Args,
salt: Option<[u8; 32]>,
return_type: RetType,
_phantom: PhantomData<fn() -> (E, ContractRef)>,
}
#[allow(clippy::type_complexity)]
pub fn build_create<ContractRef>() -> CreateBuilder<
<ContractRef as ContractEnv>::Env,
ContractRef,
Set<LimitParamsV2>,
Unset<ExecutionInput<EmptyArgumentList<ScaleEncoding>, ScaleEncoding>>,
Unset<ReturnType<()>>,
>
where
ContractRef: ContractEnv,
{
CreateBuilder {
code_hash: Default::default(),
limits: Set(LimitParamsV2 {
ref_time_limit: u64::MAX,
proof_size_limit: u64::MAX,
storage_deposit_limit: None,
}),
endowment: Default::default(),
exec_input: Default::default(),
salt: Default::default(),
return_type: Default::default(),
_phantom: Default::default(),
}
}
impl<E, ContractRef, Limits, Args, RetType>
CreateBuilder<E, ContractRef, Limits, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn code_hash(
self,
code_hash: H256,
) -> CreateBuilder<E, ContractRef, Limits, Args, RetType> {
CreateBuilder {
code_hash,
limits: self.limits,
endowment: self.endowment,
exec_input: self.exec_input,
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, Args, RetType>
CreateBuilder<E, ContractRef, Set<LimitParamsV2>, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn ref_time_limit(self, ref_time_limit: u64) -> Self {
CreateBuilder {
limits: Set(LimitParamsV2 {
ref_time_limit,
..self.limits.value()
}),
..self
}
}
#[inline]
pub fn proof_size_limit(self, proof_size_limit: u64) -> Self {
CreateBuilder {
limits: Set(LimitParamsV2 {
proof_size_limit,
..self.limits.value()
}),
..self
}
}
#[inline]
pub fn storage_deposit_limit(self, storage_deposit_limit: U256) -> Self {
CreateBuilder {
limits: Set(LimitParamsV2 {
storage_deposit_limit: Some(storage_deposit_limit),
..self.limits.value()
}),
..self
}
}
}
impl<E, ContractRef, Limits, Args, RetType>
CreateBuilder<E, ContractRef, Limits, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn endowment(
self,
endowment: U256,
) -> CreateBuilder<E, ContractRef, Limits, Args, RetType> {
CreateBuilder {
code_hash: self.code_hash,
limits: self.limits,
endowment,
exec_input: self.exec_input,
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, Limits, RetType, Abi>
CreateBuilder<
E,
ContractRef,
Limits,
Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
RetType,
>
where
E: Environment,
{
#[inline]
pub fn exec_input<Args>(
self,
exec_input: ExecutionInput<Args, Abi>,
) -> CreateBuilder<E, ContractRef, Limits, Set<ExecutionInput<Args, Abi>>, RetType>
{
CreateBuilder {
code_hash: self.code_hash,
limits: self.limits,
endowment: self.endowment,
exec_input: Set(exec_input),
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, Limits, Args, RetType>
CreateBuilder<E, ContractRef, Limits, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn salt_bytes(
self,
salt: Option<[u8; 32]>,
) -> CreateBuilder<E, ContractRef, Limits, Args, RetType> {
CreateBuilder {
code_hash: self.code_hash,
limits: self.limits,
endowment: self.endowment,
exec_input: self.exec_input,
salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, Limits, Args>
CreateBuilder<E, ContractRef, Limits, Args, Unset<ReturnType<()>>>
where
E: Environment,
{
#[inline]
pub fn returns<R>(
self,
) -> CreateBuilder<E, ContractRef, Limits, Args, Set<ReturnType<R>>>
where
ContractRef: FromAddr,
R: ConstructorReturnType<ContractRef>,
{
CreateBuilder {
code_hash: self.code_hash,
limits: self.limits,
endowment: self.endowment,
exec_input: self.exec_input,
salt: self.salt,
return_type: Set(Default::default()),
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, Limits, Args, RetType>
CreateBuilder<
E,
ContractRef,
Set<Limits>,
Set<ExecutionInput<Args, ScaleEncoding>>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
{
#[inline]
pub fn params(self) -> CreateParams<E, ContractRef, Limits, Args, RetType> {
CreateParams {
code_hash: self.code_hash,
limits: self.limits.value(),
endowment: self.endowment,
exec_input: self.exec_input.value(),
salt_bytes: self.salt,
_return_type: Default::default(),
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, Args, RetType>
CreateBuilder<
E,
ContractRef,
Set<LimitParamsV2>,
Set<ExecutionInput<Args, ScaleEncoding>>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
ContractRef: FromAddr + crate::ContractReverseReference,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractConstructorDecoder,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractMessageDecoder,
Args: AbiEncodeWith<ScaleEncoding>,
RetType: ConstructorReturnType<ContractRef>,
{
#[inline]
#[cfg(feature = "unstable-hostfn")]
pub fn instantiate(self) -> <RetType as ConstructorReturnType<ContractRef>>::Output {
self.params().instantiate()
}
#[inline]
#[cfg(feature = "unstable-hostfn")]
pub fn try_instantiate(
self,
) -> Result<
ink_primitives::ConstructorResult<
<RetType as ConstructorReturnType<ContractRef>>::Output,
>,
Error,
> {
self.params().try_instantiate()
}
}