How to Reconcile Transactions to an On-Chain Ending Balance

Subscribe to our NewsletterStake ETH with Confidence

Reconciliations are an ever present ritual for most accountants - we roll up our sleeves, break out the supporting detail and labor over getting all activity to tie out. Reconciliations are a fundamental part of accounting that ensure what we’re recording in the ledger is accurate and makes sense. They’re time consuming enough for traditional companies, but throw crypto into the mix, and you’re looking at an entropic web of transaction hashes, timestamps and spam tokens.  The challenge becomes infinitely greater when you need to reconcile on-chain activity from a few years ago - data sources become as barren as a Martian desert and sometimes you can’t even find an ending balance to reconcile to.

This article will focus on how to reconcile on-chain transactions to a point-in-time balance, specifically for networks in the Cosmos ecosystem since there’s a lack of accounting tooling to support them. Cosmos protocols are rich with accounting engimas such as continuous vesting schedules, task-oriented fairdrops and liquidity providing. Figment supports over 20+ Cosmos networks, so the accounting team needs to reconcile our activity for 2020, 2021 and 2022 - we have ending balance snapshots for 2021 (taken from Mintscan) so the goal is to add up all of our on-chain activity and see where we land against the screenshots we have. Accountants moonlight as pseudo-detectives during this exercise and can discover a wealth of historical information - time to get that magnifying glass out. 🔎

Step 1: Pull the Genesis Json Files & Network Upgrade Files

Especially for early-network participants, it’s critical to analyze the blockchain’s genesis file - this contains key information such as beginning liquid and staked balances of certain accounts, the start time of the first mainnet block and vesting accounts. Accounts can have starting balances for a variety of reasons: incentivized testnet rewards(1) for validators, founding team member grants, airdropped tokens, etc. These balances typically don’t appear on block explorers since they aren’t normal transactions - their substance is baked into block zero and cannot be changed. If you don’t include genesis file transactions, your reconciliation will likely be out of balance, unless you started participating in a given network post-mainnet launch. 

To pull a genesis file, search “{protocol name} blockchain github” and click into the public repo associated with the network. The property of transparency and decentralization really helps out accountants because we have unlimited access to important records - I usually poke around Github or search “genesis.json” until I stumble across a screen that looks like this (pulled from Injective’s file):

Genesis files always include genesis_time and chain_id parameters. A network also might have several genesis files depending on the number of network upgrades - a good example is the Kava blockchain which has nine publicly listed upgrades and associated genesis files.

After identifying the genesis file, I search for the address I’m reconciling for (in the Injective example, Figment’s public address is inj1g4d6dmvnpg7w7yugy6kplndp7jpfmf3k5d9ak9). Several code snippets appear:

Coins refers to our account’s starting liquid balance. Cosmos networks include amounts denominated in micro units, so divide the amount by 10^18 or 10^6 to get the human-readable number (in the top snapshot, we started with 100 INJ (100000000000000000000 / 10^18). The bottom snapshot is applicable for validators as it establishes our validator details such as name, public commission rate and self-delegated amount (9 INJ or 90000000000000000000 / 10^18). 

Genesis files are often the missing puzzle piece for complex reconciliations. The information is usually buried within stacks of Github gibberish so accountants have to become both detectives and defacto programmers. Since these files are tricky to find, this article includes an appendix of Genesis files for most of the Cosmos networks that Figment validates on.

Step 2: Analyze the Airdrop / Fairdrop Dynamics

Several Cosmos networks distribute their initial batch of tokens through airdrops (i.e. the developers take a snapshot of Cosmos addresses that meet certain criteria and airdrop their tokens according to a formula). A good example is the JUNO protocol which implemented a stakedrop:

“A 1:1 stakedrop is allocated to $ATOM stakers, giving the $JUNO genesis supply to staked $ATOM balances that had their assets bonded at the time of the Stargate snapshot on Feb. 18th 6:00 PM UTC. Addresses that qualify are included in the JUNO genesis block at launch.”  Source

Most networks have a straight-forward airdrop that shows up in the genesis files as “address” and “number of tokens.” Other chains, however, have a more complex scheme that isn’t easily recognizable on block explorers or within the genesis files. Osmosis had a task-oriented fairdrop that used the Stargate snapshot in conjunction with the following actions:

For Osmosis reconciliation purposes, accountants have to use the genesis file and data on Mintscan to pull accurate balances. Genesis data includes: 1) Ion airdrop (if applicable)(2), 2) liquid OSMO available and 3) Initial Claimable Amount of OSMO. Only after completing the tasks above (i.e. swapping, staking, liquidity providing and voting) can a user claim the full amount of their OSMO airdrop, with 20% being released after every task.

