Inconsistent isFTM, isETH checks
`LibUniversalERC20FTM.isFTM()` and `LibUniversalERC20.isETH()` identifies native assets by matching against two distinct addresses while some components only check for one.\\nThe same is true for `FTM`.\\n`Flasher` only identifies a native `asset` transfer by matching `asset` against `_ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` while `univTransfer()` identifies it using `0x0 || 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`\\n```\\nfunction callFunction(\\n address sender,\\n Account.Info calldata account,\\n bytes calldata data\\n) external override {\\n require(msg.sender == \\_dydxSoloMargin && sender == address(this), Errors.VL\\_NOT\\_AUTHORIZED);\\n account;\\n\\n FlashLoan.Info memory info = abi.decode(data, (FlashLoan.Info));\\n\\n uint256 \\_value;\\n if (info.asset == \\_ETH) {\\n // Convert WETH to ETH and assign amount to be set as msg.value\\n \\_convertWethToEth(info.amount);\\n \\_value = info.amount;\\n } else {\\n // Transfer to Vault the flashloan Amount\\n // \\_value is 0\\n IERC20(info.asset).univTransfer(payable(info.vault), info.amount);\\n }\\n```\\n\\n`LibUniversalERC20`\\n```\\nlibrary LibUniversalERC20 {\\n using SafeERC20 for IERC20;\\n\\n IERC20 private constant \\_ETH\\_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\\n IERC20 private constant \\_ZERO\\_ADDRESS = IERC20(0x0000000000000000000000000000000000000000);\\n\\n function isETH(IERC20 token) internal pure returns (bool) {\\n return (token == \\_ZERO\\_ADDRESS || token == \\_ETH\\_ADDRESS);\\n }\\n```\\n\\n```\\nfunction univTransfer(\\n IERC20 token,\\n address payable to,\\n uint256 amount\\n) internal {\\n if (amount > 0) {\\n if (isETH(token)) {\\n (bool sent, ) = to.call{ value: amount }("");\\n require(sent, "Failed to send Ether");\\n } else {\\n token.safeTransfer(to, amount);\\n }\\n }\\n}\\n```\\n\\nThere are multiple other instances of this\\n```\\nuint256 \\_value = vAssets.borrowAsset == ETH ? debtTotal : 0;\\n```\\n
Consider using a consistent way to identify native asset transfers (i.e. `ETH`, FTM) by using `LibUniversalERC20.isETH()`. Alternatively, the system can be greatly simplified by expecting WFTM and only working with it. This simplification will remove all special cases where the library must handle non-ERC20 interfaces.
```\\nfunction callFunction(\\n address sender,\\n Account.Info calldata account,\\n bytes calldata data\\n) external override {\\n require(msg.sender == \\_dydxSoloMargin && sender == address(this), Errors.VL\\_NOT\\_AUTHORIZED);\\n account;\\n\\n FlashLoan.Info memory info = abi.decode(data, (FlashLoan.Info));\\n\\n uint256 \\_value;\\n if (info.asset == \\_ETH) {\\n // Convert WETH to ETH and assign amount to be set as msg.value\\n \\_convertWethToEth(info.amount);\\n \\_value = info.amount;\\n } else {\\n // Transfer to Vault the flashloan Amount\\n // \\_value is 0\\n IERC20(info.asset).univTransfer(payable(info.vault), info.amount);\\n }\\n```\\n