Skip to main content
1 of 2

Why does the Astar XC20 wrapper example use the ERC20 wrapper functionality?

I am working on an XC20 implementation of an existing ERC20. I am basing the contract off of the Astar here.

I noticed there is some code inherited from the ERC20 contract via the ERC20Wrapper contract that is not needed for this implementation. The ERC20Wrapper is usually used to create a wrapped version of an existing token, but in the case with XC20, the wrapped token already exists and just needs to be bridged to the underlying token. I am curious why the example still has this unused code.

I implemented it with removing all of the extra ERC20 code and was able to get a successful run, being able to mint/burn my xcToken by depositing/withdrawing my underlying token.

Here is my contract code for reference.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IERC20} from './Dependencies/IERC20.sol';
import {BAIToken} from './BAIToken.sol';
import {Ownable} from "./Dependencies/Ownable.sol";


// This xBai interface was recieved from the astar XCM documentation 
// (https://github.com/AstarNetwork/astar-frame/blob/674356e7b611e561aaf9bf581452cab965cf8e87/examples/assets-erc20/XcBurrito.sol#L12)
interface IERC20Plus is IERC20 {
    function mint(address beneficiary, uint256 amount) external returns (bool);
    function burn(address who, uint256 amount) external returns (bool);
}


contract XBaiWrapper is Ownable{

    IERC20 public immutable underlyingToken;
    IERC20Plus public crossChainToken;

    constructor(IERC20 _underlyingToken, IERC20Plus _crossChainToken) {
        underlyingToken = _underlyingToken;
        crossChainToken = _crossChainToken;
    }

    // --- Events --- 

    event xBaiMinted(address to, uint256 amount);
    event xBaiBurned(address from, uint256 amount);
    event baiSupplyChanged(uint256 newTotalSupply);

    // --- Admin functions ---

    function mintXBai(address _to, uint256 _amount) public onlyOwner {

        require( // Make sure amount to mint is greater than 0
            _amount != 0, 
            "Mint amount must be greater than 0"
        );

        _mintCrossChainToken(_to, _amount);
        emit xBaiMinted(_to, _amount);
    }

    function burnXBai(address _from, uint256 _amount) public onlyOwner {

        require( // Make sure amount to burn is greater than 0
            _amount != 0, 
            "Burn amount must be greater than 0"
        );

        _burnCrossChainToken(_from, _amount);
        emit xBaiBurned(_from, _amount);
    }


    //=====================================================================
    // This functiontion is to be used if the total supply of xBai is 
    // greater than the amount of Bai in this contract. The caller should
    // supply this contract with Bai so that the total supply of xBai is
    // equal to this contract's balance of Bai. 
    //=====================================================================
    function supplyBai(address _from, uint256 _amount) public onlyOwner {

        require( // Make sure amount to recover is greater than 0
            _amount != 0, 
            "Burn amount must be greater than 0"
        );

        underlyingToken.transferFrom(_from, address(this), _amount);

        uint256 newBaiSupply = underlyingToken.balanceOf(address(this));
        emit baiSupplyChanged(newBaiSupply);
    }  

    //=====================================================================
    // This function is to be used if the total supply of xBai is less than
    // the amount of Bai in this contract. The call should recover enough 
    // Bai so this contract's balance of Bai is equal to the total supply
    // of xBai. 
    //=====================================================================
    function recoverBai(address _to, uint256 _amount) public onlyOwner {
        
        require( // Make sure amount to recover is greater than 0
            _amount != 0, 
            "Burn amount must be greater than 0"
        );

        underlyingToken.transfer(_to, _amount);

        uint256 newBaiSupply = underlyingToken.balanceOf(address(this));
        emit baiSupplyChanged(newBaiSupply);
    }

    // --- Public functions ---

    //=====================================================================
    // Allow a user to deposit underlying tokens and mint the corresponding 
    // number of wrapped tokens.
    //=====================================================================
    function depositFor(address _account, uint256 _amount) public returns (bool) {

        require( // Make sure amount to deposit is greater than 0
            _amount != 0, 
            "Deposit amount must be greater than 0"
        );

        underlyingToken.transferFrom(msg.sender, address(this), _amount);
        _mintCrossChainToken(_account, _amount);

        return true;
    }

    //=====================================================================
    // Allow a user to burn a number of wrapped tokens and withdraw the 
    // corresponding number of underlying tokens.
    //=====================================================================
    function withdrawTo(address _account, uint256 _amount) public returns (bool) {

        require( // Make sure amount to withdraw is greater than 0
            _amount != 0, 
            "Withdrawal amount must be greater than 0"
        );

        _burnCrossChainToken(msg.sender, _amount);
        underlyingToken.transfer(_account, _amount);

        return true;
    }

    // --- Internal functions ---

    function _mintCrossChainToken(address _to, uint256 _amount) internal {

        // add here your pre-mint hooks hooks if needed
        
        require(
            crossChainToken.mint(_to, _amount), 
            "Minting xc token failed"
        );

        // add here your post-mint hooks hooks if needed
        emit xBaiMinted(_to, _amount);
    }

    function _burnCrossChainToken(address _from, uint256 _amount) internal {

        // add here your pre-burn hooks hooks if needed

        require(
            crossChainToken.burn(_from, _amount), 
            "Burning xc token failed"
        );

        // add here your post-burn hooks hooks if needed
        emit xBaiBurned(_from, _amount);
    }

}