In the screenshots below, the address was airdropped 1,843.94 liquid OSMO (1843936771 / 10^6) and had 7,375.75 OSMO available to be claimed (since the action_completed array is set to false, the remaining 80% were still locked at mainnet launch). You can verify the subsequent claims by checking the transaction history on Mintscan -  for example, in this transaction, the user is swapping 50,000 IRIS for 849.37 OSMO and unlocking another liquid 1,843.94 OSMO in the process. To see the full details, I recommend checking the JSON logs instead of the data on the UI, since it often pulls in incorrect amounts for more complex activity.

Parsing this early data is crucial for getting on-chain activity to tie out. There also might be different revenue treatments and pricing nuances for these early tokens since pricing for OSMO doesn’t kick in on the decentralized exchange until 6/24/2021 (and mainnet launch was on 6/18/2021).

Step 3: Chain-Specific Anomalies

No two blockchains are alike, even if they both implement the Cosmos SDK standard. Blockchains in the Cosmos family generally have their own purposes such as smart contracts on Juno, NFTs on Stargaze or DeFi on Comdex. Accountants attempting to reconcile transactions have to become protocol researchers since they need to understand the underlying activity to account for it correctly. 

An excellent case study is the Secret network, which espouses “programmable privacy” and Secret smart contracts that encrypt data. Because secrecy is an inherent part of the protocol, transactional data is protected and viewable only by the addresses involved - this renders block explorers useless since transactional data is by design incomplete to public eyes. This impacts accountants since we usually aren’t the holders of a company’s private keys - we are the anonymous public scanning Mintscan to paste together a financial picture. For example, Figment was awarded a grant by the Secret community for development of our Secret Datahub nodes (see our proposal here) - however, this transfer of tokens from the community pool to our public address is nowhere to be found on Mintscan or Secret explorer. Only by verifying balances before and after the expected transfer date (and cross-referencing multiple Slack messages) could we gain comfort over the amount earned. 

Another example of missing data is the Cosmos (ATOM) network, which launched in March 2019. After pulling fully indexed data, we discovered a subset of withdraw_rewards transactions were simply missing - we had screenshots from 2019 confirming our earnings, but the on-chain data was pulling in zero. Early data often isn’t included or is indexed incorrectly so while the tokens are real, there’s barely a trace until the technology sorts itself out. In this case, accountants have to comb through available evidence (i.e. messages, screenshots, old files) to reconstruct history.

Finally, if balances still aren’t reconciling, it’s worth searching for examples of network incentives or grants to find the missing tokens. The Provenance (HASH) blockchain introduced a validator program where they airdropped ~10,000 HASH to validator addresses for a few months in 2022 (the Medium post has been deleted but you can find an archived version here). E-money (NGM) also had a similar setup with 2020 validator grants, which we discovered from a removed commit on Github. Protocols aren’t simple bank accounts - they are dynamically changing ledgers that require some digging to get to a reconciled balance.

Step 4: Vesting Schedules

The Cosmos SDK has a stellar vesting account module that is flexible and well-documented. Vesting accounts come in a few different flavors: base, continuous, periodic and delayed vesting. We’ll dive into periodic and continuous vesting since they are the most common I’ve seen across Cosmos protocols. 

Periodic Vesting

Under this type of account, tokens vest according to pre-defined time intervals. The account includes a start time and end time (in UNIX format), the original vesting amount and vesting periods with a length in seconds and an amount in micro units. The example below can be broken down in the following table:

“Vested tokens” are tokens that have unlocked and are freely available to be sent. Vesting accounts also allow delegations of the locked tokens (the “delegated_free” and “delegated_vesting” parameters). 

Continuous Vesting

Under continuous vesting, tokens are linearly vested every block from start time to end time. The documents include a formula to determine how many tokens are vested per block here.

Step 5: Staking Transactions

