Sunday, 23 February 2025

How to create Deflationary Token?

Learn how to create a deflationary token step-by-step. Understand tokenomics, smart contracts, and blockchain integration. Perfect for beginners and experts. Boost your crypto project today!

How to create Deflationary Token?

In recent years, the use of blockchain technology has become more and more popular. One of the most popular uses of blockchain technology is the creation of cryptocurrencies. However, cryptocurrencies have an inflation problem as the number of tokens in circulation increases over time.

Deflationary tokens were introduced to address this issue. The supply of these tokens will decrease over time, reducing the total amount of tokens in circulation. This article describes how to code a deflationary token smart contract on the Remix platform.

Setting Up the Environment

How to set up the environment for coding a smart contract for a deflationary token in the Remix platform?

Step 1: Install a Web3 Provider Extension To use Remix with the Ethereum blockchain, we need to have a Web3 provider extension installed on our browser. There are several Web3 provider extensions available, such as MetaMask, Nifty Wallet, and Brave browser’s built-in Crypto Wallet. 

I recommend using MetaMask, which is a popular and widely-used Web3 provider extension. To install MetaMask, go to Metamask and follow the instructions to install the extension on your browser.

Step 2: Connect MetaMask to the Ethereum Network Once MetaMask is installed, we need to connect it to the Ethereum network. Open MetaMask and click on the network dropdown on the top left corner. Select “Main Ethereum Network” or any other Ethereum network you want to use.

Step 3: Fund Your Account To deploy and test our smart contract, we need to have some Ether in our MetaMask account. Ether is the native cryptocurrency of the Ethereum network and is used to pay for gas fees when deploying and interacting with smart contracts. 

To fund your account, click on the MetaMask icon on your browser toolbar, click on “Deposit” or “Buy” and follow the instructions to purchase Ether or send Ether from another wallet to your MetaMask account.

Step 4: Open Remix With MetaMask installed and connected to the Ethereum network, we can now open the Remix platform. Go to Remix and you will be greeted with the Remix IDE.

Step 5: Create a New File. In Remix, click on the “New File” button on the left-hand side of the screen. This will create a new file where we can write our smart contract code.

Step 6: Select the Solidity Compiler Version In Remix, click on the “Solidity” dropdown on the left-hand side of the screen and select the version of the Solidity compiler you want to use. For this tutorial, we will use Solidity 0.8.9.

Step 7: Write the Smart Contract Code Now that we have set up the environment, we can start writing the code for our deflationary token smart contract.

Creating the Token Contract

Add basic structure of the contract, the variables and functions needed to implement the token’s deflationary mechanism, and the events required to track token transfers.

Step 1: Defining the Contract: To create a smart contract for a deflationary token, we need to define the contract in Solidity. In Remix, create a new file and name it “SafeSunToken.sol” or yourname.sol. At the top of the file, we need to define the version of Solidity we are using, as well as the name and symbol of our token.

pragma solidity 0.8.9;

contract SafeSunToken

{

string public name = "Safe Sun Token";

string public symbol = "SST";

}

In the above code, we have defined our contract as “SafeSunToken” and given it a name of “Safe Sun Token” and a symbol of “SST”. The “public” keyword before the name and symbol variables makes them accessible from outside the contract.

Step 2: Defining the Variables: The next step is to define the variables needed for our deflationary mechanism. We need to keep track of the total supply of tokens, as well as the balance of each account that holds our token.

uint256 private _totalSupply;

mapping(address => uint256) private _balances;

In the above code, we have defined a private variable called _totalSupply to store the total supply of tokens. We have also defined a private mapping called _balances to keep track of the balance of each account that holds our token. The address type represents the Ethereum address of an account, and the uint256 type represents an unsigned integer of 256 bits.

Step 3: Defining the Events: To track token transfers, we need to define two events: “Transfer” and “Approval”

event Transfer(address indexed from, address indexed to, uint256 value);

event Approval(address indexed owner, address indexed spender, uint256 value);

The Transfer event is emitted whenever tokens are transferred from one account to another. The Approval event is emitted whenever an account approves another account to spend a certain amount of tokens on its behalf. The indexed keyword before the from, to, owner, and spender variables allows these variables to be searchable in the Ethereum event logs.

Step 4: Defining the Constructor: The constructor is a special function that is executed only once when the contract is deployed. In the constructor, we initialize the total supply of tokens and assign all of them to the contract owner’s account.

constructor(uint256 initialSupply)

{

_totalSupply = initialSupply;

_balances[msg.sender] = initialSupply;

emit Transfer(address(0), msg.sender, initialSupply);}

In the above code, we have defined a constructor that takes an initialSupply parameter. The _totalSupply variable is set to the initial supply, and the _balances mapping is updated to reflect that the contract owner’s account holds all of the initial supply.

