Skip to content

Commit 714bcd1

Browse files
committed
Merge remote-tracking branch 'origin/main' into devnet-ready
2 parents a3a91ee + f95810a commit 714bcd1

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

runtime/src/precompiles/mod.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,100 @@ pub fn get_single_u8(data: &[u8], index: usize) -> Result<u8, PrecompileFailure>
255255
})
256256
}
257257
}
258+
259+
pub fn get_pubkey(data: &[u8]) -> Result<(AccountId32, vec::Vec<u8>), PrecompileFailure> {
260+
let mut pubkey = [0u8; 32];
261+
pubkey.copy_from_slice(get_slice(data, 0, 32)?);
262+
263+
Ok((
264+
pubkey.into(),
265+
data.get(32..)
266+
.map_or_else(vec::Vec::new, |slice| slice.to_vec()),
267+
))
268+
}
269+
270+
fn parse_netuid(data: &[u8], offset: usize) -> Result<u16, PrecompileFailure> {
271+
if data.len() < offset + 2 {
272+
return Err(PrecompileFailure::Error {
273+
exit_status: ExitError::InvalidRange,
274+
});
275+
}
276+
277+
let mut netuid_bytes = [0u8; 2];
278+
netuid_bytes.copy_from_slice(get_slice(data, offset, offset + 2)?);
279+
let netuid: u16 = netuid_bytes[1] as u16 | ((netuid_bytes[0] as u16) << 8u16);
280+
281+
Ok(netuid)
282+
}
283+
284+
fn contract_to_origin(contract: &[u8; 32]) -> Result<RawOrigin<AccountId32>, PrecompileFailure> {
285+
let (account_id, _) = get_pubkey(contract)?;
286+
Ok(RawOrigin::Signed(account_id))
287+
}
288+
289+
/// Dispatches a runtime call, but also checks and records the gas costs.
290+
fn try_dispatch_runtime_call(
291+
handle: &mut impl PrecompileHandle,
292+
call: impl Into<RuntimeCall>,
293+
origin: RawOrigin<AccountId32>,
294+
) -> PrecompileResult {
295+
let call = Into::<RuntimeCall>::into(call);
296+
let info = call.get_dispatch_info();
297+
298+
let target_gas = handle.gas_limit();
299+
if let Some(gas) = target_gas {
300+
let valid_weight =
301+
<Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(gas, false).ref_time();
302+
if info.weight.ref_time() > valid_weight {
303+
return Err(PrecompileFailure::Error {
304+
exit_status: ExitError::OutOfGas,
305+
});
306+
}
307+
}
308+
309+
handle.record_external_cost(
310+
Some(info.weight.ref_time()),
311+
Some(info.weight.proof_size()),
312+
None,
313+
)?;
314+
315+
match call.dispatch(origin.into()) {
316+
Ok(post_info) => {
317+
if post_info.pays_fee(&info) == Pays::Yes {
318+
let actual_weight = post_info.actual_weight.unwrap_or(info.weight);
319+
let cost =
320+
<Runtime as pallet_evm::Config>::GasWeightMapping::weight_to_gas(actual_weight);
321+
handle.record_cost(cost)?;
322+
323+
handle.refund_external_cost(
324+
Some(
325+
info.weight
326+
.ref_time()
327+
.saturating_sub(actual_weight.ref_time()),
328+
),
329+
Some(
330+
info.weight
331+
.proof_size()
332+
.saturating_sub(actual_weight.proof_size()),
333+
),
334+
);
335+
}
336+
337+
log::info!("Dispatch succeeded. Post info: {:?}", post_info);
338+
339+
Ok(PrecompileOutput {
340+
exit_status: ExitSucceed::Returned,
341+
output: Default::default(),
342+
})
343+
}
344+
Err(e) => {
345+
log::error!("Dispatch failed. Error: {:?}", e);
346+
log::warn!("Returning error PrecompileFailure::Error");
347+
Err(PrecompileFailure::Error {
348+
exit_status: ExitError::Other(
349+
format!("dispatch execution failed: {}", <&'static str>::from(e)).into(),
350+
),
351+
})
352+
}
353+
}
354+
}

0 commit comments

Comments
 (0)