EthSwapStake

Description:

Decentralized Finance (DeFi) protocol contract providing Swap, Staking functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

// Minimal interfaces to avoid conflicts
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IDexRouter {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function getAmountsOut(uint amountIn, address[] calldata path)
        external view returns (uint[] memory amounts);
}

interface IStakingContract {
    function stake(uint256 amount, uint256 planIndex) external;
    function Duration(uint256) external view returns (uint256);
    function Bonus(uint256) external view returns (uint256);
    function percentDivider() external view returns (uint256);
    function Stakers(address) external view returns (
        uint256 totalStaked,
        uint256 totalUnStaked,
        uint256 totalClaimedReward,
        uint256 stakeCount,
        bool alreadyExists
    );
}

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;
        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        return c;
    }
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return payable(msg.sender);
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this;
        return msg.data;
    }
}

contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _owner = _msgSender();
        emit OwnershipTransferred(address(0), _owner);
    }

    function owner() public view returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

contract EthSwapStake is Ownable {
    using SafeMath for uint256;
    
    IERC20 public lunexToken;
    IStakingContract public stakingContract;
    IDexRouter public dexRouter;
    
    address public WETH;
    address public distributor;
    
    // Events
    event EthSwappedAndStaked(
        address indexed user,
        uint256 ethAmount,
        uint256 lunexReceived,
        uint256 planIndex,
        uint256 stakeIndex
    );
    
    constructor(
        address _lunexToken,
        address _stakingContract,
        address _dexRouter,
        address _distributor
    ) {
        lunexToken = IERC20(_lunexToken);
        stakingContract = IStakingContract(_stakingContract);
        dexRouter = IDexRouter(_dexRouter);
        distributor = _distributor;
        WETH = dexRouter.WETH();
    }
    
    /**
     * @dev Main function: Swap ETH for Lunex and stake it
     * @param planIndex Staking plan (0, 1, or 2)
     * @param minLunexOut Minimum Lunex tokens expected (slippage protection)
     */
    function swapEthAndStake(
        uint256 planIndex,
        uint256 minLunexOut
    ) external payable {
        require(msg.value > 0, "Must send ETH");
        require(planIndex >= 0 && planIndex <= 2, "Invalid plan index");
        
        // Get expected Lunex amount
        uint256 expectedLunex = getLunexAmountForEth(msg.value);
        require(expectedLunex >= minLunexOut, "Slippage too high");
        
        // Swap ETH for Lunex
        uint256 lunexReceived = _swapEthForLunex(msg.value);
        
        // Approve staking contract to spend Lunex
        lunexToken.approve(address(stakingContract), lunexReceived);
        
        // Stake the Lunex tokens
        stakingContract.stake(lunexReceived, planIndex);
        
        // Get the stake index (stakeCount - 1)
        (, , , uint256 stakeCount, ) = stakingContract.Stakers(msg.sender);
        uint256 stakeIndex = stakeCount > 0 ? stakeCount - 1 : 0;
        
        emit EthSwappedAndStaked(
            msg.sender,
            msg.value,
            lunexReceived,
            planIndex,
            stakeIndex
        );
    }
    
    /**
     * @dev Internal function to swap ETH for Lunex tokens
     */
    function _swapEthForLunex(uint256 ethAmount) internal returns (uint256) {
        uint256 balanceBefore = lunexToken.balanceOf(address(this));
        
        address[] memory path = new address[](2);
        path[0] = WETH;
        path[1] = address(lunexToken);
        
        dexRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{
            value: ethAmount
        }(
            0, // Accept any amount of tokens (slippage handled in main function)
            path,
            address(this),
            block.timestamp + 300 // 5 minutes deadline
        );
        
        uint256 balanceAfter = lunexToken.balanceOf(address(this));
        return balanceAfter.sub(balanceBefore);
    }
    
    /**
     * @dev Calculate expected Lunex amount for given ETH amount
     */
    function getLunexAmountForEth(uint256 ethAmount) public view returns (uint256) {
        address[] memory path = new address[](2);
        path[0] = WETH;
        path[1] = address(lunexToken);
        
        try dexRouter.getAmountsOut(ethAmount, path) returns (uint[] memory amounts) {
            return amounts[1];
        } catch {
            return 0;
        }
    }
    
    /**
     * @dev Get current ETH/Lunex price
     */
    function getEthToLunexPrice() external view returns (uint256) {
        return getLunexAmountForEth(1 ether);
    }
    
    /**
     * @dev Calculate staking rewards for given amount and plan
     */
    function calculateStakingReward(uint256 amount, uint256 planIndex) external view returns (uint256) {
        require(planIndex >= 0 && planIndex <= 2, "Invalid plan index");
        
        uint256 bonus = stakingContract.Bonus(planIndex);
        uint256 percentDivider = stakingContract.percentDivider();
        
        return amount.mul(bonus).div(percentDivider);
    }
    
    /**
     * @dev Get all staking plan details
     */
    function getStakingPlans() external view returns (
        uint256[3] memory durations,
        uint256[3] memory bonuses
    ) {
        durations[0] = stakingContract.Duration(0);
        durations[1] = stakingContract.Duration(1);
        durations[2] = stakingContract.Duration(2);
        
        bonuses[0] = stakingContract.Bonus(0);
        bonuses[1] = stakingContract.Bonus(1);
        bonuses[2] = stakingContract.Bonus(2);
    }
    
    /**
     * @dev Emergency function to withdraw stuck ETH
     */
    function withdrawEth(address payable to) external onlyOwner {
        to.transfer(address(this).balance);
    }
    
    /**
     * @dev Emergency function to withdraw stuck tokens
     */
    function withdrawToken(address token, address to, uint256 amount) external onlyOwner {
        IERC20(token).transfer(to, amount);
    }
    
    /**
     * @dev Update distributor address
     */
    function setDistributor(address _distributor) external onlyOwner {
        distributor = _distributor;
    }
    
    /**
     * @dev Update DEX router
     */
    function setDexRouter(address _dexRouter) external onlyOwner {
        dexRouter = IDexRouter(_dexRouter);
        WETH = dexRouter.WETH();
    }
    
    // Receive ETH
    receive() external payable {}
}

Tags:
ERC20, DeFi, Swap, Staking|addr:0x502bab69ddb226d451260c457086b892ae2c5352|verified:true|block:23676728|tx:0xcf16ae3b9beb796821fcbdb3837dca73d3c48fb2cede571c499427e58dec517a|first_check:1761671494

Submitted on: 2025-10-28 18:11:36

Comments

Log in to comment.

No comments yet.