diff --git a/precompiles/tangle-lst/src/lib.rs b/precompiles/tangle-lst/src/lib.rs index 13040864..c5f8de63 100644 --- a/precompiles/tangle-lst/src/lib.rs +++ b/precompiles/tangle-lst/src/lib.rs @@ -53,7 +53,7 @@ type BalanceOf = ::AccountId, >>::Balance; -use pallet_tangle_lst::{PoolId, PoolState, BondExtra}; +use pallet_tangle_lst::{BondExtra, PoolId, PoolState}; use sp_runtime::Perbill; pub struct TangleLstPrecompile(PhantomData); @@ -61,218 +61,282 @@ pub struct TangleLstPrecompile(PhantomData); #[precompile_utils::precompile] impl TangleLstPrecompile where - Runtime: pallet_tangle_lst::Config + pallet_evm::Config, - Runtime::RuntimeCall: Dispatchable + GetDispatchInfo, - ::RuntimeOrigin: From>, - Runtime::RuntimeCall: From>, - BalanceOf: TryFrom + Into + solidity::Codec, - Runtime::AccountId: From, + Runtime: pallet_tangle_lst::Config + pallet_evm::Config, + Runtime::RuntimeCall: Dispatchable + GetDispatchInfo, + ::RuntimeOrigin: From>, + Runtime::RuntimeCall: From>, + BalanceOf: TryFrom + Into + solidity::Codec, + Runtime::AccountId: From, { - #[precompile::public("join(uint256,uint256)")] - fn join(handle: &mut impl PrecompileHandle, amount: U256, pool_id: U256) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let amount: BalanceOf = amount.try_into().map_err(|_| revert("Invalid amount"))?; - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - - let call = pallet_tangle_lst::Call::::join { amount, pool_id }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("bondExtra(uint256,uint8,uint256)")] - fn bond_extra(handle: &mut impl PrecompileHandle, pool_id: U256, extra_type: u8, extra: U256) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - let extra: BalanceOf = extra.try_into().map_err(|_| revert("Invalid extra amount"))?; - - let extra = match extra_type { - 0 => BondExtra::FreeBalance(extra), - 1 => BondExtra::Rewards, - _ => return Err(revert("Invalid extra type")), - }; - - let call = pallet_tangle_lst::Call::::bond_extra { pool_id, extra }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("unbond(bytes32,uint256,uint256)")] - fn unbond(handle: &mut impl PrecompileHandle, member_account: H256, pool_id: U256, unbonding_points: U256) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let member_account = Self::convert_to_account_id(member_account)?; - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - let unbonding_points: BalanceOf = unbonding_points.try_into().map_err(|_| revert("Invalid unbonding points"))?; - - let call = pallet_tangle_lst::Call::::unbond { member_account, pool_id, unbonding_points }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("poolWithdrawUnbonded(uint256,uint32)")] - fn pool_withdraw_unbonded(handle: &mut impl PrecompileHandle, pool_id: U256, num_slashing_spans: u32) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - - let call = pallet_tangle_lst::Call::::pool_withdraw_unbonded { pool_id, num_slashing_spans }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("withdrawUnbonded(bytes32,uint256,uint32)")] - fn withdraw_unbonded(handle: &mut impl PrecompileHandle, member_account: H256, pool_id: U256, num_slashing_spans: u32) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let member_account = Self::convert_to_account_id(member_account)?; - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - - let call = pallet_tangle_lst::Call::::withdraw_unbonded { member_account, pool_id, num_slashing_spans }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("create(uint256,bytes32,bytes32,bytes32)")] - fn create(handle: &mut impl PrecompileHandle, amount: U256, root: H256, nominator: H256, bouncer: H256) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let amount: BalanceOf = amount.try_into().map_err(|_| revert("Invalid amount"))?; - let root = Self::convert_to_account_id(root)?; - let nominator = Self::convert_to_account_id(nominator)?; - let bouncer = Self::convert_to_account_id(bouncer)?; - - let call = pallet_tangle_lst::Call::::create { amount, root, nominator, bouncer }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("createWithPoolId(uint256,bytes32,bytes32,bytes32,uint256)")] - fn create_with_pool_id(handle: &mut impl PrecompileHandle, amount: U256, root: H256, nominator: H256, bouncer: H256, pool_id: U256) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let amount: BalanceOf = amount.try_into().map_err(|_| revert("Invalid amount"))?; - let root = Self::convert_to_account_id(root)?; - let nominator = Self::convert_to_account_id(nominator)?; - let bouncer = Self::convert_to_account_id(bouncer)?; - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - - let call = pallet_tangle_lst::Call::::create_with_pool_id { amount, root, nominator, bouncer, pool_id }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("nominate(uint256,bytes32[])")] - fn nominate(handle: &mut impl PrecompileHandle, pool_id: U256, validators: Vec) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - let validators: Vec = validators.into_iter().map(Self::convert_to_account_id).collect::>()?; - - let call = pallet_tangle_lst::Call::::nominate { pool_id, validators }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("setState(uint256,uint8)")] - fn set_state(handle: &mut impl PrecompileHandle, pool_id: U256, state: u8) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - let state = match state { - 0 => PoolState::Open, - 1 => PoolState::Blocked, - 2 => PoolState::Destroying, - _ => return Err(revert("Invalid state")), - }; - - let call = pallet_tangle_lst::Call::::set_state { pool_id, state }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("setMetadata(uint256,bytes)")] - fn set_metadata(handle: &mut impl PrecompileHandle, pool_id: U256, metadata: Vec) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); - - let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; - - let call = pallet_tangle_lst::Call::::set_metadata { pool_id, metadata }; - - RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; - - Ok(()) - } - - #[precompile::public("setConfigs(uint256,uint256,uint32,uint32)")] - fn set_configs( - handle: &mut impl PrecompileHandle, - min_join_bond: U256, - min_create_bond: U256, - max_pools: u32, - global_max_commission: u32, - ) -> EvmResult { - handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - ensure_root(handle)?; - - let min_join_bond: Option> = if min_join_bond == U256::zero() { - None - } else { - Some(min_join_bond.try_into().map_err(|_| revert("Invalid min join bond"))?) - }; - - let min_create_bond: Option> = if min_create_bond == U256::zero() { - None - } else { - Some(min_create_bond.try_into().map_err(|_| revert("Invalid min create bond"))?) - }; - - let max_pools = if max_pools == 0 { None } else { Some(max_pools) }; - - let global_max_commission = if global_max_commission == 0 { - None - } else { - Some(Perbill::from_percent(global_max_commission)) - }; - - let call = pallet_tangle_lst::Call::::set_configs { - min_join_bond: min_join_bond.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), - min_create_bond: min_create_bond.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), - max_pools: max_pools.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), - global_max_commission: global_max_commission.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), - }; - - RuntimeHelper::::try_dispatch(handle, RawOrigin::Root.into(), call)?; - - Ok(()) - } + #[precompile::public("join(uint256,uint256)")] + fn join(handle: &mut impl PrecompileHandle, amount: U256, pool_id: U256) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let amount: BalanceOf = amount.try_into().map_err(|_| revert("Invalid amount"))?; + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + + let call = pallet_tangle_lst::Call::::join { amount, pool_id }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("bondExtra(uint256,uint8,uint256)")] + fn bond_extra( + handle: &mut impl PrecompileHandle, + pool_id: U256, + extra_type: u8, + extra: U256, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + let extra: BalanceOf = + extra.try_into().map_err(|_| revert("Invalid extra amount"))?; + + let extra = match extra_type { + 0 => BondExtra::FreeBalance(extra), + 1 => BondExtra::Rewards, + _ => return Err(revert("Invalid extra type")), + }; + + let call = pallet_tangle_lst::Call::::bond_extra { pool_id, extra }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("unbond(bytes32,uint256,uint256)")] + fn unbond( + handle: &mut impl PrecompileHandle, + member_account: H256, + pool_id: U256, + unbonding_points: U256, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let member_account = Self::convert_to_account_id(member_account)?; + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + let unbonding_points: BalanceOf = + unbonding_points.try_into().map_err(|_| revert("Invalid unbonding points"))?; + + let call = pallet_tangle_lst::Call::::unbond { + member_account, + pool_id, + unbonding_points, + }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("poolWithdrawUnbonded(uint256,uint32)")] + fn pool_withdraw_unbonded( + handle: &mut impl PrecompileHandle, + pool_id: U256, + num_slashing_spans: u32, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + + let call = pallet_tangle_lst::Call::::pool_withdraw_unbonded { + pool_id, + num_slashing_spans, + }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("withdrawUnbonded(bytes32,uint256,uint32)")] + fn withdraw_unbonded( + handle: &mut impl PrecompileHandle, + member_account: H256, + pool_id: U256, + num_slashing_spans: u32, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let member_account = Self::convert_to_account_id(member_account)?; + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + + let call = pallet_tangle_lst::Call::::withdraw_unbonded { + member_account, + pool_id, + num_slashing_spans, + }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("create(uint256,bytes32,bytes32,bytes32)")] + fn create( + handle: &mut impl PrecompileHandle, + amount: U256, + root: H256, + nominator: H256, + bouncer: H256, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let amount: BalanceOf = amount.try_into().map_err(|_| revert("Invalid amount"))?; + let root = Self::convert_to_account_id(root)?; + let nominator = Self::convert_to_account_id(nominator)?; + let bouncer = Self::convert_to_account_id(bouncer)?; + + let call = pallet_tangle_lst::Call::::create { amount, root, nominator, bouncer }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("createWithPoolId(uint256,bytes32,bytes32,bytes32,uint256)")] + fn create_with_pool_id( + handle: &mut impl PrecompileHandle, + amount: U256, + root: H256, + nominator: H256, + bouncer: H256, + pool_id: U256, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let amount: BalanceOf = amount.try_into().map_err(|_| revert("Invalid amount"))?; + let root = Self::convert_to_account_id(root)?; + let nominator = Self::convert_to_account_id(nominator)?; + let bouncer = Self::convert_to_account_id(bouncer)?; + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + + let call = pallet_tangle_lst::Call::::create_with_pool_id { + amount, + root, + nominator, + bouncer, + pool_id, + }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("nominate(uint256,bytes32[])")] + fn nominate( + handle: &mut impl PrecompileHandle, + pool_id: U256, + validators: Vec, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + let validators: Vec = validators + .into_iter() + .map(Self::convert_to_account_id) + .collect::>()?; + + let call = pallet_tangle_lst::Call::::nominate { pool_id, validators }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("setState(uint256,uint8)")] + fn set_state(handle: &mut impl PrecompileHandle, pool_id: U256, state: u8) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + let state = match state { + 0 => PoolState::Open, + 1 => PoolState::Blocked, + 2 => PoolState::Destroying, + _ => return Err(revert("Invalid state")), + }; + + let call = pallet_tangle_lst::Call::::set_state { pool_id, state }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("setMetadata(uint256,bytes)")] + fn set_metadata( + handle: &mut impl PrecompileHandle, + pool_id: U256, + metadata: Vec, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + let origin = Runtime::AddressMapping::into_account_id(handle.context().caller); + + let pool_id: PoolId = pool_id.try_into().map_err(|_| revert("Invalid pool id"))?; + + let call = pallet_tangle_lst::Call::::set_metadata { pool_id, metadata }; + + RuntimeHelper::::try_dispatch(handle, Some(origin).into(), call)?; + + Ok(()) + } + + #[precompile::public("setConfigs(uint256,uint256,uint32,uint32)")] + fn set_configs( + handle: &mut impl PrecompileHandle, + min_join_bond: U256, + min_create_bond: U256, + max_pools: u32, + global_max_commission: u32, + ) -> EvmResult { + handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; + ensure_root(handle)?; + + let min_join_bond: Option> = if min_join_bond == U256::zero() { + None + } else { + Some(min_join_bond.try_into().map_err(|_| revert("Invalid min join bond"))?) + }; + + let min_create_bond: Option> = if min_create_bond == U256::zero() { + None + } else { + Some(min_create_bond.try_into().map_err(|_| revert("Invalid min create bond"))?) + }; + + let max_pools = if max_pools == 0 { None } else { Some(max_pools) }; + + let global_max_commission = if global_max_commission == 0 { + None + } else { + Some(Perbill::from_percent(global_max_commission)) + }; + + let call = pallet_tangle_lst::Call::::set_configs { + min_join_bond: min_join_bond.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), + min_create_bond: min_create_bond.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), + max_pools: max_pools.map(ConfigOp::Set).unwrap_or(ConfigOp::Noop), + global_max_commission: global_max_commission + .map(ConfigOp::Set) + .unwrap_or(ConfigOp::Noop), + }; + + RuntimeHelper::::try_dispatch(handle, RawOrigin::Root.into(), call)?; + + Ok(()) + } }