Exploring the CustomSwapToken Smart Contract: Understanding Decentralized Token Swapping

Exploring the CustomSwapToken Smart Contract: Understanding Decentralized Token Swapping

In this blog post, we'll delve into a Solidity smart contract designed for token swapping – the Swap contract. This contract facilitates the exchange of Ethereum and various custom ERC-20 tokens in a decentralized manner.

Let's examine the smart contract I created for the UNISWAP Token Marketplace project, which is available on my GitHub.

Link to Smart Contract -> https://github.com/AdityaB1152/token-swap/blob/master/contracts/Swap.sol

Decentralized Token Exchange -> https://github.com/AdityaB1152/token-swap

Understanding the Components

Let's break down the main components of the Smart Contract:

  1. CustomSwapToken Contract

The CustomSwapToken contract is an ERC-20 token contract that extends the OpenZeppelin ERC-20 implementation. It is used to create custom tokens with specified names and symbols. In the constructor, an initial supply of 10 million tokens is minted and assigned to the contract deployer.

contract CustomSwapToken is ERC20 {
    // Constructor to mint tokens to the contract deployer
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        _mint(msg.sender, 10000000 * 10 ** 18);

    }
}
  1. Swap Contract

The Swap contract is the heart of the token-swapping functionality. The main functionality of the Smart contract lies in the Swap contract. It features three types of token swaps: from Ether to a custom token, from a custom token to Ether, and between two custom tokens.

  • Token Initialization:
solidityCopy codestring[] public tokens = ["Tether USD", "BNB", "USD Coin", "stETH", "TRON", "Matic Token", "SHIBA INU", "Uniswap"];
mapping(string => ERC20) public tokenInstanceMap;

tokens: An array of string literals representing the names of different tokens.

tokenInstanceMap: A mapping that associates each token name with its corresponding ERC20 token instance.

  • Ether Value:
solidityCopy codeuint256 ethValue = 1000000000000;

ethValue: A constant representing the value of 1 Ether in wei. It is set to 1000000000000 wei.

  • Contract Initialization:
solidityCopy codeconstructor(){
    for(uint i = 0; i < tokens.length; i++){
        CustomSwapToken token = new CustomSwapToken(tokens[i], tokens[i]);
        tokenInstanceMap[tokens[i]] = token;
    }
}

constructor: The constructor function initializes the contract by creating instances of CustomSwapToken for each token in the tokens array. It then populates the tokenInstanceMap with the token names and their corresponding instances.

  • Token Information Functions:
solidityCopy codefunction getBalance(string memory tokenName, address _address) public view returns (uint256) {
    return tokenInstanceMap[tokenName].balanceOf(_address);
}

function getTotalSupply(string memory tokenName) public view returns(uint256) {
    return tokenInstanceMap[tokenName].totalSupply();
}

function getName(string memory tokenName) public view returns (string memory) {
    return tokenInstanceMap[tokenName].name();
}

getBalance: Returns the balance of a specific token for a given address.

getTotalSupply: Returns the total supply of a specific token.

getName: Returns the name of a specific token.

  • Ether and Token Information Functions:
solidityCopy codefunction getEthBalance() public view returns (uint256) {
    return address(this).balance;
}

function getTokenAddress(string memory tokenName) public view returns (uint256) {
    return address(tokenInstanceMap[tokenName]);
}

getEthBalance: Returns the balance of Ether held by the contract.

getTokenAddress: Returns the address of the ERC20 token contract for a given token name.

  • Swapping Ether to Token:

    Users can exchange Ether for a custom token using the swapEthToToken function. The function calculates the output token amount based on the input Ether value and transfers the tokens to the user.

      function swapEthToToken(string memory tokenName) public payable returns (uint256) {
          // Calculate output token amount based on input Ether value
          uint256 inputValue = msg.value;
          uint256 outputValue = (inputValue / ethValue) * 10 ** 18;
    
          // Transfer tokens to the user
          require(tokenInstanceMap[tokenName].transfer(msg.sender, outputValue));
    
          // Log transaction history
          string memory etherToken = "Ether";
          _transactionHistory(tokenName, etherToken, inputValue, outputValue);
    
          return outputValue;
      }
    
  • Swapping Token to Ether:

    Users can convert a custom token to Ether with the swapTokenToEth function. The function ensures that the contract has sufficient Ether balance and transfers the calculated Ether amount to the user.

function swapTokenToEth(string memory tokenName, uint256 _amount) public returns (uint256) {
    // Calculate exact token amount and Ether to be transferred
    uint256 exactAmount = _amount / 10 ** 18;
    uint256 ethToBeTransferred = exactAmount * ethValue;

    // Check contract's Ether balance
    require(address(this).balance >= ethToBeTransferred, "Dex is running low on balance");

    // Transfer Ether to the user
    payable(msg.sender).transfer(ethToBeTransferred);

    // Transfer tokens from the user to the contract
    require(tokenInstanceMap[tokenName].transferFrom(msg.sender, address(this), _amount));

    // Log transaction history
    string memory etherToken = 'Ether';
    _transactionHistory(tokenName, etherToken, exactAmount, ethToBeTransferred);

    return ethToBeTransferred;
}
  • Swapping Token to Token:

    Users can also exchange one custom token for another with the swapTokenToToken function.

function swapTokenToToken(string memory srcTokenName, string memory destTokenName, uint256 _amount) public {
    // Transfer source token from user to the contract
    require(tokenInstanceMap[srcTokenName].transferFrom(msg.sender, address(this), _amount));

    // Transfer destination token from the contract to the user
    require(tokenInstanceMap[destTokenName].transfer(msg.sender, _amount));

    // Log transaction history
    _transactionHistory(srcTokenName, destTokenName, _amount, _amount);
}
  • Transaction History:

The History struct and associated functions maintain a record of each transaction's details, including the involved tokens, input/output values, and the user's address.

  •     struct History {
            uint256 historyId;
            string tokenA;
            string tokenB;
            uint256 inputValue;
            uint256 outputValue;
            address userAddress;
        }
    
        function _transactionHistory(string memory tokenName, string memory etherToken, uint256 inputValue, uint256 outputValue) internal {
            // Increment history index and record transaction details
            _historyIndex++;
            uint256 _historyId = _historyIndex;
            History storage history = historys[_historyId];
    
            history.historyId = _historyId;
            history.userAddress = msg.sender;
            history.tokenA = tokenName;
            history.tokenB = etherToken;
            history.inputValue = inputValue;
            history.outputValue = outputValue;
        }
    

    Solidity smart contract, Swap, demonstrates the basic functionality of a decentralized token swap platform. Users can exchange Ethereum for custom ERC-20 tokens, swap tokens for Ethereum, and even trade one ERC-20 token for another. The transaction history feature enhances transparency by logging all swaps on the blockchain.

Conclusion:

To sum up, the Solidity smart contract described in this blog post provides a simple and effective way to swap Ethereum and custom ERC-20 tokens in a decentralized manner. The contract comprises two main components: the CustomSwapToken contract, which creates custom tokens, and the Swap contract, which enables users to swap tokens. The contract also includes several helpful functions such as token balance and supply information, token swapping functions, and transaction history logging functions. Overall, this contract serves as a solid foundation for building a decentralized token-swapping platform.