Contract Source Code:
File 1 of 1 : SonicBlur
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from,
address to,
uint256 amount
) external returns (bool);
}
interface IWSonic {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
}
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), 'Ownable: caller is not the owner');
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), 'Ownable: new owner is the zero address');
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
interface IRouter02 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
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;
function getAmountsOut(
uint256 amountIn,
address[] calldata path
) external view returns (uint256[] memory amounts);
function getAmountsIn(
uint256 amountOut,
address[] calldata path
) external view returns (uint256[] memory amounts);
}
contract SonicBlur is Ownable {
IERC20 public blur;
IWSonic public wsonic;
IRouter02 public router;
event BuyBlur(address indexed buyer, uint256 amount);
event SellBlur(address indexed seller, uint256 amount);
constructor() {
blur = IERC20(0xd3DCe716f3eF535C5Ff8d041c1A41C3bd89b97aE);
wsonic = IWSonic(0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38);
// router = IRouter02(0xF5F7231073b3B41c04BA655e1a7438b1a7b29c27); // SwapX router
router = IRouter02(0x1D368773735ee1E678950B7A97bcA2CafB330CDc); // Shadow router
}
function swap(
uint256 amount,
IERC20 token,
uint256 amountOutMin,
uint256 deadline,
address[] memory path,
address to,
IERC20 outToken
) internal returns (uint256 delta) {
token.approve(address(router), amount);
uint256 beforeOut = outToken.balanceOf(to);
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
amountOutMin,
path,
to,
deadline
);
uint256 afterOut = outToken.balanceOf(to);
delta = afterOut - beforeOut;
}
function buyBlur(
uint256 amount,
IERC20 token,
uint256 amountOutMin,
uint256 deadline
) public {
token.transferFrom(msg.sender, address(this), amount);
address[] memory path;
if (address(token) == address(wsonic)) {
path = new address[](2);
path[0] = address(token);
path[1] = address(blur);
} else {
path = new address[](3);
path[0] = address(token);
path[1] = address(wsonic);
path[2] = address(blur);
}
uint256 delta = swap(
amount,
token,
amountOutMin,
deadline,
path,
msg.sender,
blur
);
emit BuyBlur(msg.sender, delta);
}
function buyBlurWithSonic(
uint256 amountOutMin,
uint256 deadline
) external payable {
wsonic.deposit{value: msg.value}();
address[] memory path = new address[](2);
path[0] = address(wsonic);
path[1] = address(blur);
uint256 delta = swap(
msg.value,
IERC20(address(wsonic)),
amountOutMin,
deadline,
path,
msg.sender,
blur
);
emit BuyBlur(msg.sender, delta);
}
function sellBlur(
uint256 amount,
IERC20 token,
uint256 amountOutMin,
uint256 deadline
) public {
blur.transferFrom(msg.sender, address(this), amount);
address[] memory path;
if (address(token) == address(wsonic)) {
path = new address[](2);
path[0] = address(blur);
path[1] = address(token);
} else {
path = new address[](3);
path[0] = address(blur);
path[1] = address(wsonic);
path[2] = address(token);
}
swap(
amount,
blur,
amountOutMin,
deadline,
path,
msg.sender,
token
);
emit SellBlur(msg.sender, amount);
}
function sellBlurForSonic(
uint256 amount,
uint256 amountOutMin,
uint256 deadline
) external {
blur.transferFrom(msg.sender, address(this), amount);
address[] memory path = new address[](2);
path[0] = address(blur);
path[1] = address(wsonic);
uint256 delta = swap(
amount,
blur,
amountOutMin,
deadline,
path,
address(this),
IERC20(address(wsonic))
);
wsonic.withdraw(delta);
payable(msg.sender).transfer(delta);
emit SellBlur(msg.sender, amount);
}
function getAmountToken(
uint256 amountBlur,
address token
) external view returns (uint256) {
address[] memory path;
if (address(token) == address(wsonic)) {
path = new address[](2);
path[0] = address(blur);
path[1] = token;
} else {
path = new address[](3);
path[0] = address(blur);
path[1] = address(wsonic);
path[2] = token;
}
uint256[] memory amounts = router.getAmountsOut(amountBlur, path);
return amounts[path.length - 1];
}
function getAmountBlur(
uint256 amountToken,
address token
) external view returns (uint256) {
address[] memory path;
if (address(token) == address(wsonic)) {
path = new address[](2);
path[0] = token;
path[1] = address(blur);
} else {
path = new address[](3);
path[0] = token;
path[1] = address(wsonic);
path[2] = address(blur);
}
uint256[] memory amounts = router.getAmountsOut(amountToken, path);
return amounts[path.length - 1];
}
function setBlur(IERC20 _blur) external onlyOwner {
blur = _blur;
}
function setWSonic(IWSonic _wsonic) external onlyOwner {
wsonic = _wsonic;
}
function setRouter(IRouter02 _router) external onlyOwner {
router = _router;
}
function withdrawAsset(
IERC20 _token,
uint256 _amount,
uint256 _amountSonic,
address to
) external onlyOwner {
if (_amount > 0) {
_token.transfer(to, _amount);
}
if (_amountSonic > 0) {
payable(to).transfer(_amountSonic);
}
}
receive() external payable {}
}