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 {}
}
Submitted on: 2025-10-28 18:11:36
Comments
Log in to comment.
No comments yet.