Fetch onchain data with function calls

Monitoring Address Token Balance

Another, similar example, is monitoring the token balance of an address. In this example, we'll use the Uniswap V2 USDC/USDT Pool. In Uniswap V2, the exchange rate of the two tokens is determined by their liquidity in the pool. Because both USDC and USDT are supposed to be $1, their liquidity should be almost the same. Monitoring for this will allow us to catch potential depeg events in either stablecoin.

use Call, PercentageDiff from hexagate;

source pool: address = 0x3041CbD36888bECc7bbCBc0045E3B1f144466f5f;
source usdc: address = 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48;
source usdt: address = 0xdac17f958d2ee523a2206206994597c13d831ec7;

source usdcBalance: integer = Call {
    contract: usdc,
    signature: "function balanceOf(address) returns (uint256)",
    params: tuple(pool)
};

source usdtBalance: integer = Call {
    contract: usdt,
    signature: "function balanceOf(address) returns (uint256)",
    params: tuple(pool)
};

source percentageDiff: integer = PercentageDiff {
    before: usdcBalance,
    after: usdtBalance
};

source threshold: integer = 2; // Up to 2% difference is allowed

rule {
    description: "Uniswap USDC/USDT pool balance differ by more than ${percentageDiff}%",
    condition: percentageDiff <= threshold
};

There are some similarities to the previous example, but also some differences. Let's break them down:


This is pretty similar to the first example, but we are importing different sources, and also declaring more addresses in advance. We will use these addresses next.


USDC and USDT are both ERC20 tokens (which means they are contracts). These contract expose a function called balanceOf, which we can use to fetch the token balance of a specific address.

We can use the Call datasource in Gate to call functions on specific contracts. It receives 3 parameters:

  • The contract address to call

    • We use the USDC and USDT contract addresses, since we need the balance in both tokens of the pool, to compare them

  • The EVM function signature

  • The EVM function parameters

    • We send the pool address in both calls, since we want to fetch the USDC and USDT balances of that address

    • This parameter is a tuple, since some EVM functions can receive more than 1 parameter

In general, using the Call datasource is a common way to fetch onchain data in Gate.


We use another datasource, PercentageDiff, to calculate the difference between the balances, as a percentage. We then create a rule which ensures every block that the difference between both balances is never above 2%.

Last updated