diff --git a/examples/CRISP/server/src/server/routes/voting.rs b/examples/CRISP/server/src/server/routes/voting.rs index 0484a8097b..a46cd6b378 100644 --- a/examples/CRISP/server/src/server/routes/voting.rs +++ b/examples/CRISP/server/src/server/routes/voting.rs @@ -5,14 +5,16 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use crate::server::{ - CONFIG, app_data::AppData, database::SledDB, models::{ - VoteRequest, VoteResponse, VoteResponseStatus, VoteStatusRequest, VoteStatusResponse - }, repo::CrispE3Repository + app_data::AppData, + database::SledDB, + models::{ + VoteRequest, VoteResponse, VoteResponseStatus, VoteStatusRequest, VoteStatusResponse, + }, + repo::CrispE3Repository, + CONFIG, }; use actix_web::{web, HttpResponse, Responder}; -use alloy::{ - primitives::{Bytes, U256}, -}; +use alloy::primitives::{Bytes, U256}; use e3_sdk::evm_helpers::contracts::{EnclaveContract, EnclaveWrite}; use eyre::Error; use log::{error, info}; diff --git a/examples/CRISP/server/src/server/token_holders/etherscan.rs b/examples/CRISP/server/src/server/token_holders/etherscan.rs index 5a3bcb0a65..1f6c5a3e01 100644 --- a/examples/CRISP/server/src/server/token_holders/etherscan.rs +++ b/examples/CRISP/server/src/server/token_holders/etherscan.rs @@ -20,6 +20,7 @@ sol! { #[sol(rpc)] contract ERC20Votes { function getPastVotes(address account, uint256 timepoint) external view returns (uint256); + function decimals() external view returns (uint8); } } @@ -178,8 +179,8 @@ impl EtherscanClient { } return Err(eyre!( - "Etherscan getLogs failed on page {}: {}", - page, + "Etherscan getLogs failed on page {}: {}", + page, data.message )); } @@ -245,8 +246,8 @@ impl EtherscanClient { } return Err(eyre!( - "Etherscan getLogs failed on page {}: {}", - page, + "Etherscan getLogs failed on page {}: {}", + page, data.message )); } @@ -326,13 +327,22 @@ impl EtherscanClient { ) -> Result> { let mut token_holders: Vec = Vec::new(); + let decimals = Self::get_decimals(token_address, rpc_url).await?; + + // we want to keep some precision. + let half_decimals = decimals / 2; + + let scale_factor = U256::from(10u128.pow(half_decimals as u32)); + for voter in potential_voters { match Self::get_past_votes(token_address, voter.address, block_number, rpc_url).await { Ok(votes) => { if votes >= threshold { + let scaled_votes = votes / scale_factor; + token_holders.push(TokenHolder { address: voter.address.to_string(), - balance: votes.to_string(), + balance: scaled_votes.to_string(), }); } } @@ -452,6 +462,21 @@ impl EtherscanClient { Ok(votes) } + /// Get the token decimals + async fn get_decimals(token_address: Address, rpc_url: &str) -> Result { + let url = rpc_url.parse().context("Failed to parse RPC URL")?; + let provider = ProviderBuilder::new().connect_http(url); + let token = ERC20Votes::new(token_address, provider); + + let decimals = token + .decimals() + .call() + .await + .context("Failed to call decimals")?; + + Ok(decimals) + } + /// Parse address from 32-byte topic (last 20 bytes) fn parse_address_from_topic(topic: &str) -> Result { let hex = topic.strip_prefix("0x").unwrap_or(topic);