contract TokenSwap is HasAdmin {
  IERC20 public oldToken;
  IERC20 public newToken;
  MainchainGateway public mainchainGateway;

  constructor(
    IERC20 _oldToken,
    IERC20 _newToken
  )
    public
  {
    oldToken = _oldToken;
    newToken = _newToken;
  }

  function setGateway(MainchainGateway _mainchainGateway) external onlyAdmin {
    if (address(mainchainGateway) != address(0)) {
      require(newToken.approve(address(mainchainGateway), 0));
    }

    mainchainGateway = _mainchainGateway;
    require(newToken.approve(address(mainchainGateway), uint256(-1)));
  }

  function swapToken() external {
    uint256 _balance = oldToken.balanceOf(msg.sender);
    require(oldToken.transferFrom(msg.sender, address(this), _balance));
    require(newToken.transfer(msg.sender, _balance));
  }

  function swapAndBridge(address _recipient, uint256 _amount) external {
    require(_recipient != address(0), "TokenSwap: recipient is the zero address");
    uint256 _balance = oldToken.balanceOf(msg.sender);
    require(oldToken.transferFrom(msg.sender, address(this), _balance));

    require(_amount <= _balance);
    require(newToken.transfer(msg.sender, _balance - _amount));
    mainchainGateway.depositERC20For(_recipient, address(newToken), _amount);
  }

  function swapAndBridgeAll(address _recipient) external {
    require(_recipient != address(0), "TokenSwap: recipient is the zero address");
    uint256 _balance = oldToken.balanceOf(msg.sender);
    require(oldToken.transferFrom(msg.sender, address(this), _balance));
    mainchainGateway.depositERC20For(_recipient, address(newToken), _balance);
  }

  // Used when some old token lost forever
  function withdrawToken() external onlyAdmin {
    newToken.transfer(msg.sender, newToken.balanceOf(address(this)));
  }
}
/**
 * Smart contract wallet to support swapping between old ERC-20 token to a new contract.
 * It also supports swap and deposit into mainchainGateway in a single transaction.
 * Pre-requisites: New token needs to be transferred to this contract.
 * Dev should check that the decimals and supply of old token and new token are identical.
 */
function withdrawToken() external onlyAdmin {
  newToken.transfer(msg.sender, newToken.balanceOf(address(this)));
}

// Used when some old token lost forever