pallet_evm_precompile_crowdloan_rewards/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
20
21use fp_evm::PrecompileHandle;
22use frame_support::{
23 dispatch::{GetDispatchInfo, PostDispatchInfo},
24 traits::Currency,
25};
26use pallet_evm::AddressMapping;
27use parity_scale_codec::EncodeLike;
28use precompile_utils::prelude::*;
29
30use sp_core::{H160, U256};
31use sp_runtime::traits::Dispatchable;
32use sp_std::{
33 convert::{TryFrom, TryInto},
34 fmt::Debug,
35 marker::PhantomData,
36};
37
38#[cfg(test)]
39mod mock;
40#[cfg(test)]
41mod tests;
42
43pub type BalanceOf<Runtime> =
44 <<Runtime as pallet_crowdloan_rewards::Config>::RewardCurrency as Currency<
45 <Runtime as frame_system::Config>::AccountId,
46 >>::Balance;
47
48pub struct CrowdloanRewardsPrecompile<Runtime>(PhantomData<Runtime>);
50
51#[precompile_utils::precompile]
52impl<Runtime> CrowdloanRewardsPrecompile<Runtime>
53where
54 Runtime: pallet_crowdloan_rewards::Config + pallet_evm::Config + frame_system::Config,
55 BalanceOf<Runtime>: TryFrom<U256> + TryInto<u128> + Debug,
56 <Runtime as pallet_crowdloan_rewards::Config>::RewardCurrency:
57 frame_support::traits::Currency<<Runtime as frame_system::pallet::Config>::AccountId>,
58 <Runtime as frame_system::pallet::Config>::RuntimeCall:
59 Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo,
60 <Runtime as frame_system::pallet::Config>::RuntimeCall:
61 From<pallet_crowdloan_rewards::Call<Runtime>>,
62 <Runtime as pallet_evm::Config>::AddressMapping:
63 AddressMapping<<Runtime as frame_system::pallet::Config>::AccountId>,
64 <Runtime as frame_system::Config>::AccountId: From<<Runtime as frame_system::pallet::Config>::AccountId>
65 + Into<<Runtime as frame_system::pallet::Config>::AccountId>
66 + EncodeLike<<Runtime as frame_system::pallet::Config>::AccountId>,
67{
68 #[precompile::public("isContributor(address)")]
70 #[precompile::public("is_contributor(address)")]
71 #[precompile::view]
72 fn is_contributor(handle: &mut impl PrecompileHandle, contributor: Address) -> EvmResult<bool> {
73 handle.record_db_read::<Runtime>(3268)?;
76
77 let contributor: H160 = contributor.into();
78
79 let account = Runtime::AddressMapping::into_account_id(contributor);
80
81 log::trace!(
82 target: "crowdloan-rewards-precompile",
83 "Checking whether {:?} is a contributor",
84 contributor
85 );
86
87 let is_contributor: bool =
89 pallet_crowdloan_rewards::Pallet::<Runtime>::accounts_payable(account.into()).is_some();
90
91 log::trace!(target: "crowldoan-rewards-precompile", "Result from pallet is {:?}", is_contributor);
92
93 Ok(is_contributor)
94 }
95
96 #[precompile::public("rewardInfo(address)")]
97 #[precompile::public("reward_info(address)")]
98 #[precompile::view]
99 fn reward_info(
100 handle: &mut impl PrecompileHandle,
101 contributor: Address,
102 ) -> EvmResult<(U256, U256)> {
103 handle.record_db_read::<Runtime>(3268)?;
106
107 let contributor: H160 = contributor.into();
108
109 let account = Runtime::AddressMapping::into_account_id(contributor);
110
111 log::trace!(
112 target: "crowdloan-rewards-precompile",
113 "Checking reward info for {:?}",
114 contributor
115 );
116
117 let reward_info =
119 pallet_crowdloan_rewards::Pallet::<Runtime>::accounts_payable(account.into());
120
121 let (total, claimed): (U256, U256) = if let Some(reward_info) = reward_info {
122 let total_reward: u128 = reward_info
123 .total_reward
124 .try_into()
125 .map_err(|_| RevertReason::value_is_too_large("balance type"))?;
126 let claimed_reward: u128 = reward_info
127 .claimed_reward
128 .try_into()
129 .map_err(|_| RevertReason::value_is_too_large("balance type"))?;
130
131 (total_reward.into(), claimed_reward.into())
132 } else {
133 (0u128.into(), 0u128.into())
134 };
135
136 log::trace!(
137 target: "crowldoan-rewards-precompile", "Result from pallet is {:?} {:?}",
138 total, claimed
139 );
140
141 Ok((total, claimed))
142 }
143
144 #[precompile::public("claim()")]
145 fn claim(handle: &mut impl PrecompileHandle) -> EvmResult {
146 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
147 let call = pallet_crowdloan_rewards::Call::<Runtime>::claim {};
148
149 RuntimeHelper::<Runtime>::try_dispatch(
150 handle,
151 frame_system::RawOrigin::Signed(origin.into()).into(),
152 call,
153 0,
154 )?;
155
156 Ok(())
157 }
158
159 #[precompile::public("updateRewardAddress(address)")]
160 #[precompile::public("update_reward_address(address)")]
161 fn update_reward_address(
162 handle: &mut impl PrecompileHandle,
163 new_address: Address,
164 ) -> EvmResult {
165 log::trace!(
166 target: "crowdloan-rewards-precompile",
167 "In update_reward_address dispatchable wrapper"
168 );
169
170 let new_address: H160 = new_address.into();
171
172 let new_reward_account = Runtime::AddressMapping::into_account_id(new_address);
173
174 log::trace!(target: "crowdloan-rewards-precompile", "New account is {:?}", new_address);
175
176 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
177 let call = pallet_crowdloan_rewards::Call::<Runtime>::update_reward_address {
178 new_reward_account: new_reward_account.into(),
179 };
180
181 RuntimeHelper::<Runtime>::try_dispatch(
182 handle,
183 frame_system::RawOrigin::Signed(origin.into()).into(),
184 call,
185 0,
186 )?;
187
188 Ok(())
189 }
190}