description |
---|
An interchain ERC20 token built on Abacus |
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);
}
}