Skip to content

Commit

Permalink
feat: ERC20 token bridging
Browse files Browse the repository at this point in the history
  • Loading branch information
kupermind committed Nov 14, 2023
1 parent 2932bbd commit f2338e4
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
path = lib/solmate
url = https://github.com/rari-capital/solmate
branch = v7
[submodule "lib/fx-portal"]
path = lib/fx-portal
url = https://github.com/0xPolygon/fx-portal
53 changes: 53 additions & 0 deletions contracts/bridges/FxERC20ChildTunnel.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import {FxBaseChildTunnel} from "../../lib/fx-portal/contracts/tunnel/FxBaseChildTunnel.sol";
import {IERC20} from "../interfaces/IERC20.sol";

/**
* @title FxERC20ChildTunnel
*/
contract FxERC20ChildTunnel is FxBaseChildTunnel {
event FxDepositERC20(address indexed childToken, address indexed rootToken, address from, address indexed to, uint256 amount);
event FxWithdrawERC20(address indexed rootToken, address indexed childToken, address from, address indexed to, uint256 amount);

// Child token
address public immutable childToken;
// Root token
address public immutable rootToken;

// slither-disable-next-line missing-zero-check
constructor(address _fxChild, address _childToken, address _rootToken) FxBaseChildTunnel(_fxChild) {
childToken = _childToken;
rootToken = _rootToken;
}

function deposit(uint256 amount) public {
_deposit(msg.sender, amount);
}

function depositTo(address to, uint256 amount) public {
_deposit(to, amount);
}

function _processMessageFromRoot(
uint256 /* stateId */,
address sender,
bytes memory data
) internal override validateSender(sender) {
// Decode incoming data
(address from, address to, uint256 amount) = abi.decode(data, (address, address, uint256));

IERC20(childToken).transfer(to, amount);
emit FxWithdrawERC20(rootToken, childToken, from, to, amount);
}

function _deposit(address to, uint256 amount) internal {
// Deposit tokens
IERC20(childToken).transferFrom(msg.sender, address(this), amount);

// Send message to root
_sendMessageToRoot(abi.encode(msg.sender, to, amount));
emit FxDepositERC20(childToken, rootToken, msg.sender, to, amount);
}
}
48 changes: 48 additions & 0 deletions contracts/bridges/FxERC20RootTunnel.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import {FxBaseRootTunnel} from "../../lib/fx-portal/contracts/tunnel/FxBaseRootTunnel.sol";
import {IERC20} from "../interfaces/IERC20.sol";

/**
* @title FxERC20RootTunnel
*/
contract FxERC20RootTunnel is FxBaseRootTunnel {
event FxDepositERC20(address indexed childToken, address indexed rootToken, address from, address indexed to, uint256 amount);
event FxWithdrawERC20(address indexed rootToken, address indexed childToken, address from, address indexed to, uint256 amount);

// Child token
address public immutable childToken;
// Root token
address public immutable rootToken;

constructor(address _checkpointManager, address _fxRoot, address _childToken, address _rootToken)
FxBaseRootTunnel(_checkpointManager, _fxRoot)
{
childToken = _childToken;
rootToken = _rootToken;
}

function withdraw(address to, uint256 amount) external {
// Transfer from sender to this contract
IERC20(rootToken).transferFrom(msg.sender, address(this), amount);

// Burn tokens
IERC20(rootToken).burn(amount);

// Send message to child
bytes memory message = abi.encode(msg.sender, to, amount);
_sendMessageToChild(message);
emit FxWithdrawERC20(rootToken, childToken, msg.sender, to, amount);
}

// exit processor
function _processMessageFromChild(bytes memory data) internal override {
// Decode message from child
(address from, address to, uint256 amount) = abi.decode(data, (address, address, uint256));

// transfer from tokens to
IERC20(rootToken).mint(to, amount);
emit FxDepositERC20(childToken, rootToken, from, to, amount);
}
}
48 changes: 48 additions & 0 deletions contracts/interfaces/IERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

/// @dev ERC20 token interface.
interface IERC20 {
/// @dev Gets the amount of tokens owned by a specified account.
/// @param account Account address.
/// @return Amount of tokens owned.
function balanceOf(address account) external view returns (uint256);

/// @dev Gets the total amount of tokens stored by the contract.
/// @return Amount of tokens.
function totalSupply() external view returns (uint256);

/// @dev Gets remaining number of tokens that the `spender` can transfer on behalf of `owner`.
/// @param owner Token owner.
/// @param spender Account address that is able to transfer tokens on behalf of the owner.
/// @return Token amount allowed to be transferred.
function allowance(address owner, address spender) external view returns (uint256);

/// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
/// @param spender Account address that will be able to transfer tokens on behalf of the caller.
/// @param amount Token amount.
/// @return True if the function execution is successful.
function approve(address spender, uint256 amount) external returns (bool);

/// @dev Transfers the token amount.
/// @param to Address to transfer to.
/// @param amount The amount to transfer.
/// @return True if the function execution is successful.
function transfer(address to, uint256 amount) external returns (bool);

/// @dev Transfers the token amount that was previously approved up until the maximum allowance.
/// @param from Account address to transfer from.
/// @param to Account address to transfer to.
/// @param amount Amount to transfer to.
/// @return True if the function execution is successful.
function transferFrom(address from, address to, uint256 amount) external returns (bool);

/// @dev Mints tokens.
/// @param account Account address.
/// @param amount Token amount.
function mint(address account, uint256 amount) external;

/// @dev Burns tokens.
/// @param amount Token amount to burn.
function burn(uint256 amount) external;
}
1 change: 1 addition & 0 deletions lib/fx-portal
Submodule fx-portal added at 296ac8

0 comments on commit f2338e4

Please sign in to comment.