SPARTAv2 (Token) Fee Burn

As most of us are now aware; Spartan Protocol deployed a new v2 SPARTA token on BSC mainnet following the drain on the v1 pools. Whilst the exploit in the v1 pools was not related to this base contract; the event raised the opportunity to:

  • Remove some functions that are no longer required from the burnForSparta distribution period
  • Allow some of the remaining distribution supply to be claimed by those who were affected by the recent exploit
  • Add in long-term deflationary aspects to counter the short-term expedited distributed supply

Removal of ‘BurnForSparta’ Functions

Spartan Protocol’s initial fair distribution involved bringing along BNB and selected BEP20 tokens and burning them in exchange for SPARTA.

This distribution program is now over and has left behind some functions which are no longer required. Those have been left out of the new V2 token contract to leave us with something less complex.

Upgrade & Claim SPARTA v2

The deployment of the V2 token contract enabled users to upgrade their V1 tokens to V2. With it an allocated fund for affected users to claim from, please see more in this article:

Deflationary — feeBurn on Transfer

With the proposal to use some of the SPARTA remaining from the bond distribution to make LPers partial again, came concerns including expedited short-term inflation and/or dumping on market.

Most of the raised concerns are relevant even without the claim of SPARTA being allocated to those affected. Out-of-the-box thinking will be required ongoing to move forward with bringing more utility to the token within the V2 protocol ecosystem.

On the base level; we were able to implement a simple deflationary mechanism within the existing internal _transfer() function. This article is a bit of an explainer on how that works and how it will affect users and the overall tokenomics.

The modified _transfer() function

feeBurn in _transfer()

With the SPARTAv2 token, any wallet, user or contract performing a standard transfer of SPARTAv2 tokens will have a small portion of that transfer burnt out of the supply along the way.

The feeBurn has been in action since the first SPARTAv2 token transfer. It starts at 0% and grows/shrinks with the token’s total supply. The feeBurn is set to be 1% *if* the token’s total supply is at the max (300M) however the max supply is programmatically impossible to reach.

When any standard transfer event takes place, the feeBurn will apply, which essentially means whenever SPARTA tokens move from one wallet/contract to another. The only transfer events excluded are when SPARTA is minted.


This feeBurn adds deflationary pressure to counteract the emissions curve. What we will likely see is a push/pull at some point in the supply where the feeBurn is having a tug-of-war with the daily emissions and holding the supply in a fairly consistent band.

As the supply increases, the feeBurn gets more aggressive and the daily emissions get less aggressive. This will mean that SPARTA gets more deflationary as the supply increases and time goes on.

Note: If v1 had this deflationary function in place, we could estimate a rough ~2,600,000 SPARTA would have been burnt out of the total supply by now based on the transfer count * avg transfer amount plugged into the calculation of the feeBurn using half of the supply as the totalSupply figure

SPARTA v1 Token Transfer Details thanks to

Function Broken Down

The following is a more detailed breakdown of each line of the functions involved in the feeBurn. For the sake of examples; let’s assume the user is transferring 100 SPARTA and the totalSupply is currently 100m.

Step 1:

Checks that the sender of the transfer is not 0x0000000000000000000000000000000000000000. This will ensure that the feeBurn does not apply when SPARTA is being minted into the supply.

Check — Do not apply the feeBurn to SPARTA token minting events

Note: The BASE._mint() function will still emit a ‘Transfer’ event however it handles the transfer inside itself and does not use the BASE._transfer() function.

Internal _mint() function emitting a ‘Transfer’ event

Step 2:

Checks that the recipient is not the SPARTA token contract. Numerous Spartans accidentally sent their precious SPARTA to the base contract in V1. This new user-safety check will prevent users from accidentally sending SPARTAv2 tokens to the SPARTAv2 token contract.

User safety check — Do not allow users to accidentally send SPARTA to the base contract
List of users who accidentally sent SPARTAv1 to the base token contract

Step 3:

Gets the sender’s total balance of SPARTA, and checks that their balance is greater than the amount they are attempting to transfer. Self-explanatory.

Ensure the sender’s balance has enough SPARTA to perform the transfer

Step 4a:

Calls UTILS.calcPart() to calculate the feeBurn amount.

feeOnTransfer & the transfer amount being handed to UTILS.calcPart()

Before we go there, however, we need to explore the value of the BASE.feeOnTransfer storage which is handed to UTILS.calcPart(feeOnTransfer, amount)

BASE.feeOnTransfer is calculated using UTILS.getFeeOnTransfer() which is called via BASE._checkEmission() after every BASE._transfer()

Step 4b:

Let’s start with the relevant section of BASE._checkEmission() where the BASE.feeOnTransfer storage is updated.

Here we perform a simple calculation for BASE.feeOnTransfer using the BASE.totalSupply & BASE.maxSupply

We will use 100M total supply as the example for the remainder of this breakdown resulting in a BASE.feeOnTransfer value of 33.333333333

share = (amount * part) / total;feeOnTransfer = (100 * totalSupply) / maxSupply
maxSupply = 300m
totalSupply = 100m (as an example)
feeOnTransfer = 33.333333333

Note: UTILS.getFeeOnTransfer() can be swapped out by the DAO in the future by swapping out the UTILS contract; so the 100 basis points could theoretically be increased or decreased (or changed to ‘0’ to disable feeBurn)

However as highlighted below; BASE.feeOnTransfer is hard coded in the base token contract to be capped at 500 basis points (5%) to prevent a flawed or rogue UTILS contract performing an undesired burn amount in the future.

Step 4c:

Now that we understand the BASE.feeOnTransfer value; we can continue with step 4a where we call UTILS.calcPart(feeOnTransfer, amount)

UTILS.calcPart(feeOnTransfer, amount) ensures the basis point value is valid and then hands it to UTILS.calcShare(feeOnTransfer, 10000, amount)

Using our example values will result in this output:

share = (amount * part) / total;feeBurn = (transferAmount * feeOnTransfer) / 10000transferAmount = 100 SPARTA
feeOnTransfer = 33.33333333 (from previous example)
feeBurn (_fee) = 0.333333 SPARTA

Step 5:

Back to the BASE._transfer() function. Here we check if the feeBurn value (_fee) is valid and perform the burn.

The BASE._burn(sender, _fee) function does its checks and then removes the feeBurn (_fee) amount from the users' balance and also from BASE.totalSupply and emits a ‘Transfer’ event.

Step 6:

The transfer function then adjusts the two users’ balances & emits the ‘Transfer’ event.

Step 7:

Run BASE.checkEmission() to update the BASE.feeOnTransfer storage value ready for the next Transfer.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store



Incentivized liquidity and synthetic asset generation for Binance Smart Chain.