transporter_precompile/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
3#![forbid(unsafe_code)]
4#![warn(rust_2018_idioms)]
5
6use core::marker::PhantomData;
7use domain_runtime_primitives::MultiAccountId;
8use fp_evm::Log;
9use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo};
10use frame_support::traits::OriginTrait;
11use pallet_evm::AddressMapping;
12use pallet_transporter::{BalanceOf, Location};
13use parity_scale_codec::Decode;
14use precompile_utils::prelude::*;
15use precompile_utils::solidity;
16use sp_core::crypto::AccountId32;
17use sp_core::{Get, H160, H256, U256};
18use sp_messenger::messages::ChainId;
19use sp_runtime::traits::Dispatchable;
20
21pub struct TransporterPrecompile<Runtime>(PhantomData<Runtime>);
22
23pub const SELECTOR_LOG_TRANSFER_TO_CONSENSUS: [u8; 32] =
25 keccak256!("TransferToConsensus(address,bytes32,uint256)");
26
27pub fn log_transfer_to_consensus(address: H160, who: H160, receiver: H256, amount: U256) -> Log {
28 log3(
29 address,
30 SELECTOR_LOG_TRANSFER_TO_CONSENSUS,
31 who,
32 receiver,
33 solidity::encode_event_data(amount),
34 )
35}
36
37#[precompile]
38impl<Runtime> TransporterPrecompile<Runtime>
39where
40 Runtime: pallet_evm::Config + pallet_transporter::Config,
41 Runtime::RuntimeCall: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo + Decode,
42 <Runtime as pallet_evm::Config>::AddressMapping: AddressMapping<Runtime::AccountId>,
43 Runtime::RuntimeCall: From<pallet_transporter::Call<Runtime>>,
44 BalanceOf<Runtime>: From<u128> + Into<u128>,
45{
46 #[precompile::public("transfer_to_consensus_v1(bytes32,uint256)")]
47 fn transfer_to_consensus_v1(
48 handle: &mut impl PrecompileHandle,
49 receiver: H256,
50 amount: Convert<U256, u128>,
51 ) -> EvmResult {
52 let amount = amount.converted();
53
54 let event = log_transfer_to_consensus(
55 handle.context().address,
56 handle.context().caller,
57 receiver,
58 amount.into(),
59 );
60 handle.record_log_costs(&[&event])?;
61
62 let receiver = AccountId32::new(receiver.0);
63 let amount: BalanceOf<Runtime> = amount.into();
64
65 let origin = Runtime::RuntimeOrigin::signed(Runtime::AddressMapping::into_account_id(
66 handle.context().caller,
67 ));
68
69 RuntimeHelper::<Runtime>::try_dispatch(
70 handle,
71 origin,
72 pallet_transporter::Call::<Runtime>::transfer {
73 dst_location: Location {
74 chain_id: ChainId::Consensus,
75 account_id: MultiAccountId::AccountId32(receiver.into()),
76 },
77 amount,
78 },
79 0,
81 )?;
82
83 event.record(handle)?;
84
85 Ok(())
86 }
87
88 #[precompile::public("minimum_transfer_amount()")]
89 #[precompile::view]
90 fn minimum_transfer_amount(_handle: &mut impl PrecompileHandle) -> EvmResult<U256> {
91 let min_transfer = <Runtime as pallet_transporter::Config>::MinimumTransfer::get();
92 Ok(U256::from(min_transfer.into()))
93 }
94}