Skip to main content
PulseScanner.io

Address

0x85a0914fd8a08d85d2d64a10d4179657c7d4cd17
Current Holdings
$0.00
TXs sent
not counted
First Active
2023-05-17
block 17,286,388
Last Active
1,104 days ago
block 18,262,609
Funded By
0x3661…9334

Net worth historyi

3 snapshots · to block 27,539,724coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchWETHGatewaysolc 0.7.6+commit.7338295fruntime exact · creation exact
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;

import {Ownable} from "../dependencies/openzeppelin/contracts/Ownable.sol";
import {SafeERC20} from "../dependencies/openzeppelin/contracts/SafeERC20.sol";
import {IERC20} from "../dependencies/openzeppelin/contracts/IERC20.sol";
import {IWETH} from "./interfaces/IWETH.sol";
import {IWETHGateway} from "./interfaces/IWETHGateway.sol";
import {ILendingPool} from "../interfaces/ILendingPool.sol";
import {IAToken} from "../interfaces/IAToken.sol";
import {ReserveConfiguration} from "../protocol/libraries/configuration/ReserveConfiguration.sol";
import {UserConfiguration} from "../protocol/libraries/configuration/UserConfiguration.sol";
import {Helpers} from "../protocol/libraries/helpers/Helpers.sol";
import {DataTypes} from "../protocol/libraries/types/DataTypes.sol";

contract WETHGateway is IWETHGateway, Ownable {
    using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
    using UserConfiguration for DataTypes.UserConfigurationMap;
    using SafeERC20 for IERC20;

    IWETH internal immutable WETH;

    /**
     * @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool.
     * @param weth Address of the Wrapped Ether contract
     **/
    constructor(address weth) {
        WETH = IWETH(weth);
    }

    function authorizeLendingPool(address lendingPool) external onlyOwner {
        WETH.approve(lendingPool, uint256(-1));
    }

    /**
     * @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens)
     * is minted.
     * @param lendingPool address of the targeted underlying lending pool
     * @param onBehalfOf address of the user who will receive the aTokens representing the deposit
     * @param referralCode integrators are assigned a referral code and can potentially receive rewards.
     **/
    function depositETH(
        address lendingPool,
        address onBehalfOf,
        uint16 referralCode
    ) external payable override {
        WETH.deposit{value: msg.value}();
        ILendingPool(lendingPool).deposit(
            address(WETH),
            msg.value,
            onBehalfOf,
            referralCode
        );
    }

    /**
     * @dev withdraws the WETH _reserves of msg.sender.
     * @param lendingPool address of the targeted underlying lending pool
     * @param amount amount of aWETH to withdraw and receive native ETH
     * @param to address of the user who will receive native ETH
     */
    function withdrawETH(
        address lendingPool,
        uint256 amount,
        address to
    ) external override {
        IAToken aWETH = IAToken(
            ILendingPool(lendingPool)
                .getReserveData(address(WETH))
                .aTokenAddress
        );
        uint256 userBalance = aWETH.balanceOf(msg.sender);
        uint256 amountToWithdraw = amount;

        // if amount is equal to uint(-1), the user wants to redeem everything
        if (amount == type(uint256).max) {
            amountToWithdraw = userBalance;
        }
        IERC20(aWETH).safeTransferFrom(
            msg.sender,
            address(this),
            amountToWithdraw
        );
        ILendingPool(lendingPool).withdraw(
            address(WETH),
            amountToWithdraw,
            address(this)
        );
        WETH.withdraw(amountToWithdraw);
        _safeTransferETH(to, amountToWithdraw);
    }

    /**
     * @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
     * @param lendingPool address of the targeted underlying lending pool
     * @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
     * @param rateMode the rate mode to repay
     * @param onBehalfOf the address for which msg.sender is repaying
     */
    function repayETH(
        address lendingPool,
        uint256 amount,
        uint256 rateMode,
        address onBehalfOf
    ) external payable override {
        (uint256 stableDebt, uint256 variableDebt) = Helpers
            .getUserCurrentDebtMemory(
                onBehalfOf,
                ILendingPool(lendingPool).getReserveData(address(WETH))
            );

        uint256 paybackAmount = DataTypes.InterestRateMode(rateMode) ==
            DataTypes.InterestRateMode.STABLE
            ? stableDebt
            : variableDebt;

        if (amount < paybackAmount) {
            paybackAmount = amount;
        }
        require(
            msg.value >= paybackAmount,
            "msg.value is less than repayment amount"
        );
        WETH.deposit{value: paybackAmount}();
        ILendingPool(lendingPool).repay(
            address(WETH),
            msg.value,
            rateMode,
            onBehalfOf
        );

        // refund remaining dust eth
        if (msg.value > paybackAmount)
            _safeTransferETH(msg.sender, msg.value - paybackAmount);
    }

    /**
     * @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`.
     * @param lendingPool address of the targeted underlying lending pool
     * @param amount the amount of ETH to borrow
     * @param interesRateMode the interest rate mode
     * @param referralCode integrators are assigned a referral code and can potentially receive rewards
     */
    function borrowETH(
        address lendingPool,
        uint256 amount,
        uint256 interesRateMode,
        uint16 referralCode
    ) external override {
        ILendingPool(lendingPool).borrow(
            address(WETH),
            amount,
            interesRateMode,
            referralCode,
            msg.sender
        );
        WETH.withdraw(amount);
        _safeTransferETH(msg.sender, amount);
    }

    /**
     * @dev transfer ETH to an address, revert if it fails.
     * @param to recipient of the transfer
     * @param value the amount to send
     */
    function _safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "ETH_TRANSFER_FAILED");
    }

    /**
     * @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due
     * direct transfers to the contract address.
     * @param token token to transfer
     * @param to recipient of the transfer
     * @param amount amount to send
     */
    function emergencyTokenTransfer(
        address token,
        address to,
        uint256 amount
    ) external onlyOwner {
        IERC20(token).safeTransfer(to, amount);
    }

    /**
     * @dev transfer native Ether from the utility contract, for native Ether recovery in case of stuck Ether
     * due selfdestructs or transfer ether to pre-computated contract address before deployment.
     * @param to recipient of the transfer
     * @param amount amount to send
     */
    function emergencyEtherTransfer(address to, uint256 amount)
        external
        onlyOwner
    {
        _safeTransferETH(to, amount);
    }

    /**
     * @dev Get WETH address used by WETHGateway
     */
    function getWETHAddress() external view returns (address) {
        return address(WETH);
    }

    /**
     * @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract.
     */
    receive() external payable {
        require(msg.sender == address(WETH), "Receive not allowed");
    }

    /**
     * @dev Revert fallback calls
     */
    fallback() external payable {
        revert("Fallback not allowed");
    }
}