Contract Name:
UniswapSwapV2Helper
Contract Source Code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IUniswapV2Router {
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function usdcToEth(uint256 usdcAmount) external view returns (uint256);
}
interface IUniswapV2Factory {
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
}
interface IPair {
function buyTotalFee() external view returns (uint256);
function sellTotalFee() external view returns (uint256);
}
contract UniswapSwapV2Helper {
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant ETHER_VISTA_FACTORY =
0x9a27cb5ae0B2cEe0bb71f9A85C0D60f3920757B4;
address constant ETHER_VISTA_ROUTER =
0xEAaa41cB2a64B11FE761D41E747c032CdD60CaCE;
address public vaultAddress = 0xcD3420a9bda59D7a54baEc1DcAaFe19b09beB521;
event OrderRecord(
address fromToken,
address toToken,
address sender,
uint256 fromAmount,
uint256 returnAmount
);
constructor() {}
receive() external payable {
(bool sent, ) = vaultAddress.call{value: address(this).balance / 100}(
""
);
require(sent, "Receive: Failed to send Ether to vault");
(sent, ) = tx.origin.call{value: address(this).balance}("");
require(sent, "Receive: Failed to send Ether to tx.origin");
}
function swap(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable {
uint256 fee = amountIn / 100;
amountIn = msg.value - fee;
require(path[0] == WETH, "Buy: Path[0] has to be WETH");
require(path[1] != address(0), "Buy: Path[1] can not be address 0");
IERC20 token = IERC20(path[1]);
uint256 tokenBalanceDiff;
{
uint256 tokenBalanceBefore = token.balanceOf(address(this));
IUniswapV2Router(ETHER_VISTA_ROUTER)
.swapExactETHForTokensSupportingFeeOnTransferTokens{
value: amountIn
}(amountOutMin, path, address(this), deadline);
uint256 tokeBalanceAfter = token.balanceOf(address(this));
require(
tokeBalanceAfter > tokenBalanceBefore,
"Buy: Token balance did not increase"
);
tokenBalanceDiff = tokeBalanceAfter - tokenBalanceBefore;
require(
tokenBalanceDiff > amountOutMin,
"Buy: Not enough output amount"
);
}
token.transfer(to, tokenBalanceDiff);
{
(bool sent, ) = vaultAddress.call{value: address(this).balance}("");
require(sent, "Buy: Failed to send Ether to vault");
}
emit OrderRecord(
address(0),
path[1],
msg.sender,
amountIn,
tokenBalanceDiff
);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}