Skip to content

Latest commit

 

History

History
109 lines (98 loc) · 4.11 KB

erc20-token.md

File metadata and controls

109 lines (98 loc) · 4.11 KB
description
An interchain ERC20 token built on Abacus

ERC20 token

You can see an example interchain ERC20 token in the abacus-token repo.

As you can see, the additional changes on top of the vanilla OpenZeppelin ERC20 contract are minimal. It has a transferRemote() function that burns the specified amount of tokens on the sending chain and mints the equivalent amount on the receiving chain.

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.13;

import {Router} from "@abacus-network/app/contracts/Router.sol";

import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";

/**
 * @title Abacus Token that extends the ERC20 token standard to enable native interchain transfers.
 * @author Abacus Works
 * @dev Supply on each chain is not constant but the aggregate supply across all chains is.
 */
contract AbcToken is Router, ERC20Upgradeable {
    /**
     * @dev Emitted on `transferRemote` when a transfer message is dispatched.
     * @param destination The identifier of the destination chain.
     * @param recipient The address of the recipient on the destination chain.
     * @param amount The amount of tokens burnt on the origin chain.
     */
    event SentTransferRemote(
        uint32 indexed destination,
        address indexed recipient,
        uint256 amount
    );

    /**
     * @dev Emitted on `_handle` when a transfer message is processed.
     * @param origin The identifier of the origin chain.
     * @param recipient The address of the recipient on the destination chain.
     * @param amount The amount of tokens minted on the destination chain.
     */
    event ReceivedTransferRemote(
        uint32 indexed origin,
        address indexed recipient,
        uint256 amount
    );

    /**
     * @notice Initializes the Abacus router, ERC20 metadata, and mints initial supply to deployer.
     * @param _xAppConnectionManager The address of the XAppConnectionManager contract.
     * @param _totalSupply The initial supply of the token.
     * @param _name The name of the token.
     * @param _symbol The symbol of the token.
     */
    function initialize(
        address _xAppConnectionManager,
        uint256 _totalSupply,
        string memory _name,
        string memory _symbol
    ) external initializer {
        __Router_initialize(_xAppConnectionManager);
        __ERC20_init(_name, _symbol);
        _mint(msg.sender, _totalSupply);
    }

    /**
     * @notice Transfers `_amount` of tokens from `msg.sender` to `_recipient` on the `_destination` chain.
     * @dev Burns `_amount` of tokens from `msg.sender` on the origin chain and dispatches
     *      message to the `destination` chain to mint `_amount` of tokens to `recipient`.
     * @dev Emits `SentTransferRemote` event on the origin chain.
     * @param _destination The identifier of the destination chain.
     * @param _recipient The address of the recipient on the destination chain.
     * @param _amount The amount of tokens to be sent to the remote recipient.
     */
    function transferRemote(
        uint32 _destination,
        address _recipient,
        uint256 _amount
    ) external payable {
        _burn(msg.sender, _amount);
        _dispatchWithGasAndCheckpoint(
            _destination,
            abi.encode(_recipient, _amount),
            msg.value
        );
        emit SentTransferRemote(_destination, _recipient, _amount);
    }

    /**
     * @dev Mints tokens to recipient when router receives transfer message.
     * @dev Emits `ReceivedTransferRemote` event on the destination chain.
     * @param _origin The identifier of the origin chain.
     * @param _message The encoded remote transfer message containing the recipient address and amount.
     */
    function _handle(
        uint32 _origin,
        bytes32,
        bytes memory _message
    ) internal override {
        (address recipient, uint256 amount) = abi.decode(
            _message,
            (address, uint256)
        );
        _mint(recipient, amount);
        emit ReceivedTransferRemote(_origin, recipient, amount);
    }
}