df_hyperliquid_core/client/evm/precompiles/
read.rs1use crate::client::Http;
5use crate::client::evm::abi::AbiError;
6use crate::client::evm::precompiles::table::address;
7use crate::client::evm::rpc::{BlockTag, CallRequest, Rpc, RpcError};
8use crate::client::evm::u256::{B256, U256};
9use crate::utils::Address;
10
11#[derive(Debug, Clone)]
13pub struct Read<T> {
14 pub at: Address,
15 pub data: Vec<u8>,
16 decode: fn(&[u8]) -> Result<T, AbiError>,
17}
18
19impl<T> Read<T> {
20 #[must_use]
22 pub fn request(&self) -> CallRequest {
23 CallRequest::to(self.at, self.data.clone())
24 }
25
26 pub fn decode(&self, answer: &[u8]) -> Result<T, AbiError> {
28 (self.decode)(answer)
29 }
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
33pub enum ReadError {
34 #[error(transparent)]
35 Rpc(#[from] RpcError),
36 #[error("the precompile's answer does not fit its struct: {0}")]
37 Abi(#[from] AbiError),
38}
39
40impl<H: Http> Rpc<H> {
41 pub async fn read<T>(&self, read: &Read<T>) -> Result<T, ReadError> {
43 let answer = self.call(&read.request(), BlockTag::Latest).await?;
44 Ok(read.decode(&answer)?)
45 }
46}
47
48pub(super) enum Arg {
51 Address(Address),
52 Uint(u64),
53}
54
55pub(super) fn read<T>(at: u16, args: &[Arg], decode: fn(&[u8]) -> Result<T, AbiError>) -> Read<T> {
56 let mut data = Vec::with_capacity(args.len() * 32);
57 for arg in args {
58 let word = match arg {
59 Arg::Address(address) => B256::from_address(*address).0,
60 Arg::Uint(value) => U256::from_u64(*value).to_be_bytes(),
61 };
62 data.extend_from_slice(&word);
63 }
64 Read { at: address(at), data, decode }
65}