Finally, we emit a Transfer event with a from address of 0 (which represents the token contract itself) and a to address of the contract owner’s address, indicating that the entire initial supply has been transferred to the owner’s account.

Step 5: Implementing the Deflationary Mechanism: To implement the deflationary mechanism, we need to define a function that will burn a certain percentage of tokens every time a transfer occurs.

function _burn(uint256 amount) internal

{

uint256 burnAmount = amount / 100; // 1% burn rate

_totalSupply -= burnAmount;

_balances[address(0)] += burnAmount;

emit Transfer(msg.sender, address(0), burnAmount);

}

In the above code, we have defined an internal function called _burn that takes an amount parameter. We have set the burn rate to 1%, which means that 1% of the tokens will be burned every time a transfer occurs.

The internal keyword before the function name means that it can only be called from within the contract.

The _totalSupply variable is updated to reflect the burned tokens, and the _balances mapping for the burn address (0x0000000000000000000000000000000000000000) is updated to reflect the burned tokens being removed from circulation.

Finally, we emit a Transfer event with a from address of the sender’s address and a to address of the burn address, indicating that the burned tokens have been transferred to the burn address.

Step 6: Implementing the Transfer Function: The transfer function is used to transfer tokens from one account to another. We need to modify this function to include the deflationary mechanism.

function transfer(address recipient, uint256 amount)

public returns (bool)

{

require(_balances[msg.sender] >= amount, "Insufficient balance");

_balances[msg.sender] -= amount;

_balances[recipient] += amount;

_burn(amount);

emit Transfer(msg.sender, recipient, amount);

return true;

}

In the above code, we have modified the transfer function to include the _burn function, which burns a certain percentage of tokens every time a transfer occurs. Before transferring the tokens, we check that the sender’s account has a sufficient balance.

The sender’s balance is updated to reflect the transfer, and the recipient’s balance is updated accordingly.

The _burn function is called to burn a percentage of the transferred tokens. Finally, we emit a Transfer event with a from address of the sender’s address and a to address of the recipient’s address, indicating that the tokens have been transferred.

Step 7: Implementing the Approval Function: The approval function is used to approve another account to spend a certain amount of tokens on behalf of the calling account.

function approve(address spender, uint256 amount)

public returns (bool)

{

_allowances[msg.sender][spender] = amount;

emit Approval(msg.sender, spender, amount);

return true;

}

In the above code, we have defined the approve function, which approves another account to spend a certain amount of tokens on behalf of the calling account. The _allowances mapping is updated to reflect the approved amount, and an Approval event is emitted.

Step 8: Implementing the Transfer From Function: The transfer from function is used to transfer tokens from one account to another on behalf of a third account that has been approved to spend a certain amount of tokens.

function transferFrom(address sender, address recipient, uint256 amount)

public returns (bool)

