Understand Transaction Effects

Overview

The Fordefi transaction API provides a standardized way to understand the impact of blockchain transactions on your organization's vaults. To support all transaction types in their full generality, we model a transaction as having any number of "effects" on the organization's vaults. An example of an effect is a token transfer from the organization's vault to another address. For example, a swap transaction contains two transfer effects: one for the amount of tokens sent from the vault to the DEX contract, and one for the amount of tokens received back from the contract. Another example is a transaction that executes an ERC-20 token's approve function. Such a transaction will have a single "allowance" effect.

Use Cases

This is particularly useful in several common scenarios:

  • Maintaining Internal Ledgers: If your application maintains internal account balances (for example, if you're operating a centralized exchange), you need to process both incoming and outgoing blockchain transactions to correctly update your managed balances. Effects provide a reliable way to track these balance changes.
  • Auditing and Reconciliation: Effects enable accurate accounting and reconciliation by providing a standardized view of transaction effects across different chains and transaction types. It thus makes it easy to match on-chain activity with internal records.
  • User-Facing Applications: When building applications that need to present transaction details to end users, the effects help you display clear, human-readable transaction information across different blockchain networks. When simulating transactions, it allows you to show accurate previews of transaction outcomes before they are executed
  • Programmatic Approvals: When using policies that require programmatic approvals, the effects can be used by the approving API User to inspect the transaction and its effects before approving it.

Retrieving Transaction Effects

You can retrieve the effects of a transaction in one of the following ways:

Mined vs Expected

Fordefi captures the effects of a transaction at two points in time. The expected_result field contains the effects of an outgoing transaction as predicted by the Fordefi transaction simulation engine. The mined_result field contains the authoritative effects of the transaction as it was executed on the blockchain. Depending on the type of the transaction and its state, a transaction object contains the expected_result and/or the mined_result. For example, an outgoing transaction will contain the expected_result as soon as its created and the mined_result only after it has been mined on the blockchain. In contrast, an incoming transaction will only contain the mined_result.

Unrelated effects

Fordefi filters out any effects that are not relevant to the organization's vaults. For example, if an airdrop transaction transfers a token to hundreds of addresses, the transaction will only contain those transfers that are relevant to one of the organization's vaults.

Effect Types

The most common effects are:

Balance changes

A balance change effect represents a change in the balance of an asset in the organization's vault. It can be either an increase or a decrease.

The important fields of a balance change effect are:

  • address: the account affected by the balance change. This field contains the on-chain address, as well as additional metadata such as the vault or contact when applicable.
  • priced_asset: the information about the asset that was transferred.
  • diff: the change in the balance of the asset. Can be positive or negative and is denominated in the asset's base units. Use priced_asset.asset_info.decimals to convert the base units into the "natural" units.

Transfers

A transfer effect represents the transfer of an asset, which can be a chain's native asset (e.g., ETH, BTC, etc.), a fungible token (e.g., USDC ERC-20 on Ethereum, USDC SPL token on Solana, etc.), or a non-fungible token (currently only ERC-721 and ERC-1155 on EVM chains).

The important fields of a transfer effect are:

  • from and to: the sender and recipient objects. Each of them contains the on-chain address, as well as additional metadata such as the vault or contact when applicable.
  • priced_asset: the information about the asset being transferred.
  • amount: the amount of the asset that was transferred in base units. (priced_asset.asset_info.decimals is used to convert the base units to the "natural" units.)
Balance changes vs transfers

Whereas a balance change is well defined for every transaction across all chains, deducing the transfer effects is sometimes a heuristic process that can result in incomplete results. When possible, users should prefer using the balance change effects to determine the effects of a transaction on the organization's vaults.

Allowances

An allowance effect is specific to EVM chains and represents the approval of a spender to spend a certain amount of tokens on behalf of the owner. Fordefi supports allowance effects for ERC-20, ERC-721, and ERC-1155 tokens.

The important fields of an allowance effect are:

  • owner: the owner of the token that grants the allowance.
  • spender: the recipient of the allowance.
  • priced_asset: the information about the asset that is being approved.
  • amount: the amount of the asset that was approved.

The owner and spender fields contain the on-chain address and, when applicable, additional metadata such as the vault or contact this address corresponds to. Note that a vault may be on the owner or spender side of the allowance.

Example: an ERC20 transfer

In the special case where a transaction is a simple transfer, the transaction's mined_result.effects.transfers will contain a single effect with the amount of the transfer. You can check whether a transaction is a simple transfer by the <CHAIN_TYPE>_transaction_type_details.type field. For each chain type it will contain the subtype of the transaction. For example, an EVM transaction can have its evm_transaction_type_details.type be native_transfer or token_transfer.

{
   "mined_result":{
      "effects":{
         "balance_changes":[
            {
               "priced_asset":{
                  "type":"asset_price",
                  "asset_info":{
                     "id":"62df5e15-a0e9-43ff-9536-25b5eb1216d2",
                     "asset_identifier":{
                        "type":"evm",
                        "details":{
                           "type":"erc20",
                           "token":{
                              "chain":"evm_mantle_mainnet",
                              "hex_repr":"0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9"
                           }
                        },
                        "chain":{
                           "chain_type":"evm",
                           "chain_id":5000,
                           "unique_id":"evm_mantle_mainnet",
                           "name":"Mantle"
                        }
                     },
                     "name":"USD Coin",
                     "symbol":"USDC",
                     "decimals":6
                  },
                  "price":{
                     "price_float":"100.1",
                     "fiat_currency":{
                        "currency_symbol":"usd",
                        "decimals":2
                     }
                  }
               },
               "diff":"1000000",
               "type":"erc20",
               "address":{
                  "vault":{
                     "id":"6fccc3cb-22a8-4d28-8402-7dc434f7573d",
                     "address":"0x09EC0D8f29074961C4F9624B736EaE98b8473B0e"
                  },
                  "address":"0x09EC0D8f29074961C4F9624B736EaE98b8473B0e"
               }
            }
         ],
         "transfers":[
            {
               "priced_asset":{
                  
               },
               "amount":"1000000",
               "type":"erc20",
               "from":{
                  "address":"0x588846213A30fd36244e0ae0eBB2374516dA836C"
               },
               "to":{
                  "vault":{
                     "id":"6fccc3cb-22a8-4d28-8402-7dc434f7573d",
                     "address":"0x09EC0D8f29074961C4F9624B736EaE98b8473B0e"
                  },
                  "address":"0x09EC0D8f29074961C4F9624B736EaE98b8473B0e"
               }
            }
         ]
      }
   }
}
Why there's no single amount field?

A common pitfall is for users to look for a single "amount" field in the transaction object. However, since a transaction is not necessarily a simple transfer, it does not necessarily have a single well-defined amount. In the general case, you should look at the transaction's effects to determine the amounts of the individual transfer effects.