There’s a handful of universal staking transactions to be aware of when reconciling validator and delegator accounts:

  • Withdraw_rewards - this transaction is triggered when a user claims staking rewards on their account. For a delegator, this is the total rewards that have accrued on their principal balance since the last time rewards were claimed. For validators, this is the balance on any amount self-staked to validator(s).
  • Withdraw_commission: this transaction type specifically applies to validators. When called, any unclaimed commissions on the validator beneficiary account are swept into the available (liquid) balance on the wallet.
  • Auto-claimed rewards: whenever an account undelegates, redelegates or delegates, any accrued rewards and commissions will automatically be claimed and swept into the available balance. These transactions are often reconciling items because they’re easy to miss - to catch them, navigate to the JSON logs on Mintscan to see if there’s any rewards numbers lurking there.
  • Unjail: this transaction punishes validators for downtime(5). Downtime penalties on Cosmos networks are {.001} * {staked balance before downtime event}.
  • For example, if a validator is self-staking 10 OSMO and gets jailed, .01 OSMO will be subtracted from their account, leaving them with a staked balance of 9.99.

Note: when a Cosmos network upgrades, there’s a possibility that any accrued rewards & commission before the upgrade time will be automatically claimed (i.e. Kava has this feature). This will not be an on-chain transaction that can be referenced but rather a state change update. To calculate the amount claimed, take the difference between the liquid balance before the upgrade and the liquid balance stated in the genesis file for the new version.

Step 6: Pulling It All Together

As this article demonstrates, reconciling on-chain transactions to a point-in-time balance is no easy feat. Accountants must be programmers, researchers, detectives and a dose of crazy to make sense of thousands of incongruous transactions. The benefit of this undertaking is having a razor clear picture of your entity's activity since inception, which is paramount for an audit.

After aggregating all the data, the reconciliation process is fairly simple. I create the following table under an address’ transactions and fill it out with the cleaned data.

If the checks are all zero, then the account is fully reconciled and ready to be imported into a crypto subledger.

Note: for the delegations, I include the staked balance as positive with its corresponding negative value in liquid since staking tokens moves them from a liquid position to a staked one.

Happy reconciling!

Case Study: Osmosis Liquidity Providing

Tracing liquidity providing activity on Osmosis is convoluted so see below for the lifecycle of an LP position:

When an address joins a pool, they contribute a pair of tokens that meet the pool’s ratio criteria (i.e. 50/50). In exchange, the address receives a GAMM(6) token which represents their proportional interest in the pool. The user then locks their GAMM token and starts earning daily rewards in OSMO - these liquid rewards are not visible on Mintscan but can be pulled from stake.tax. The rewards drop into the available balance in the LP wallet and only stop once the user’s position starts unwinding. 

On Osmosis, users can have unlock periods of 1, 7 or 14 days, with the 14 day election earning the most rewards. Once the unlock period is over, the user can exit the pool by forfeiting their GAMM token and getting their original pair (i.e. OSMO/ATOM) back, albeit at slightly different amounts than when they first contributed due to changing prices of the assets in the pool.

For purposes of uploading this activity into a crypto subledger, the following entries can be made:

Mintscan also breaks when displaying IBC-ed tokens and either writes  “UNKNOWN” or a indecipherable IBC code of the underlying token (see swap of 6,000 JUNO below):

In this example, 6,000 JUNO was swapped into 231,263 UST, which has an asset code of ibc/BE1BB42D4BE3C30D50B68D7C41DB4DFCE9678E8EF8C539F6E6A9345048894FCC. A full list of IBC codes can be found here.

Appendix: Genesis Files

Note: these links may change in the future so please double check before using them. If a network has upgraded, be sure to use the genesis file for the network version you’re looking for.

(1) - Incentivized testnet rewards refer to rewards given to validators for running nodes on a blockchain’s testnet and completing tasks outlined by the protocol. These rewards are earned during testnet and distributed upon mainnet launch in block zero.

(2) - Ion is the “secondary native token” on the Osmosis blockchain without any immediate purpose. It has a fixed supply of 21,294 tokens and was airdropped all at once upon Osmosis mainnet launch.

(3) - UNIX timestamp converter here.
(4) - 1 day = 86400 seconds

(5) - Downtime is different from slashing because it’s due to validator performance instead of double-signing a transaction. The penalty is much less severe than a double-signing slash.
(6) - Generalized Automated Market Maker

Stay in Touch

Subscribe to receive Figment and Web 3 ecosystem updates.
Get Updates
Light blue dots