Missing transactions in MaticTokenTransfers


It seems that the table MaticTokenTransfers does not contain al transactions that we perform.
I have this code snipped that I used to check this. I calculated the balance of a address by summing up all transactions and then comparing it to the balance from MaticTokenBalance. And it does not add up. Also the balance from MaticTokenBalance seems to be correct, it is the same as the one shown in Metamask.
What seems to be happening is that when we perform multiple transactions in one of our contract methods, then only one of those transaction gets to be recorded in MaticTokenTransfers. Could this really be the case?

We are using on the Matic Mumbai network.

The code we use to check this is below:

  let TokenTransfers = null;
  let queryReceiver = null;
  let querySender = null;
  let query = null;
  let erc20Transactions = null;
  let tokenAddress = "0xb80ac2abc27dcc7695b8c60bc2800e5ee97fea7b";
  let ownerAddress = "0x211773ea847a59ca889424a52835d24f8fdb79b2";

  // Load all transaction send to / from the owner
  TokenTransfers = Moralis.Object.extend("MaticTokenTransfers");
  queryReceiver = new Moralis.Query(TokenTransfers)
    .equalTo("token_address", tokenAddress)
    .equalTo("to_address", ownerAddress);

  querySender = new Moralis.Query(TokenTransfers)
    .equalTo("token_address", tokenAddress)
    .equalTo("from_address", ownerAddress);

  query = Moralis.Query.or(queryReceiver, querySender);
  erc20Transactions = await query.find();

  let balance = web3.utils.toBN("0");

  // Calculate the balance
  erc20Transactions = erc20Transactions.map((t) => {

    let value = web3.utils.toBN(t.get("value"));

    if (t.get("to_address") === ownerAddress) {
      balance = balance.add(value);
    } else {
      balance = balance.sub(value);

    return {
      from_address: t.get("from_address"),
      to_address: t.get("to_address"),
      value: t.get("value"),

  console.log("DEBUG: erc20Transactions: ", erc20Transactions);

  // Now load the balance from the table
  let balanceQuery = await new Moralis.Query("MaticTokenBalance")
    .equalTo("address", ownerAddress).find();

  let otherBalance = balanceQuery[0].get("balance");

   // The 2 values should be equal
  console.log("DEBUG:              calculated balance: ", web3.utils.fromWei(balance.toString(), 'ether'));
  console.log("DEBUG:  balance from MaticTokenBalance: ", web3.utils.fromWei(otherBalance, 'ether'));


You cant always count transactions to deduce the balance.
Some tokens are rebase/deflationare/etc where balance can change in different ways outside of just transactions.

I will check what it could be.

Can you check here and see which transactions are missing from your DB?


if you can paste code for contract that does several transactions that are not picked up that would be great also

but first please see which transactions are missing when you look at Metamas history/Matic explorer and Moralis DB



Yes, these seem to be the transactions in the block explorer:

And only 1 is shown in the DB:

This is the transaction: ( 0x8dad211d847815f0408afef8c440766f96db054aef2ea8a654982417e00b33b3 ):


perfect thanks we will take a look, probably will get back tomorrow

We basically call the mint function of a ERC20 token in a loop.
The relevant code from the smart contract would be the one below. What we invoke is the distributeCO2CreditsToMultipleTrees, which loops and invokes distributeCO2Credits which then calls the mint function:

    function distributeCO2Credits(uint256 _treeId, uint256 _upToTimestamp)
        require(_treeId < treeTokens.length, "Invalid tree ID");
        Tree storage tree = treeTokens[_treeId];
        uint256 lastCO2TokenTimestamp = tree.lastCO2TokenTimestamp;

            lastCO2TokenTimestamp < _upToTimestamp,
            "CO2 tokens for that timespan already minted"

        // Check & timestamps
        TreeBatch storage batch = treeBatches[tree.batchId];
        if (lastCO2TokenTimestamp == 0) {
            lastCO2TokenTimestamp = batch.plantDate;

        tree.lastCO2TokenTimestamp = _upToTimestamp;

        // Calculate and newCO2ToEmit and update amountCO2Claimed
        uint256 co2TokensPerYear = batch.amountCO2AbsorbedPerYear * (10**18);
        uint256 delta = _upToTimestamp - lastCO2TokenTimestamp;
        uint256 newCO2ToEmit =
            (co2TokensPerYear * delta) / MILLISECONDS_IN_YEAR;

        tree.amountCO2Claimed += newCO2ToEmit;

        address owner = ownerOf(_treeId);

        co2.mint(owner, newCO2ToEmit);
        emit CO2Distributed(_treeId, owner, newCO2ToEmit);

    function distributeCO2CreditsToMultipleTrees(uint256[] memory _treeIds, uint256 _upToTimestamp)
        for(uint256 i=0; i < _treeIds.length;i++) {
            distributeCO2Credits(_treeIds[i], _upToTimestamp);

1 Like

@nutrina just to confirm again - TokenBalance for that user and token in Moralis is correct right?

Yes, MaticTokenBalance for that user and token seems to be correct.

1 Like

@nutrina update server to last version and try again

Yes, this seems to work with the latest server version. Only issue I am having is that MaticTokenTransfers has been renamed to PolyonTokenTransfers :smile: . But that is not a big deal.

Is this a fix you did after I reported it? Or have I just missed a server update?