Skip to content

[Bug] the multicall function keep returuning a unit type #617

@somethinganything254-ops

Description

Component

op-alloy

What version of op-alloy are you on?

1.1.3

Operating System

Linux

Describe the bug

whenever i try to parse the result from the multicall.aggregate function the result ends up being a unit type and i cant work with it // src/reserves.rs — FIXED FOR ALLOY v1.1.3 (Raw .call() + Manual Decode)
use alloy::primitives::{Address, U256, Bytes};
use alloy::providers::{Provider, MulticallBuilder};
use alloy::sol;
use eyre::Result;
use std::collections::{HashMap, HashSet};
use alloy::primitives::address;

sol! {
#[sol(rpc)]
#[allow(missing_docs)]
#[derive(Debug)]
contract IUniswapV2Pair {
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}
}

pub type ReserveCache = HashMap<Address, (U256, U256)>;

pub async fn update_reserves

(provider: &P) -> Result
where
P: Provider + Send + Sync + Clone + 'static,
{
// Collect all unique pairs from your triangles
let mut unique_pairs = HashSet::new();
for tri in crate::config::TOP_20_TRIANGLES {
unique_pairs.insert(tri.pair_ab);
unique_pairs.insert(tri.pair_bc);
unique_pairs.insert(tri.pair_ca);
}
let pairs: Vec

= unique_pairs.into_iter().collect();

// Start MulticallBuilder
let mut mc = provider.multicall();

// Add one getReserves() call per pair — fully type-safe
for &pair in &pairs {
    let contract = IUniswapV2Pair::new(pair, provider.clone());  // Clone fixes lifetime
        mc.add(contract.getReserves());  // .add() for SolCall
}   

// FIXED: Use .call() for raw Bytes (avoids getReservesReturn type mismatch)
let results: Vec<Bytes> = mc.aggregate().await?;

// FIXED: Manual decode from Bytes (no tuple unpacking issues)
let mut reserves = ReserveCache::with_capacity(pairs.len());
for (i, result) in results.into_iter().enumerate() {
    if result.len() < 64 { continue; }  // Skip failed/empty calls
    let r0 = U256::from_be_slice(&result[0..32]);  // reserve0 (u112 padded to 32 bytes)
    let r1 = U256::from_be_slice(&result[32..64]); // reserve1
    // Skip timestamp (64..96)
    reserves.insert(pairs[i], (r0, r1));
}

Ok(reserves)

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions