Sushiswap_ZapIn_V4
About
Stats
Public Functions
13
Event Types
2
Code Size
39,381 bytes
Library Use
Uses SafeERC20 for IERC20.
Constants (5) keyboard_arrow_up
sushiSwapFactoryAddress Constant
IUniswapV2Factory help
the result of calling IUniswapV2Factory with UNKNOWN ARGUMENT
sushiSwapRouter Constant
IUniswapV2Router02 help
the result of calling IUniswapV2Router02 with UNKNOWN ARGUMENT
State Variables (9) keyboard_arrow_up
Functions
owner keyboard_arrow_up
renounceOwnership keyboard_arrow_up
transferOwnership keyboard_arrow_up
Modifiers help
onlyOwner checks for the following:
Source Code
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
toggleContractActive keyboard_arrow_up
set_feeWhitelist keyboard_arrow_up
Modifiers help
onlyOwner checks for the following:
Source Code
function set_feeWhitelist(address zapAddress, bool status) external onlyOwner {
feeWhitelist[zapAddress] = status;
}
set_new_goodwill keyboard_arrow_up
set_new_affiliateSplit keyboard_arrow_up
set_affiliate keyboard_arrow_up
Modifiers help
onlyOwner checks for the following:
Source Code
function set_affiliate(address _affiliate, bool _status) external onlyOwner {
affiliates[_affiliate] = _status;
}
withdrawTokens keyboard_arrow_up
Modifiers help
onlyOwner checks for the following:
Source Code
function withdrawTokens(address[] calldata tokens) external onlyOwner {
for (uint256 i = 0; i < tokens.length; i++) {
uint256 qty;
if (tokens[i] == ETHAddress) {
qty = address(this).balance - totalAffiliateBalance[tokens[i]];
Address.sendValue(payable(owner()), qty);
} else {
qty =
IERC20(tokens[i]).balanceOf(address(this)) -
totalAffiliateBalance[tokens[i]];
IERC20(tokens[i]).safeTransfer(owner(), qty);
}
}
}
affilliateWithdraw keyboard_arrow_up
Source Code
function affilliateWithdraw(address[] calldata tokens) external {
uint256 tokenBal;
for (uint256 i = 0; i < tokens.length; i++) {
tokenBal = affiliateBalance[msg.sender][tokens[i]];
affiliateBalance[msg.sender][tokens[i]] = 0;
totalAffiliateBalance[tokens[i]] =
totalAffiliateBalance[tokens[i]] -
tokenBal;
if (tokens[i] == ETHAddress) {
Address.sendValue(payable(msg.sender), tokenBal);
} else {
IERC20(tokens[i]).safeTransfer(msg.sender, tokenBal);
}
}
}
setApprovedTargets keyboard_arrow_up
Modifiers help
onlyOwner checks for the following:
Requirements help
Source Code
function setApprovedTargets(
address[] calldata targets,
bool[] calldata isApproved
) external onlyOwner {
require(targets.length == isApproved.length, "Invalid Input length");
for (uint256 i = 0; i < targets.length; i++) {
approvedTargets[targets[i]] = isApproved[i];
}
}
constructor keyboard_arrow_up
ZapIn keyboard_arrow_up
Parameters help
Modifiers help
stopInEmergency checks for the following:
Requirements help
Source Code
function ZapIn(
address _FromTokenContractAddress,
address _pairAddress,
uint256 _amount,
uint256 _minPoolTokens,
address _swapTarget,
bytes calldata swapData,
address affiliate,
bool transferResidual,
bool shouldSellEntireBalance
) external payable stopInEmergency returns (uint256) {
uint256 toInvest = _pullTokens(
_FromTokenContractAddress,
_amount,
affiliate,
true,
shouldSellEntireBalance
);
uint256 LPBought = _performZapIn(
_FromTokenContractAddress,
_pairAddress,
toInvest,
_swapTarget,
swapData,
transferResidual
);
require(LPBought >= _minPoolTokens, "High Slippage");
emit zapIn(msg.sender, _pairAddress, LPBought);
IERC20(_pairAddress).safeTransfer(msg.sender, LPBought);
return LPBought;
}
Internal Functions
Internal functions are parts of the contract that can't be used directly, but instead are used by the public functions listed above.
internal Sushiswap_ZapIn_V4._getPairTokens keyboard_arrow_up
Source Code
function _getPairTokens(address _pairAddress)
internal
pure
returns (address token0, address token1)
{
IUniswapV2Pair uniPair = IUniswapV2Pair(_pairAddress);
token0 = uniPair.token0();
token1 = uniPair.token1();
}
internal Sushiswap_ZapIn_V4._performZapIn keyboard_arrow_up
Parameters help
Source Code
function _performZapIn(
address _FromTokenContractAddress,
address _pairAddress,
uint256 _amount,
address _swapTarget,
bytes memory swapData,
bool transferResidual
) internal returns (uint256) {
uint256 intermediateAmt;
address intermediateToken;
(address _ToUniswapToken0, address _ToUniswapToken1) = _getPairTokens(
_pairAddress
);
if (
_FromTokenContractAddress != _ToUniswapToken0 &&
_FromTokenContractAddress != _ToUniswapToken1
) {
// swap to intermediate
(intermediateAmt, intermediateToken) = _fillQuote(
_FromTokenContractAddress,
_pairAddress,
_amount,
_swapTarget,
swapData
);
} else {
intermediateToken = _FromTokenContractAddress;
intermediateAmt = _amount;
}
// divide intermediate into appropriate amount to add liquidity
(uint256 token0Bought, uint256 token1Bought) = _swapIntermediate(
intermediateToken,
_ToUniswapToken0,
_ToUniswapToken1,
intermediateAmt
);
return
_uniDeposit(
_ToUniswapToken0,
_ToUniswapToken1,
token0Bought,
token1Bought,
transferResidual
);
}
internal Sushiswap_ZapIn_V4._uniDeposit keyboard_arrow_up
Parameters help
Source Code
function _uniDeposit(
address _ToUnipoolToken0,
address _ToUnipoolToken1,
uint256 token0Bought,
uint256 token1Bought,
bool transferResidual
) internal returns (uint256) {
_approveToken(_ToUnipoolToken0, address(sushiSwapRouter), token0Bought);
_approveToken(_ToUnipoolToken1, address(sushiSwapRouter), token1Bought);
(uint256 amountA, uint256 amountB, uint256 LP) = sushiSwapRouter.addLiquidity(
_ToUnipoolToken0,
_ToUnipoolToken1,
token0Bought,
token1Bought,
1,
1,
address(this),
deadline
);
if (transferResidual) {
//Returning Residue in token0, if any.
if (token0Bought - amountA > 0) {
IERC20(_ToUnipoolToken0).safeTransfer(msg.sender, token0Bought - amountA);
}
//Returning Residue in token1, if any
if (token1Bought - amountB > 0) {
IERC20(_ToUnipoolToken1).safeTransfer(msg.sender, token1Bought - amountB);
}
}
return LP;
}
internal Sushiswap_ZapIn_V4._fillQuote keyboard_arrow_up
Parameters help
Source Code
function _fillQuote(
address _fromTokenAddress,
address _pairAddress,
uint256 _amount,
address _swapTarget,
bytes memory swapData
) internal returns (uint256 amountBought, address intermediateToken) {
if (_swapTarget == wethTokenAddress) {
IWETH(wethTokenAddress).deposit{value: _amount}();
return (_amount, wethTokenAddress);
}
uint256 valueToSend;
if (_fromTokenAddress == address(0)) {
valueToSend = _amount;
} else {
_approveToken(_fromTokenAddress, _swapTarget, _amount);
}
(address _token0, address _token1) = _getPairTokens(_pairAddress);
IERC20 token0 = IERC20(_token0);
IERC20 token1 = IERC20(_token1);
uint256 initialBalance0 = token0.balanceOf(address(this));
uint256 initialBalance1 = token1.balanceOf(address(this));
require(approvedTargets[_swapTarget], "Target not Authorized");
(bool success, ) = _swapTarget.call{value: valueToSend}(swapData);
require(success, "Error Swapping Tokens 1");
uint256 finalBalance0 = token0.balanceOf(address(this)) - initialBalance0;
uint256 finalBalance1 = token1.balanceOf(address(this)) - initialBalance1;
if (finalBalance0 > finalBalance1) {
amountBought = finalBalance0;
intermediateToken = _token0;
} else {
amountBought = finalBalance1;
intermediateToken = _token1;
}
require(amountBought > 0, "Swapped to Invalid Intermediate");
}
internal Sushiswap_ZapIn_V4._swapIntermediate keyboard_arrow_up
Parameters help
Source Code
function _swapIntermediate(
address _toContractAddress,
address _ToUnipoolToken0,
address _ToUnipoolToken1,
uint256 _amount
) internal returns (uint256 token0Bought, uint256 token1Bought) {
IUniswapV2Pair pair = IUniswapV2Pair(
sushiSwapFactoryAddress.getPair(_ToUnipoolToken0, _ToUnipoolToken1)
);
(uint256 res0, uint256 res1, ) = pair.getReserves();
if (_toContractAddress == _ToUnipoolToken0) {
uint256 amountToSwap = calculateSwapInAmount(res0, _amount);
//if no reserve or a new pair is created
if (amountToSwap <= 0) amountToSwap = _amount / 2;
token1Bought = _token2Token(
_toContractAddress,
_ToUnipoolToken1,
amountToSwap
);
token0Bought = _amount - amountToSwap;
} else {
uint256 amountToSwap = calculateSwapInAmount(res1, _amount);
//if no reserve or a new pair is created
if (amountToSwap <= 0) amountToSwap = _amount / 2;
token0Bought = _token2Token(
_toContractAddress,
_ToUnipoolToken0,
amountToSwap
);
token1Bought = _amount - amountToSwap;
}
}
internal Sushiswap_ZapIn_V4.calculateSwapInAmount keyboard_arrow_up
Source Code
function calculateSwapInAmount(uint256 reserveIn, uint256 userIn)
internal
pure
returns (uint256)
{
return
(Babylonian.sqrt(reserveIn * ((userIn * 3988000) + (reserveIn * 3988009))) -
(reserveIn * 1997)) / 1994;
}
internal Sushiswap_ZapIn_V4._token2Token keyboard_arrow_up
Parameters help
Requirements help
Source Code
function _token2Token(
address _FromTokenContractAddress,
address _ToTokenContractAddress,
uint256 tokens2Trade
) internal returns (uint256 tokenBought) {
if (_FromTokenContractAddress == _ToTokenContractAddress) {
return tokens2Trade;
}
_approveToken(
_FromTokenContractAddress,
address(sushiSwapRouter),
tokens2Trade
);
address pair = sushiSwapFactoryAddress.getPair(
_FromTokenContractAddress,
_ToTokenContractAddress
);
require(pair != address(0), "No Swap Available");
address[] memory path = new address[](2);
path[0] = _FromTokenContractAddress;
path[1] = _ToTokenContractAddress;
tokenBought = sushiSwapRouter.swapExactTokensForTokens(
tokens2Trade,
1,
path,
address(this),
deadline
)[path.length - 1];
require(tokenBought > 0, "Error Swapping Tokens 2");
}
internal ZapInBaseV3._pullTokens keyboard_arrow_up
Parameters help
Source Code
function _pullTokens(
address token,
uint256 amount,
address affiliate,
bool enableGoodwill,
bool shouldSellEntireBalance
) internal returns (uint256 value) {
uint256 totalGoodwillPortion;
if (token == address(0)) {
require(msg.value > 0, "No eth sent");
// subtract goodwill
totalGoodwillPortion = _subtractGoodwill(
ETHAddress,
msg.value,
affiliate,
enableGoodwill
);
return msg.value - totalGoodwillPortion;
}
require(amount > 0, "Invalid token amount");
require(msg.value == 0, "Eth sent with token");
//transfer token
if (shouldSellEntireBalance) {
require(
Address.isContract(msg.sender),
"ERR: shouldSellEntireBalance is true for EOA"
);
amount = IERC20(token).allowance(msg.sender, address(this));
}
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
// subtract goodwill
totalGoodwillPortion = _subtractGoodwill(
token,
amount,
affiliate,
enableGoodwill
);
return amount - totalGoodwillPortion;
}
internal ZapInBaseV3._subtractGoodwill keyboard_arrow_up
Parameters help
Source Code
function _subtractGoodwill(
address token,
uint256 amount,
address affiliate,
bool enableGoodwill
) internal returns (uint256 totalGoodwillPortion) {
bool whitelisted = feeWhitelist[msg.sender];
if (enableGoodwill && !whitelisted && goodwill > 0) {
totalGoodwillPortion = (amount * goodwill) / 10000;
if (affiliates[affiliate]) {
if (token == address(0)) {
token = ETHAddress;
}
uint256 affiliatePortion = (totalGoodwillPortion * affiliateSplit) / 100;
affiliateBalance[affiliate][token] += affiliatePortion;
totalAffiliateBalance[token] += affiliatePortion;
}
}
}
internal ZapBaseV2._getBalance keyboard_arrow_up
Source Code
function _getBalance(address token) internal view returns (uint256 balance) {
if (token == address(0)) {
balance = address(this).balance;
} else {
balance = IERC20(token).balanceOf(address(this));
}
}
internal ZapBaseV2._approveToken keyboard_arrow_up
Source Code
function _approveToken(address token, address spender) internal {
IERC20 _token = IERC20(token);
if (_token.allowance(address(this), spender) > 0) return;
else {
_token.safeApprove(spender, type(uint256).max);
}
}
internal ZapBaseV2._approveToken keyboard_arrow_up
Source Code
function _approveToken(
address token,
address spender,
uint256 amount
) internal {
IERC20(token).safeApprove(spender, 0);
IERC20(token).safeApprove(spender, amount);
}
internal Context._msgSender keyboard_arrow_up
internal Context._msgData keyboard_arrow_up
Parameters help
This function has no parameters.
Source Code
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}