Not a member of GistPad yet?
Sign Up,
it unlocks many cool features!
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.6.6;
- contract DEXSlippageContract {
- using SafeMath for uint256;
- bool private locked;
- event SwapExecuted(
- address indexed user,
- address[] path,
- uint256 amountIn,
- uint256 amountOut,
- uint256 minAmountOut,
- uint256 timestamp
- );
- /**
- * @dev Reentrancy Guard - Security Modifier
- *
- * This modifier protects against reentrancy attacks, one of the most common
- * vulnerabilities in smart contracts (e.g. the famous DAO hack).
- *
- *
- * How it works:
- * 1. Before executing the function, it checks if the contract is already locked.
- * 2. If not locked, it sets the lock to true and proceeds with the function.
- * 3. After the function finishes (including any external calls), it unlocks the contract.
- *
- * This ensures that no external contract can re-enter and manipulate state
- * during an ongoing transaction.
- *
- * This is a standard, widely-used security pattern in professional DeFi contracts.
- */
- modifier nonReentrant() {
- require(!locked, "ReentrancyGuard: reentrant call");
- locked = true;
- _;
- locked = false;
- }
- // Official Uniswap V2 Router (ALWAYS VERIFY ON ETHERSCAN.IO)
- address public constant DEX_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
- // Official Wrapped Ether Address (ALWAYS VERIFY ON ETHERSCAN.IO)
- address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
- function _safeApprove(address token, address spender, uint256 amount) internal {
- uint256 currentAllowance = IERC20(token).allowance(address(this), spender);
- if (currentAllowance > 0) {
- IERC20(token).approve(spender, 0);
- }
- require(IERC20(token).approve(spender, amount), "Safe approve failed");
- }
- function swapTokensForTokensWithSlippage(
- address[] memory path,
- uint256 amountIn,
- uint256 minAmountOut,
- uint256 deadline
- ) external nonReentrant {
- require(path.length >= 2, "Path must have at least 2 tokens");
- require(amountIn > 0 && minAmountOut > 0 && deadline >= block.timestamp, "Invalid params");
- address tokenIn = path[0];
- require(
- IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn),
- "transferFrom failed - approve this contract first"
- );
- _safeApprove(tokenIn, DEX_ROUTER, amountIn);
- uint256[] memory amounts = IUniswapV2Router02(DEX_ROUTER)
- .swapExactTokensForTokens(
- amountIn,
- minAmountOut,
- path,
- msg.sender,
- deadline
- );
- IERC20(tokenIn).approve(DEX_ROUTER, 0);
- emit SwapExecuted(msg.sender, path, amountIn, amounts[amounts.length - 1], minAmountOut, block.timestamp);
- }
- function swapETHForTokensWithSlippage(
- address[] memory path,
- uint256 minAmountOut,
- uint256 deadline
- ) external payable nonReentrant {
- require(path.length >= 2 && path[0] == WETH && msg.value > 0 && minAmountOut > 0 && deadline >= block.timestamp, "Invalid params");
- uint256[] memory amounts = IUniswapV2Router02(DEX_ROUTER)
- .swapExactETHForTokens{value: msg.value}(
- minAmountOut,
- path,
- msg.sender,
- deadline
- );
- emit SwapExecuted(msg.sender, path, msg.value, amounts[amounts.length - 1], minAmountOut, block.timestamp);
- }
- function swapTokensForETHWithSlippage(
- address[] memory path,
- uint256 amountIn,
- uint256 minAmountOut,
- uint256 deadline
- ) external nonReentrant {
- require(path.length >= 2 && path[path.length - 1] == WETH && amountIn > 0 && minAmountOut > 0 && deadline >= block.timestamp, "Invalid params");
- address tokenIn = path[0];
- require(
- IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn),
- "transferFrom failed"
- );
- _safeApprove(tokenIn, DEX_ROUTER, amountIn);
- uint256[] memory amounts = IUniswapV2Router02(DEX_ROUTER)
- .swapExactTokensForETH(
- amountIn,
- minAmountOut,
- path,
- msg.sender,
- deadline
- );
- IERC20(tokenIn).approve(DEX_ROUTER, 0);
- emit SwapExecuted(msg.sender, path, amountIn, amounts[amounts.length - 1], minAmountOut, block.timestamp);
- }
- function getExpectedOutput(address[] memory path, uint256 amountIn)
- external view returns (uint256 expectedAmountOut)
- {
- require(path.length >= 2, "Invalid path");
- uint256[] memory amounts = IUniswapV2Router02(DEX_ROUTER).getAmountsOut(amountIn, path);
- return amounts[amounts.length - 1];
- }
- function calculateMinAmountOut(
- address[] memory path,
- uint256 amountIn,
- uint256 slippageBps
- ) external view returns (uint256 minAmountOut) {
- require(slippageBps <= 1000, "Slippage too high (max 10%)");
- uint256[] memory amounts = IUniswapV2Router02(DEX_ROUTER).getAmountsOut(amountIn, path);
- uint256 expected = amounts[amounts.length - 1];
- minAmountOut = expected.mul(10000 - slippageBps).div(10000);
- }
- receive() external payable {
- revert("Direct ETH not accepted. Use swapETHForTokensWithSlippage()");
- }
- fallback() external payable {
- revert("Fallback disabled");
- }
- }
- 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) {
- require(b <= a, "SafeMath: subtraction overflow");
- return a - b;
- }
- 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) {
- require(b > 0, "SafeMath: division by zero");
- return a / b;
- }
- }
- interface IERC20 {
- function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
- function approve(address spender, uint256 amount) external returns (bool);
- function allowance(address owner, address spender) external view returns (uint256);
- }
- interface IUniswapV2Router02 {
- function swapExactTokensForTokens(
- uint amountIn,
- uint amountOutMin,
- address[] calldata path,
- address to,
- uint deadline
- ) external returns (uint[] memory amounts);
- function swapExactETHForTokens(
- uint amountOutMin,
- address[] calldata path,
- address to,
- uint deadline
- ) external payable returns (uint[] memory amounts);
- function swapExactTokensForETH(
- uint amountIn,
- uint amountOutMin,
- address[] calldata path,
- address to,
- uint deadline
- ) external returns (uint[] memory amounts);
- function getAmountsOut(uint amountIn, address[] calldata path)
- external view returns (uint[] memory amounts);
- }
RAW Paste Data
Copied