{

require(_balances[sender] >= amount, "Insufficient balance");

require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");

_balances[sender]

We continue the implementation of the transferFrom function by updating the balances and allowances mappings.

_balances[sender] -= amount;

_balances[recipient] += amount;

_allowances[sender][msg.sender] -= amount;

_burn(amount);

emit Transfer(sender, recipient, amount);

return true;

In the above code, we have updated the sender’s balance to reflect the transfer, and the recipient’s balance is updated accordingly.

The _allowances mapping is also updated to reflect the transferred amount being deducted from the approved amount.

We have called the _burn function to burn a certain percentage of the transferred tokens, and we have emitted a Transfer event with a from address of the sender’s address and a to address of the recipient’s address, indicating that the tokens have been transferred.

Step 9: Adding Token Metadata: We can add token metadata to provide additional information about the token, such as its name, symbol, and decimal places.

string private _name = "Safe Sun Token";

string private _symbol = "SST";

uint8 private _decimals = 18;

function name() public view returns (string memory)

{

return _name;

}

function symbol() public view returns (string memory)

{

return _symbol;

}

function decimals() public view returns (uint8)

{

return _decimals;

}

In the above code, we have defined the name, symbol, and decimal places for the token. We have also defined getter functions to retrieve this information.

Step 10: Deploying the Contract: Finally, we can deploy the contract on the Ethereum network using Remix. To do this, we need to select the “Solidity Compiler” tab and click on the “Compile SafeSunToken.sol” button to compile the contract.

Once the contract has been compiled successfully, we can select the “Deploy & Run Transactions” tab and select the “SafeSunToken” contract from the dropdown menu.

We can then click on the “Deploy” button to deploy the contract on the Ethereum network. After the contract has been deployed, we can interact with it by calling its functions, such as the transfer function to transfer tokens to another account. Instead of Ethereum, you can deploy on other EVM networks, including Polygon Network.

Testing the Contract

Once the contract is deployed, it’s important to test it to ensure that it works as intended. In this chapter, we will cover some basic tests to verify the functionality of the deflationary token contract.

Step 1: Verify the Token Metadata

The first step is to verify the token metadata, which includes the token name, symbol, and decimal places. We can do this by calling the “name” “symbol” and “decimals” functions. To call these functions, we need to select the contract instance from the “Deployed Contracts” section in Remix and click on the “name” function under the “Read” section. This will display the name of the token in the “decoded output” section. Similarly, we can click on the “symbol” and “decimals” functions to verify the symbol and decimal places of the token.

Step 2: Transfer Tokens

The next step is to test the transfer function by transferring tokens from one account to another. To do this, we can call the transfer function and specify the recipient’s address and the amount of tokens to transfer. To verify the transfer, we can call the balanceOf function and pass in the sender’s address and the recipient’s address to check if the balances have been updated correctly.

Step 3: Approve and TransferFrom

The approve and transferFrom functions are used for token delegation, allowing a third party to transfer tokens on behalf of the token holder. To test these functions, we can follow these steps: Call the “approve” function and specify the delegate’s address and the amount of tokens to be approved.

Call the allowance function to verify that the delegate has been approved to transfer tokens. Call the transferFrom function and specify the sender’s address, the recipient’s address, and the amount of tokens to transfer. Call the balanceOf function to verify that the balances have been updated correctly.

Step 4: Test the Deflationary Mechanism

The deflationary mechanism implemented in the contract burns a certain percentage of the transferred tokens. To test this mechanism, we can follow these steps:

Transfer tokens from one account to another using the transfer function. Call the totalSupply function to verify the total supply of tokens. Call the balanceOf function to verify the balances of the sender and the recipient. Verify that the total supply of tokens has decreased by the expected percentage.

Step 5: Test for Reentrancy Attacks

A reentrancy attack is a type of attack where an attacker exploits a vulnerability in a contract to repeatedly call a function before the previous invocation has completed. This can lead to unexpected behavior and loss of funds. To test for reentrancy attacks, we can follow these steps:

Deploy the contract on the Ethereum network. Call the attack function with a callback function that will repeatedly call the transfer function. Verify that the contract can detect and prevent the reentrancy attack.

Full Sample Code

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract SafeSunToken


{

string public name;

string public symbol;

uint8 public decimals;uint256 public totalSupply;

mapping(address => uint256) public balanceOf;

mapping(address => mapping(address => uint256)) public allowance;

event Transfer(address indexed from, address indexed to, uint256 value);

event Approval(address indexed owner, address indexed spender, uint256 value);

constructor(string memory name, string memory symbol, uint8 decimals, uint256 totalSupply)


{

name = _name;

symbol = _symbol;

decimals = _decimals;

totalSupply = _totalSupply;

balanceOf[msg.sender] = totalSupply;

}

function transfer(address to, uint256 value)

public returns (bool success)


{

require(balanceOf[msg.sender] >= _value);

uint256 tokensToBurn = calculateBurnAmount(_value);

uint256 tokensToTransfer = _value - tokensToBurn;

balanceOf[msg.sender] -= _value;

balanceOf[_to] += tokensToTransfer;

totalSupply -= tokensToBurn;

emit Transfer(msg.sender, _to, tokensToTransfer);

emit Transfer(msg.sender, address(0), tokensToBurn);

return true;

}


function calculateBurnAmount(uint256 _value)

private view returns (uint256)

{

uint256 burnAmount = (_value * 5) / 100; // 5% burn rate

if (totalSupply <= 1000000 ether)

{


// Stop burning below a certain total supply

return 0;

}


else

if (totalSupply <= 10000000 ether)

{

// Reduce burn rate below a certain total supply

return (burnAmount * 2) / 5; // 2% burn rate

}

else

{

return burnAmount;

}

}


function approve(address spender, uint256 value)

public returns (bool success){allowance[msg.sender][_spender] = _value;

emit Approval(msg.sender, spender, value);

return true;

}


function transferFrom(address from, address to, uint256 _value)

public returns (bool success){require(balanceOf[_from] >= _value);

require(allowance[_from][msg.sender] >= _value);

uint256 tokensToBurn = calculateBurnAmount(_value);

uint256 tokensToTransfer = _value - tokensToBurn;

balanceOf[_from] -= _value;balanceOf[_to] += tokensToTransfer;

totalSupply -= tokensToBurn;

allowance[_from][msg.sender] -= _value;

emit Transfer(_from, _to, tokensToTransfer);

emit Transfer(_from, address(0), tokensToBurn);

return true;

}

}

Note that this is a basic implementation of a deflationary token contract and does not include features such as a pause function or an emergency stop mechanism. It is important to thoroughly test and audit the contract to identify and prevent any potential vulnerabilities or bugs that could compromise the security of the contract. This is for educational purpose only. Thank you

Sankar Srinivasan

No comments:

Post a Comment