Transaction Hash:
Block:
24412131 at Feb-08-2026 12:41:35 PM +UTC
Transaction Fee:
0.000005412212695873 ETH
$0.01
Gas Used:
59,597 Gas / 0.090813509 Gwei
Emitted Events:
| 529 |
Bridgers.SwapEth( toToken=USDT(TRON), sender=[Receiver] TransitSwapRouterV5, destination=TJ8XzxrqV3UMPXxBv3SiQ2STV9Hhb5VMEC, fromAmount=1359137239240000000, minReturnAmount=2886756735 )
|
| 530 |
TransitSwapRouterV5.TransitSwapped( srcToken=0xEeeeeEee...eeeeeEEeE, dstToken=0xa614f803...7e6DeD13C, dstReceiver=0x59849Be4...CD6711eD5, amount=1363226920000000000, returnAmount=0, toChainID=728126428, channel=ios )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x00000047...1EE0b1A34 | (Transit Finance: Router V5) | 4.493807869236026117 Eth | 4.497897549996026117 Eth | 0.00408968076 | |
| 0x29295486...1D47C25F4 |
3.232573168263587468 Eth
Nonce: 196
|
1.869340836050891595 Eth
Nonce: 197
| 1.363232332212695873 | ||
|
0x4838B106...B0BAD5f97
Miner
| (Titan Builder) | 18.863685937739104572 Eth | 18.863687998794074972 Eth | 0.0000020610549704 | |
| 0xB685760E...2A289895b | 21.539625323993661043 Eth | 22.898762563233661043 Eth | 1.35913723924 |
Execution Trace
ETH 1.36322692
TransitSwapRouterV5.cross( desc=[{name:srcToken, type:address, order:1, indexed:false, value:0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, valueString:0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE}, {name:dstToken, type:address, order:2, indexed:false, value:0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C, valueString:0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C}, {name:caller, type:address, order:3, indexed:false, value:0xB685760EBD368a891F27ae547391F4E2A289895b, valueString:0xB685760EBD368a891F27ae547391F4E2A289895b}, {name:dstReceiver, type:address, order:4, indexed:false, value:0x59849Be4bC95Bf0539AF25EdeceD39DCD6711eD5, valueString:0x59849Be4bC95Bf0539AF25EdeceD39DCD6711eD5}, {name:wrappedToken, type:address, order:5, indexed:false, value:0x0000000000000000000000000000000000000000, valueString:0x0000000000000000000000000000000000000000}, {name:amount, type:uint256, order:6, indexed:false, value:1363226920000000000, valueString:1363226920000000000}, {name:fee, type:uint256, order:7, indexed:false, value:4089680760000000, valueString:4089680760000000}, {name:toChain, type:uint256, order:8, indexed:false, value:728126428, valueString:728126428}, {name:channel, type:string, order:9, indexed:false, value:ios, valueString:ios}, {name:calls, type:bytes, order:10, indexed:false, value:0x16B3B4C2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000AC10697F000000000000000000000000000000000000000000000000000000000000000A555344542854524F4E29000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022544A38587A7872715633554D505878427633536951325354563948686235564D4543000000000000000000000000000000000000000000000000000000000000, valueString:0x16B3B4C2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000AC10697F000000000000000000000000000000000000000000000000000000000000000A555344542854524F4E29000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022544A38587A7872715633554D505878427633536951325354563948686235564D4543000000000000000000000000000000000000000000000000000000000000}, {name:signature, type:bytes, order:11, indexed:false, value:0x, valueString:0x}] )
- ETH 1.35913723924
Bridgers.swapEth( toToken=USDT(TRON), destination=TJ8XzxrqV3UMPXxBv3SiQ2STV9Hhb5VMEC, minReturnAmount=2886756735 )
cross[CrossRouter (ln:27)]
calculateTradeFee[CrossRouter (ln:32)]isETH[CrossRouter (ln:33)]safeDeposit[CrossRouter (ln:38)]call[TransferHelper (ln:833)]encodeWithSelector[TransferHelper (ln:833)]decode[TransferHelper (ln:834)]
safeApprove[CrossRouter (ln:39)]call[TransferHelper (ln:808)]encodeWithSelector[TransferHelper (ln:808)]decode[TransferHelper (ln:809)]
safeTransferFrom[CrossRouter (ln:43)]call[TransferHelper (ln:823)]encodeWithSelector[TransferHelper (ln:823)]decode[TransferHelper (ln:824)]
safeApprove[CrossRouter (ln:44)]call[TransferHelper (ln:808)]encodeWithSelector[TransferHelper (ln:808)]decode[TransferHelper (ln:809)]
call[CrossRouter (ln:47)]revert[CrossRouter (ln:49)]_emitTransit[CrossRouter (ln:52)]
File 1 of 2: TransitSwapRouterV5
File 2 of 2: Bridgers
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./UniswapV2Router.sol";
import "./UniswapV3Router.sol";
import "./AggregateRouter.sol";
import "./CrossRouter.sol";
contract TransitSwapRouterV5 is UniswapV2Router, UniswapV3Router, AggregateRouter, CrossRouter {
function withdrawTokens(address[] memory tokens, address recipient) external onlyExecutor {
for (uint index; index < tokens.length; index++) {
uint amount;
if (TransferHelper.isETH(tokens[index])) {
amount = address(this).balance;
TransferHelper.safeTransferETH(recipient, amount);
} else {
amount = IERC20(tokens[index]).balanceOf(address(this));
TransferHelper.safeTransferWithoutRequire(tokens[index], recipient, amount);
}
emit Withdraw(tokens[index], msg.sender, recipient, amount);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./BaseCore.sol";
contract CrossRouter is BaseCore {
using SafeMath for uint256;
constructor() {}
function cross(CrossDescription calldata desc) external payable nonReentrant whenNotPaused {
require(desc.calls.length > 0, "data should be not zero");
require(desc.amount > 0, "amount should be greater than 0");
require(_cross_caller_allowed[desc.caller], "invalid caller");
uint256 swapAmount;
uint256 actualAmountIn = calculateTradeFee(false, desc.amount, desc.fee, desc.signature);
if (TransferHelper.isETH(desc.srcToken)) {
require(msg.value == desc.amount, "invalid msg.value");
swapAmount = actualAmountIn;
if (desc.wrappedToken != address(0)) {
require(_wrapped_allowed[desc.wrappedToken], "Invalid wrapped address");
TransferHelper.safeDeposit(desc.wrappedToken, swapAmount);
TransferHelper.safeApprove(desc.wrappedToken, desc.caller, swapAmount);
swapAmount = 0;
}
} else {
TransferHelper.safeTransferFrom(desc.srcToken, msg.sender, address(this), desc.amount);
TransferHelper.safeApprove(desc.srcToken, desc.caller, actualAmountIn);
}
{
(bool success, bytes memory result) = desc.caller.call{value:swapAmount}(desc.calls);
if (!success) {
revert(RevertReasonParser.parse(result, "TransitCrossV5:"));
}
}
_emitTransit(desc.srcToken, desc.dstToken, desc.dstReceiver, desc.amount, 0, desc.toChain, desc.channel);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./BaseCore.sol";
contract AggregateRouter is BaseCore {
using SafeMath for uint256;
constructor() {
}
function aggregateAndGasUsed(TransitSwapDescription calldata desc, CallbytesDescription calldata callbytesDesc) external payable returns (uint256 returnAmount, uint256 gasUsed) {
uint256 gasLeftBefore = gasleft();
returnAmount = _executeAggregate(desc, callbytesDesc);
gasUsed = gasLeftBefore - gasleft();
}
function aggregate(TransitSwapDescription calldata desc, CallbytesDescription calldata callbytesDesc) external payable returns (uint256 returnAmount) {
returnAmount = _executeAggregate(desc, callbytesDesc);
}
function _executeAggregate(TransitSwapDescription calldata desc, CallbytesDescription calldata callbytesDesc) internal nonReentrant whenNotPaused returns (uint256 returnAmount) {
require(callbytesDesc.calldatas.length > 0, "data should be not zero");
require(desc.amount > 0, "amount should be greater than 0");
require(desc.dstReceiver != address(0), "receiver should be not address(0)");
require(desc.minReturnAmount > 0, "minReturnAmount should be greater than 0");
require(_wrapped_allowed[desc.wrappedToken], "invalid wrapped address");
uint256 actualAmountIn = calculateTradeFee(true, desc.amount, desc.fee, desc.signature);
uint256 swapAmount;
uint256 toBeforeBalance;
address bridgeAddress = _aggregate_bridge;
if (TransferHelper.isETH(desc.srcToken)) {
require(msg.value == desc.amount, "invalid msg.value");
swapAmount = actualAmountIn;
} else {
TransferHelper.safeTransferFrom(desc.srcToken, msg.sender, address(this), desc.amount);
TransferHelper.safeTransfer(desc.srcToken, bridgeAddress, actualAmountIn);
}
if (TransferHelper.isETH(desc.dstToken)) {
toBeforeBalance = desc.dstReceiver.balance;
} else {
toBeforeBalance = IERC20(desc.dstToken).balanceOf(desc.dstReceiver);
}
{
//bytes4(keccak256(bytes('callbytes(CallbytesDescription)')));
(bool success, bytes memory result) = bridgeAddress.call{value : swapAmount}(abi.encodeWithSelector(0x3f3204d2, callbytesDesc));
if (!success) {
revert(RevertReasonParser.parse(result, "TransitSwap:"));
}
}
if (TransferHelper.isETH(desc.dstToken)) {
returnAmount = desc.dstReceiver.balance.sub(toBeforeBalance);
} else {
returnAmount = IERC20(desc.dstToken).balanceOf(desc.dstReceiver).sub(toBeforeBalance);
}
require(returnAmount >= desc.minReturnAmount, "Too little received");
_emitTransit(desc.srcToken, desc.dstToken, desc.dstReceiver, desc.amount, returnAmount, 0, desc.channel);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./BaseCore.sol";
contract UniswapV3Router is BaseCore {
using SafeMath for uint256;
uint256 private constant _ZERO_FOR_ONE_MASK = 1 << 255;
uint160 private constant MIN_SQRT_RATIO = 4295128739;
uint160 private constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
constructor() {}
fallback() external {
(int256 amount0Delta, int256 amount1Delta, bytes memory _data) = abi.decode(msg.data[4:], (int256,int256,bytes));
_executeCallback(amount0Delta, amount1Delta, _data);
}
function pancakeV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata _data
) external {
_executeCallback(amount0Delta, amount1Delta, _data);
}
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata _data
) external {
_executeCallback(amount0Delta, amount1Delta, _data);
}
function _executeCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes memory _data
) internal {
require(amount0Delta > 0 || amount1Delta > 0, "M0 or M1"); // swaps entirely within 0-liquidity regions are not supported
(uint256 pool, bytes memory tokenInAndPoolSalt) = abi.decode(_data, (uint256, bytes));
(address tokenIn, bytes32 poolSalt) = abi.decode(tokenInAndPoolSalt, (address, bytes32));
_verifyCallback(pool, poolSalt, msg.sender);
uint256 amountToPay = uint256(amount1Delta);
if (amount0Delta > 0) {
amountToPay = uint256(amount0Delta);
}
TransferHelper.safeTransfer(tokenIn, msg.sender, amountToPay);
}
function exactInputV3SwapAndGasUsed(ExactInputV3SwapParams calldata params) external payable returns (uint256 returnAmount, uint256 gasUsed) {
uint256 gasLeftBefore = gasleft();
returnAmount = _executeV3Swap(params);
gasUsed = gasLeftBefore - gasleft();
}
function exactInputV3Swap(ExactInputV3SwapParams calldata params) external payable returns (uint256 returnAmount) {
returnAmount = _executeV3Swap(params);
}
function _executeV3Swap(ExactInputV3SwapParams calldata params) internal nonReentrant whenNotPaused returns (uint256 returnAmount) {
require(params.pools.length > 0, "Empty pools");
require(params.deadline >= block.timestamp, "Expired");
require(_wrapped_allowed[params.wrappedToken], "Invalid wrapped address");
address tokenIn = params.srcToken;
address tokenOut = params.dstToken;
uint256 actualAmountIn = calculateTradeFee(true, params.amount, params.fee, params.signature);
uint256 toBeforeBalance;
bool isToETH;
if (TransferHelper.isETH(params.srcToken)) {
tokenIn = params.wrappedToken;
require(msg.value == params.amount, "Invalid msg.value");
TransferHelper.safeDeposit(params.wrappedToken, actualAmountIn);
} else {
TransferHelper.safeTransferFrom(params.srcToken, msg.sender, address(this), params.amount);
}
if (TransferHelper.isETH(params.dstToken)) {
tokenOut = params.wrappedToken;
toBeforeBalance = IERC20(params.wrappedToken).balanceOf(address(this));
isToETH = true;
} else {
toBeforeBalance = IERC20(params.dstToken).balanceOf(params.dstReceiver);
}
{
uint256 len = params.pools.length;
address recipient = address(this);
bytes memory tokenInAndPoolSalt;
if (len > 1) {
address thisTokenIn = tokenIn;
address thisTokenOut = address(0);
for (uint256 i; i < len; i++) {
uint256 thisPool = params.pools[i];
(thisTokenIn, tokenInAndPoolSalt) = _verifyPool(thisTokenIn, thisTokenOut, thisPool);
if (i == len - 1 && !isToETH) {
recipient = params.dstReceiver;
thisTokenOut = tokenOut;
}
actualAmountIn = _swap(recipient, thisPool, tokenInAndPoolSalt, actualAmountIn);
}
returnAmount = actualAmountIn;
} else {
(, tokenInAndPoolSalt) = _verifyPool(tokenIn, tokenOut, params.pools[0]);
if (!isToETH) {
recipient = params.dstReceiver;
}
returnAmount = _swap(recipient, params.pools[0], tokenInAndPoolSalt, actualAmountIn);
}
}
if (isToETH) {
returnAmount = IERC20(params.wrappedToken).balanceOf(address(this)).sub(toBeforeBalance);
require(returnAmount >= params.minReturnAmount, "Too little received");
TransferHelper.safeWithdraw(params.wrappedToken, returnAmount);
TransferHelper.safeTransferETH(params.dstReceiver, returnAmount);
} else {
returnAmount = IERC20(params.dstToken).balanceOf(params.dstReceiver).sub(toBeforeBalance);
require(returnAmount >= params.minReturnAmount, "Too little received");
}
_emitTransit(params.srcToken, params.dstToken, params.dstReceiver, params.amount, returnAmount, 0, params.channel);
}
function _swap(address recipient, uint256 pool, bytes memory tokenInAndPoolSalt, uint256 amount) internal returns (uint256 amountOut) {
bool zeroForOne = pool & _ZERO_FOR_ONE_MASK == 0;
if (zeroForOne) {
(, int256 amount1) =
IUniswapV3Pool(address(uint160(pool))).swap(
recipient,
zeroForOne,
amount.toInt256(),
MIN_SQRT_RATIO + 1,
abi.encode(pool, tokenInAndPoolSalt)
);
amountOut = SafeMath.toUint256(-amount1);
} else {
(int256 amount0,) =
IUniswapV3Pool(address(uint160(pool))).swap(
recipient,
zeroForOne,
amount.toInt256(),
MAX_SQRT_RATIO - 1,
abi.encode(pool, tokenInAndPoolSalt)
);
amountOut = SafeMath.toUint256(-amount0);
}
}
function _verifyPool(address tokenIn, address tokenOut, uint256 pool) internal view returns (address nextTokenIn, bytes memory tokenInAndPoolSalt) {
IUniswapV3Pool iPool = IUniswapV3Pool(address(uint160(pool)));
address token0 = iPool.token0();
address token1 = iPool.token1();
uint24 fee = iPool.fee();
bytes32 poolSalt = keccak256(abi.encode(token0, token1, fee));
bool zeroForOne = pool & _ZERO_FOR_ONE_MASK == 0;
if (zeroForOne) {
require(tokenIn == token0, "Bad pool");
if (tokenOut != address(0)) {
require(tokenOut == token1, "Bad pool");
}
nextTokenIn = token1;
tokenInAndPoolSalt = abi.encode(token0, poolSalt);
} else {
require(tokenIn == token1, "Bad pool");
if (tokenOut != address(0)) {
require(tokenOut == token0, "Bad pool");
}
nextTokenIn = token0;
tokenInAndPoolSalt = abi.encode(token1, poolSalt);
}
}
function _verifyCallback(uint256 pool, bytes32 poolSalt, address caller) internal view {
uint poolDigit = pool >> 248 & 0xf;
UniswapV3Pool memory v3Pool = _uniswapV3_factory_allowed[poolDigit];
require(v3Pool.factory != address(0), "Callback bad pool indexed");
address calcPool = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex'ff',
v3Pool.factory,
poolSalt,
v3Pool.initCodeHash
)
)
)
)
);
require(calcPool == caller, "Callback bad pool");
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./BaseCore.sol";
contract UniswapV2Router is BaseCore {
using SafeMath for uint256;
constructor() {
}
function _beforeSwap(ExactInputV2SwapParams calldata exactInput, bool supportingFeeOn) internal returns (bool isToETH, uint256 actualAmountIn, address[] memory paths, uint256 thisAddressBeforeBalance, uint256 toBeforeBalance) {
require(exactInput.path.length == exactInput.pool.length + 1, "Invalid path");
require(_wrapped_allowed[exactInput.wrappedToken], "Invalid wrapped address");
actualAmountIn = calculateTradeFee(true, exactInput.amount, exactInput.fee, exactInput.signature);
//检查第一个或最后一个是否为ETH
address[] memory path = exactInput.path;
address dstToken = path[exactInput.path.length - 1];
if (TransferHelper.isETH(exactInput.path[0])) {
require(msg.value == exactInput.amount, "Invalid msg.value");
path[0] = exactInput.wrappedToken;
TransferHelper.safeDeposit(exactInput.wrappedToken, actualAmountIn);
} else {
if (supportingFeeOn) {
actualAmountIn = IERC20(path[0]).balanceOf(address(this));
TransferHelper.safeTransferFrom(path[0], msg.sender, address(this), exactInput.amount);
actualAmountIn = IERC20(path[0]).balanceOf(address(this)).sub(actualAmountIn).sub(exactInput.fee);
} else {
TransferHelper.safeTransferFrom(path[0], msg.sender, address(this), exactInput.amount);
}
}
if (TransferHelper.isETH(dstToken)) {
path[path.length - 1] = exactInput.wrappedToken;
isToETH = true;
thisAddressBeforeBalance = IERC20(exactInput.wrappedToken).balanceOf(address(this));
} else {
if (supportingFeeOn) {
toBeforeBalance = IERC20(dstToken).balanceOf(exactInput.dstReceiver);
}
}
paths = path;
}
function exactInputV2SwapAndGasUsed(ExactInputV2SwapParams calldata exactInput, uint256 deadline) external payable returns (uint256 returnAmount, uint256 gasUsed) {
uint256 gasLeftBefore = gasleft();
returnAmount = _executeV2Swap(exactInput, deadline);
gasUsed = gasLeftBefore - gasleft();
}
function exactInputV2Swap(ExactInputV2SwapParams calldata exactInput, uint256 deadline) external payable returns (uint256 returnAmount) {
returnAmount = _executeV2Swap(exactInput, deadline);
}
function _executeV2Swap(ExactInputV2SwapParams calldata exactInput, uint256 deadline) internal nonReentrant whenNotPaused returns (uint256 returnAmount) {
require(deadline >= block.timestamp, "Expired");
bool supportingFeeOn = exactInput.router >> 248 & 0xf == 1;
{
(bool isToETH, uint256 actualAmountIn, address[] memory paths, uint256 thisAddressBeforeBalance, uint256 toBeforeBalance) = _beforeSwap(exactInput, supportingFeeOn);
TransferHelper.safeTransfer(paths[0], exactInput.pool[0], actualAmountIn);
if (supportingFeeOn) {
if(isToETH) {
_swapSupportingFeeOnTransferTokens(address(uint160(exactInput.router)), paths, exactInput.pool, address(this));
returnAmount = IERC20(exactInput.wrappedToken).balanceOf(address(this)).sub(thisAddressBeforeBalance);
} else {
_swapSupportingFeeOnTransferTokens(address(uint160(exactInput.router)), paths, exactInput.pool, exactInput.dstReceiver);
returnAmount = IERC20(paths[paths.length - 1]).balanceOf(exactInput.dstReceiver).sub(toBeforeBalance);
}
} else {
uint[] memory amounts = IUniswapV2(address(uint160(exactInput.router))).getAmountsOut(actualAmountIn, paths);
if(isToETH) {
_swap(amounts, paths, exactInput.pool, address(this));
returnAmount = IERC20(exactInput.wrappedToken).balanceOf(address(this)).sub(thisAddressBeforeBalance);
} else {
_swap(amounts, paths, exactInput.pool, exactInput.dstReceiver);
returnAmount = amounts[amounts.length - 1];
}
}
require(returnAmount >= exactInput.minReturnAmount, "Too little received");
if (isToETH) {
TransferHelper.safeWithdraw(exactInput.wrappedToken, returnAmount);
TransferHelper.safeTransferETH(exactInput.dstReceiver, returnAmount);
}
}
string memory channel = exactInput.channel;
_emitTransit(exactInput.path[0], exactInput.path[exactInput.path.length - 1], exactInput.dstReceiver, exactInput.amount, returnAmount, 0, channel);
}
function _swap(uint[] memory amounts, address[] memory path, address[] memory pool, address _to) internal {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = input < output ? (input, output) : (output, input);
uint amountOut = amounts[i + 1];
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
address to = i < path.length - 2 ? pool[i + 1] : _to;
IUniswapV2(pool[i]).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
function _swapSupportingFeeOnTransferTokens(address router, address[] memory path, address[] memory pool, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = input < output ? (input, output) : (output, input);
IUniswapV2 pair = IUniswapV2(pool[i]);
uint amountInput;
uint amountOutput;
{ // scope to avoid stack too deep errors
(uint reserve0, uint reserve1,) = pair.getReserves();
(uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
amountInput = IERC20(input).balanceOf(address(pair)).sub(reserveInput);
amountOutput = IUniswapV2(router).getAmountOut(amountInput, reserveInput, reserveOutput);
}
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
address to = i < path.length - 2 ? pool[i + 1] : _to;
pair.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./libs/Pausable.sol";
import "./libs/ReentrancyGuard.sol";
import "./libs/TransferHelper.sol";
import "./libs/RevertReasonParser.sol";
import "./libs/SafeMath.sol";
import "./libs/Ownable.sol";
import "./interfaces/IERC20.sol";
import "./interfaces/IUniswapV2.sol";
import "./interfaces/IUniswapV3Pool.sol";
contract BaseCore is Ownable, Pausable, ReentrancyGuard {
using SafeMath for uint256;
struct ExactInputV2SwapParams {
address dstReceiver;
address wrappedToken;
uint256 router;
uint256 amount;
uint256 minReturnAmount;
uint256 fee;
address[] path;
address[] pool;
bytes signature;
string channel;
}
struct ExactInputV3SwapParams {
address srcToken;
address dstToken;
address dstReceiver;
address wrappedToken;
uint256 amount;
uint256 minReturnAmount;
uint256 fee;
uint256 deadline;
uint256[] pools;
bytes signature;
string channel;
}
struct TransitSwapDescription {
address srcToken;
address dstToken;
address dstReceiver;
address wrappedToken;
uint256 amount;
uint256 minReturnAmount;
uint256 fee;
string channel;
bytes signature;
}
struct CrossDescription {
address srcToken;
address dstToken;
address caller;
address dstReceiver;
address wrappedToken;
uint256 amount;
uint256 fee;
uint256 toChain;
string channel;
bytes calls;
bytes signature;
}
struct CallbytesDescription {
address srcToken;
bytes calldatas;
}
struct UniswapV3Pool {
address factory;
bytes initCodeHash;
}
uint256 internal _aggregate_fee;
uint256 internal _cross_fee;
address internal _aggregate_bridge;
address internal _fee_signer;
bytes32 public DOMAIN_SEPARATOR;
//whitelist cross's caller
mapping(address => bool) internal _cross_caller_allowed;
//whitelist wrapped
mapping(address => bool) internal _wrapped_allowed;
//whitelist uniswap v3 factory
mapping(uint => UniswapV3Pool) internal _uniswapV3_factory_allowed;
bytes32 public constant CHECKFEE_TYPEHASH = keccak256("CheckFee(address payer,uint256 amount,uint256 fee)");
event Receipt(address from, uint256 amount);
event Withdraw(address indexed token, address indexed executor, address indexed recipient, uint amount);
event ChangeWrappedAllowed(address[] wrappedTokens, bool[] newAllowed);
event ChangeV3FactoryAllowed(uint256[] poolIndex, address[] factories, bytes[] initCodeHash);
event ChangeCrossCallerAllowed(address[] callers);
event ChangeFeeRate(bool isAggregate, uint256 newRate);
event ChangeSigner(address preSigner, address newSigner);
event ChangeAggregateBridge(address newBridge);
event TransitSwapped(address indexed srcToken, address indexed dstToken, address indexed dstReceiver, uint256 amount, uint256 returnAmount, uint256 toChainID, string channel);
constructor() Ownable(msg.sender) {
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes("TransitSwapV5")),
keccak256(bytes("5")),
block.chainid,
address(this)
)
);
}
receive() external payable {
emit Receipt(msg.sender, msg.value);
}
function calculateTradeFee(bool isAggregate, uint256 tradeAmount, uint256 fee, bytes calldata signature) internal view returns (uint256) {
uint256 thisFee;
if (isAggregate) {
thisFee = tradeAmount.mul(_aggregate_fee).div(10000);
} else {
thisFee = tradeAmount.mul(_cross_fee).div(10000);
}
if (fee < thisFee) {
require(verifySignature(tradeAmount, fee, signature), "Invalid signature fee");
}
return tradeAmount.sub(fee);
}
function _emitTransit(address srcToken, address dstToken, address dstReceiver, uint256 amount, uint256 returnAmount, uint256 toChainID, string memory channel) internal {
emit TransitSwapped (
srcToken,
dstToken,
dstReceiver,
amount,
returnAmount,
toChainID,
channel
);
}
function changeFee(bool[] memory isAggregate, uint256[] memory newRate) external onlyExecutor {
for (uint i; i < isAggregate.length; i++) {
require(newRate[i] >= 0 && newRate[i] <= 1000, "fee rate is:0-1000");
if (isAggregate[i]) {
_aggregate_fee = newRate[i];
} else {
_cross_fee = newRate[i];
}
emit ChangeFeeRate(isAggregate[i], newRate[i]);
}
}
function changeTransitProxy(address aggregator, address signer) external onlyExecutor {
if (aggregator != address(0)) {
_aggregate_bridge = aggregator;
emit ChangeAggregateBridge(aggregator);
}
if (signer != address(0)) {
address preSigner = _fee_signer;
_fee_signer = signer;
emit ChangeSigner(preSigner, signer);
}
}
function changeAllowed(address[] calldata crossCallers, address[] calldata wrappedTokens) public onlyExecutor {
if(crossCallers.length != 0){
for (uint i; i < crossCallers.length; i++) {
_cross_caller_allowed[crossCallers[i]] = !_cross_caller_allowed[crossCallers[i]];
}
emit ChangeCrossCallerAllowed(crossCallers);
}
if(wrappedTokens.length != 0) {
bool[] memory newAllowed = new bool[](wrappedTokens.length);
for (uint index; index < wrappedTokens.length; index++) {
_wrapped_allowed[wrappedTokens[index]] = !_wrapped_allowed[wrappedTokens[index]];
newAllowed[index] = _wrapped_allowed[wrappedTokens[index]];
}
emit ChangeWrappedAllowed(wrappedTokens, newAllowed);
}
}
function changeUniswapV3FactoryAllowed(uint[] calldata poolIndex, address[] calldata factories, bytes[] calldata initCodeHash) public onlyExecutor {
require(poolIndex.length == initCodeHash.length, "invalid data");
require(factories.length == initCodeHash.length, "invalid data");
uint len = factories.length;
for (uint i; i < len; i++) {
_uniswapV3_factory_allowed[poolIndex[i]] = UniswapV3Pool(factories[i],initCodeHash[i]);
}
emit ChangeV3FactoryAllowed(poolIndex, factories, initCodeHash);
}
function changePause(bool paused) external onlyExecutor {
if (paused) {
_pause();
} else {
_unpause();
}
}
function transitProxyAddress() external view returns (address bridgeProxy, address feeSigner) {
bridgeProxy = _aggregate_bridge;
feeSigner = _fee_signer;
}
function transitFee() external view returns (uint256, uint256) {
return (_aggregate_fee, _cross_fee);
}
function transitAllowedQuery(address crossCaller, address wrappedToken, uint256 poolIndex) external view returns (bool isCrossCallerAllowed, bool isWrappedAllowed, UniswapV3Pool memory pool) {
isCrossCallerAllowed = _cross_caller_allowed[crossCaller];
isWrappedAllowed = _wrapped_allowed[wrappedToken];
pool = _uniswapV3_factory_allowed[poolIndex];
}
function verifySignature(uint256 amount, uint256 fee, bytes calldata signature) internal view returns (bool) {
bytes32 digest = keccak256(
abi.encodePacked(
"\\x19\\x01",
DOMAIN_SEPARATOR,
keccak256(abi.encode(CHECKFEE_TYPEHASH, msg.sender, amount, fee))
)
);
(uint8 v, bytes32 r, bytes32 s) = splitSignature(signature);
address recovered = ecrecover(digest, v, r, s);
return recovered == _fee_signer;
}
function splitSignature(bytes memory _signature) internal pure returns (uint8 v, bytes32 r, bytes32 s) {
require(bytes(_signature).length == 65, "Invalid signature length");
assembly {
r := mload(add(_signature, 0x20))
s := mload(add(_signature, 0x40))
v := byte(0, mload(add(_signature, 0x60)))
}
return (v, r, s);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
interface IUniswapV3Pool {
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.9;
interface IUniswapV2 {
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountsOut(uint amountIn, address[] memory path) external view returns (uint[] memory amounts);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.9;
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
// Add executor extension
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable {
address private _executor;
address private _pendingExecutor;
bool internal _initialized;
event ExecutorshipTransferStarted(address indexed previousExecutor, address indexed newExecutor);
event ExecutorshipTransferred(address indexed previousExecutor, address indexed newExecutor);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor(address newExecutor) {
require(!_initialized, "Ownable: initialized");
_transferExecutorship(newExecutor);
_initialized = true;
}
/**
* @dev Throws if called by any account other than the executor.
*/
modifier onlyExecutor() {
_checkExecutor();
_;
}
/**
* @dev Returns the address of the current executor.
*/
function executor() public view virtual returns (address) {
return _executor;
}
/**
* @dev Returns the address of the pending executor.
*/
function pendingExecutor() public view virtual returns (address) {
return _pendingExecutor;
}
/**
* @dev Throws if the sender is not the executor.
*/
function _checkExecutor() internal view virtual {
require(executor() == msg.sender, "Ownable: caller is not the executor");
}
/**
* @dev Transfers executorship of the contract to a new account (`newExecutor`).
* Can only be called by the current executor.
*/
function transferExecutorship(address newExecutor) public virtual onlyExecutor {
_pendingExecutor = newExecutor;
emit ExecutorshipTransferStarted(executor(), newExecutor);
}
function _transferExecutorship(address newExecutor) internal virtual {
delete _pendingExecutor;
address oldExecutor = _executor;
_executor = newExecutor;
emit ExecutorshipTransferred(oldExecutor, newExecutor);
}
function acceptExecutorship() external {
address sender = msg.sender;
require(pendingExecutor() == sender, "Ownable: caller is not the new executor");
_transferExecutorship(sender);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
function div(uint x, uint y) internal pure returns (uint z) {
require(y != 0 , 'ds-math-div-zero');
z = x / y;
}
function toInt256(uint256 value) internal pure returns (int256) {
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
library RevertReasonParser {
function parse(bytes memory data, string memory prefix) internal pure returns (string memory) {
// https://solidity.readthedocs.io/en/latest/control-structures.html#revert
// We assume that revert reason is abi-encoded as Error(string)
// 68 = 4-byte selector 0x08c379a0 + 32 bytes offset + 32 bytes length
if (data.length >= 68 && data[0] == "\\x08" && data[1] == "\\xc3" && data[2] == "\\x79" && data[3] == "\\xa0") {
string memory reason;
// solhint-disable no-inline-assembly
assembly {
// 68 = 32 bytes data length + 4-byte selector + 32 bytes offset
reason := add(data, 68)
}
/*
revert reason is padded up to 32 bytes with ABI encoder: Error(string)
also sometimes there is extra 32 bytes of zeros padded in the end:
https://github.com/ethereum/solidity/issues/10170
because of that we can't check for equality and instead check
that string length + extra 68 bytes is less than overall data length
*/
require(data.length >= 68 + bytes(reason).length, "Invalid revert reason");
return string(abi.encodePacked(prefix, "Error(", reason, ")"));
}
// 36 = 4-byte selector 0x4e487b71 + 32 bytes integer
else if (data.length == 36 && data[0] == "\\x4e" && data[1] == "\\x48" && data[2] == "\\x7b" && data[3] == "\\x71") {
uint256 code;
// solhint-disable no-inline-assembly
assembly {
// 36 = 32 bytes data length + 4-byte selector
code := mload(add(data, 36))
}
return string(abi.encodePacked(prefix, "Panic(", _toHex(code), ")"));
}
return string(abi.encodePacked(prefix, "Unknown(", _toHex(data), ")"));
}
function _toHex(uint256 value) private pure returns(string memory) {
return _toHex(abi.encodePacked(value));
}
function _toHex(bytes memory data) private pure returns(string memory) {
bytes16 alphabet = 0x30313233343536373839616263646566;
bytes memory str = new bytes(2 + data.length * 2);
str[0] = "0";
str[1] = "x";
for (uint256 i = 0; i < data.length; i++) {
str[2 * i + 2] = alphabet[uint8(data[i] >> 4)];
str[2 * i + 3] = alphabet[uint8(data[i] & 0x0f)];
}
return string(str);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
library TransferHelper {
address private constant _ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
address private constant _ZERO_ADDRESS = address(0);
function isETH(address token) internal pure returns (bool) {
return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS);
}
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_TOKEN_FAILED');
}
function safeTransferWithoutRequire(address token, address to, uint256 value) internal returns (bool) {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
return (success && (data.length == 0 || abi.decode(data, (bool))));
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
// solium-disable-next-line
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: TRANSFER_FAILED');
}
function safeDeposit(address wrapped, uint value) internal {
// bytes4(keccak256(bytes('deposit()')));
(bool success, bytes memory data) = wrapped.call{value:value}(abi.encodeWithSelector(0xd0e30db0));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: DEPOSIT_FAILED');
}
function safeWithdraw(address wrapped, uint value) internal {
// bytes4(keccak256(bytes('withdraw(uint256 wad)')));
(bool success, bytes memory data) = wrapped.call{value:0}(abi.encodeWithSelector(0x2e1a7d4d, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: WITHDRAW_FAILED');
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
assembly {
sstore(_status.slot, _ENTERED)
}
_;
assembly {
sstore(_status.slot, _NOT_ENTERED)
}
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(msg.sender);
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(msg.sender);
}
}File 2 of 2: Bridgers
{"Bridgers.sol":{"content":"// SPDX-License-Identifier: MIT\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC20.sol\";\r\nimport \"./Ownable.sol\";\r\nimport \"./ReentrancyGuard.sol\";\r\nimport \"./SafeMath.sol\";\r\nimport \"./TransferHelper.sol\";\r\n\r\n\r\ncontract Bridgers is ReentrancyGuard, Ownable {\r\n using SafeMath for uint256;\r\n\r\n string public name;\r\n\r\n string public symbol;\r\n\r\n event Swap(\r\n address fromToken,\r\n string toToken,\r\n address sender,\r\n string destination,\r\n uint256 fromAmount,\r\n uint256 minReturnAmount\r\n );\r\n\r\n\r\n event SwapEth(\r\n string toToken,\r\n address sender,\r\n string destination,\r\n uint256 fromAmount,\r\n uint256 minReturnAmount\r\n );\r\n\r\n event WithdrawETH(uint256 amount);\r\n\r\n event Withdtraw(address token, uint256 amount);\r\n\r\n constructor() {\r\n name = \"Bridgers1.1\";\r\n symbol = \"Bridgers\";\r\n }\r\n\r\n\r\n function swap(\r\n address fromToken,\r\n string memory toToken,\r\n string memory destination,\r\n uint256 fromAmount,\r\n uint256 minReturnAmount\r\n ) external nonReentrant {\r\n require(fromToken != address(0), \"FROMTOKEN_CANT_T_BE_0\");\r\n require(fromAmount \u003e 0, \"FROM_TOKEN_AMOUNT_MUST_BE_MORE_THAN_0\");\r\n uint256 _inputAmount;\r\n uint256 _fromTokenBalanceOrigin = IERC20(fromToken).balanceOf(address(this));\r\n TransferHelper.safeTransferFrom(fromToken, msg.sender, address(this), fromAmount);\r\n uint256 _fromTokenBalanceNew = IERC20(fromToken).balanceOf(address(this));\r\n _inputAmount = _fromTokenBalanceNew.sub(_fromTokenBalanceOrigin);\r\n require(_inputAmount \u003e 0, \"NO_FROM_TOKEN_TRANSFER_TO_THIS_CONTRACT\");\r\n emit Swap(fromToken, toToken, msg.sender, destination, fromAmount, minReturnAmount);\r\n }\r\n\r\n\r\n function swapEth(string memory toToken, string memory destination, uint256 minReturnAmount\r\n ) external payable nonReentrant {\r\n uint256 _ethAmount = msg.value;\r\n require(_ethAmount \u003e 0, \"ETH_AMOUNT_MUST_BE_MORE_THAN_0\");\r\n emit SwapEth(toToken, msg.sender, destination, _ethAmount, minReturnAmount);\r\n }\r\n\r\n function withdrawETH(address destination, uint256 amount) external onlyOwner {\r\n require(destination != address(0), \"DESTINATION_CANNT_BE_0_ADDRESS\");\r\n uint256 balance = address(this).balance;\r\n require(balance \u003e= amount, \"AMOUNT_CANNT_MORE_THAN_BALANCE\");\r\n TransferHelper.safeTransferETH(destination, amount);\r\n emit WithdrawETH(amount);\r\n }\r\n\r\n function withdraw(address token, address destination, uint256 amount) external onlyOwner {\r\n require(destination != address(0), \"DESTINATION_CANNT_BE_0_ADDRESS\");\r\n require(token != address(0), \"TOKEN_MUST_NOT_BE_0\");\r\n uint256 balance = IERC20(token).balanceOf(address(this));\r\n require(balance \u003e= amount, \"AMOUNT_CANNT_MORE_THAN_BALANCE\");\r\n TransferHelper.safeTransfer(token, destination, amount);\r\n emit Withdtraw(token, amount);\r\n }\r\n\r\n receive() external payable {}\r\n}"},"Context.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"},"IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller\u0027s account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller\u0027s tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender\u0027s allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller\u0027s\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"},"Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _setOwner(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _setOwner(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _setOwner(newOwner);\n }\n\n function _setOwner(address newOwner) private {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"},"ReentrancyGuard.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot\u0027s contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler\u0027s defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction\u0027s gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"},"SafeMath.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler\u0027s built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity\u0027s arithmetic operations.\n *\n * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c \u003c a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b \u003e a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring \u0027a\u0027 not being zero, but the\n // benefit is lost if \u0027b\u0027 is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity\u0027s `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity\u0027s `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity\u0027s `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity\u0027s `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity\u0027s `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b \u003c= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b \u003e 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b \u003e 0, errorMessage);\n return a % b;\n }\n }\n}\n"},"TransferHelper.sol":{"content":"// SPDX-License-Identifier: MIT\r\n\r\npragma solidity \u003e=0.8.0;\r\n\r\nlibrary TransferHelper {\r\n function safeApprove(address token, address to, uint value) internal {\r\n // bytes4(keccak256(bytes(\u0027approve(address,uint256)\u0027)));\r\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\r\n require(success \u0026\u0026 (data.length == 0 || abi.decode(data, (bool))), \u0027TransferHelper: APPROVE_FAILED\u0027);\r\n }\r\n\r\n function safeTransfer(address token, address to, uint value) internal {\r\n // bytes4(keccak256(bytes(\u0027transfer(address,uint256)\u0027)));\r\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\r\n require(success \u0026\u0026 (data.length == 0 || abi.decode(data, (bool))), \u0027TransferHelper: TRANSFER_FAILED\u0027);\r\n }\r\n\r\n function safeTransferFrom(address token, address from, address to, uint value) internal {\r\n // bytes4(keccak256(bytes(\u0027transferFrom(address,address,uint256)\u0027)));\r\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\r\n require(success \u0026\u0026 (data.length == 0 || abi.decode(data, (bool))), \u0027TransferHelper: TRANSFER_FROM_FAILED\u0027);\r\n }\r\n\r\n function safeTransferETH(address to, uint value) internal {\r\n (bool success,) = to.call{value:value}(new bytes(0));\r\n require(success, \u0027TransferHelper: ETH_TRANSFER_FAILED\u0027);\r\n }\r\n}\r\n"}}