contract SaiDaiTokenSwap is Pausable, Destructible
{
  using SafeMath for uint;
  using SafeTransfer for ERC20;
  address constant ETHER = address(0);
  uint constant expScale = 1e18;
  uint constant rateDecimals = 18;
  uint constant rateUnit = 10 ** rateDecimals;

  ERC20 sai;
  ERC20 dai;
  address migration;
  MakerDAO_MigrationProxyActions proxy;

  event LogWithdrawToken(
    address indexed _from,
    address indexed _token,
    uint amount
  );

  event LogTokenSwap(
    address indexed _userAddress,
    address indexed _userSentTokenAddress,
    uint _userSentTokenAmount,
    address indexed _userReceivedTokenAddress,
    uint _userReceivedTokenAmount
  );

  constructor(
    address _sai,
    address _dai,
    address _migration,
    address _proxy
  )
    public
  {
    sai = ERC20(_sai);
    dai = ERC20(_dai);
    migration = _migration;
    proxy = MakerDAO_MigrationProxyActions(_proxy);
  }

  function() external {
    revert("fallback function not allowed");
  }

  /**
   * @dev Withdraw asset.
   * @param _tokenAddress Asset to be withdrawed.
   * @return bool.
   */
  function withdrawToken(address _tokenAddress)
    public
    onlyOwner
  {
    uint tokenBalance;
    if (_tokenAddress == ETHER) {
      tokenBalance = address(this).balance;
      msg.sender.transfer(tokenBalance);
    } else {
      tokenBalance = ERC20(_tokenAddress).balanceOf(address(this));
      ERC20(_tokenAddress)._safeTransfer(msg.sender, tokenBalance);
    }
    emit LogWithdrawToken(msg.sender, _tokenAddress, tokenBalance);
  }

  /******************* rate functions for interface compatibility *******************/

  function buyRate() public pure returns(uint) {
    return rateUnit;
  }

  function buyRateDecimals() public pure returns(uint) {
    return rateDecimals;
  }

  function sellRate() public pure returns(uint) {
    return 0;
  }

  function sellRateDecimals() public pure returns(uint) {
    return rateDecimals;
  }

  /******************* end rate functions *******************/

  /**
 * @dev For interface compatibility. Function to calculate the number of tokens the user is going to receive.
 * @param _offerTokenAmount The amount of tokens.
 * @param _isRedeem If true, the offered token is the LoanToken, otherwise is the underlying token.
 * @return uint.
 */
  function getAmount(uint _offerTokenAmount, bool _isRedeem)
    public pure returns(uint toUserAmount)
  {
    // Swap dai to sai forbidden
    return _isRedeem? 0 : _offerTokenAmount;
  }

  /**
   * @dev Release purchased asset to the buyer based on pair rate.
   * @param _userOfferTokenAddress The token address the purchaser is offering (It may be the quote or the base).
   * @param _userOfferTokenAmount The amount of token the user want to swap.
   * @return bool.
   */
  function swapToken (
    address _userOfferTokenAddress,
    uint _userOfferTokenAmount
  )
    public
    whenNotPaused
    returns (bool)
  {
    require(_userOfferTokenAmount != 0, "_userOfferTokenAmount == 0");
    require(
      ERC20(_userOfferTokenAddress).allowance(msg.sender, address(this)) >= _userOfferTokenAmount,
      "ERC20 allowance < _userOfferTokenAmount"
    );
    // check if offered token address is correct
    require(_userOfferTokenAddress == address(sai), "Swap dai to sai forbidden");

    // get user's tokens
    sai._safeTransferFrom(msg.sender, address(this), _userOfferTokenAmount);

    uint toUserAmount = _userOfferTokenAmount;
    sai._safeApprove(address(proxy), _userOfferTokenAmount);
    proxy.swapSaiToDai(migration, _userOfferTokenAmount);
    require(dai.balanceOf(address(this)) >= toUserAmount, "No enough dai after swap");
//    require(toUserAmount > 0, "toUserAmount must be greater than 0");
    require(
      dai.transfer(msg.sender, toUserAmount),
      "cannot transfer the dai tokens to the user"
    );

    emit LogTokenSwap(
      msg.sender,
      address(sai),
      _userOfferTokenAmount,
      address(dai),
      toUserAmount
    );
    return true;
  }


}
/**
 * @title TokenSwap.
 * @author Eidoo SAGL.
 * @dev A swap asset contract. The offerAmount and wantAmount are collected and sent into the contract itself.
 */
function swapToken (
  address _userOfferTokenAddress,
  uint _userOfferTokenAmount
)
  public
  whenNotPaused
  returns (bool)
{
  require(_userOfferTokenAmount != 0, "_userOfferTokenAmount == 0");
  require(
    ERC20(_userOfferTokenAddress).allowance(msg.sender, address(this)) >= _userOfferTokenAmount,
    "ERC20 allowance < _userOfferTokenAmount"
  );
  // check if offered token address is correct
  require(_userOfferTokenAddress == address(sai), "Swap dai to sai forbidden");

  // get user's tokens
  sai._safeTransferFrom(msg.sender, address(this), _userOfferTokenAmount);

  uint toUserAmount = _userOfferTokenAmount;
  sai._safeApprove(address(proxy), _userOfferTokenAmount);
  proxy.swapSaiToDai(migration, _userOfferTokenAmount);
  require(dai.balanceOf(address(this)) >= toUserAmount, "No enough dai after swap");
    require(toUserAmount > 0, "toUserAmount must be greater than 0");
  require(
    dai.transfer(msg.sender, toUserAmount),
    "cannot transfer the dai tokens to the user"
  );

  emit LogTokenSwap(
    msg.sender,
    address(sai),
    _userOfferTokenAmount,
    address(dai),
    toUserAmount
  );
  return true;
}

/**
 * @dev Release purchased asset to the buyer based on pair rate.
 * @param _userOfferTokenAddress The token address the purchaser is offering (It may be the quote or the base).
 * @param _userOfferTokenAmount The amount of token the user want to swap.
 * @return bool.
 */