I have a contract deployed on the rinkeby testnet. It is basically a clone of uniswapV2. Whenever I try to call the router contract's addLiquidity/ removeLiquidity/ swapTokens functions this error pops up. All other functions in other contracts are working just fine! Only functions of the router contract are giving this error!
I am unable to rectify this problem at the moment kindly look into this and suggest some ways to make it work! Here is the code for reference:
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.10;
import "../interfaces/IKswapPair.sol";
import "../interfaces/IKswapFactory.sol";
import "./KswapLibrary.sol";
contract KswapRouter {
error ExcessiveInputAmount();
error InsufficientAAmount();
error InsufficientBAmount();
error InsufficientOutputAmount();
error SafeTransferFailed();
IKswapFactory factory;
constructor(address factoryAddress) {
factory = IKswapFactory(factoryAddress);
}
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to
)
public
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
)
{
if (factory.pairs(tokenA, tokenB) == address(0)) {
factory.createPair(tokenA, tokenB);
}
(amountA, amountB) = _calculateLiquidity(
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin
);
address pairAddress = KswapLibrary.pairFor(
address(factory),
tokenA,
tokenB
);
_safeTransferFrom(tokenA, msg.sender, pairAddress, amountA);
_safeTransferFrom(tokenB, msg.sender, pairAddress, amountB);
liquidity = IKswapPair(pairAddress).mint(to);
}
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to
) public returns (uint256 amountA, uint256 amountB) {
address pair = KswapLibrary.pairFor(
address(factory),
tokenA,
tokenB
);
IKswapPair(pair).transferFrom(msg.sender, pair, liquidity);
(amountA, amountB) = IKswapPair(pair).burn(to);
if (amountA < amountAMin) revert InsufficientAAmount();
if (amountB < amountBMin) revert InsufficientBAmount();
}
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to
) public returns (uint256[] memory amounts) {
amounts = KswapLibrary.getAmountsOut(
address(factory),
amountIn,
path
);
if (amounts[amounts.length - 1] < amountOutMin)
revert InsufficientOutputAmount();
_safeTransferFrom(
path[0],
msg.sender,
KswapLibrary.pairFor(address(factory), path[0], path[1]),
amounts[0]
);
_swap(amounts, path, to);
}
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to
) public returns (uint256[] memory amounts) {
amounts = KswapLibrary.getAmountsIn(
address(factory),
amountOut,
path
);
if (amounts[amounts.length - 1] > amountInMax)
revert ExcessiveInputAmount();
_safeTransferFrom(
path[0],
msg.sender,
KswapLibrary.pairFor(address(factory), path[0], path[1]),
amounts[0]
);
_swap(amounts, path, to);
}
//
//
//
// PRIVATE
//
//
//
function _swap(
uint256[] memory amounts,
address[] memory path,
address to_
) internal {
for (uint256 i = 0; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0, ) = KswapLibrary.sortTokens(input, output);
uint256 amountOut = amounts[i + 1];
(uint256 amount0Out, uint256 amount1Out) = input == token0
? (uint256(0), amountOut)
: (amountOut, uint256(0));
address to = i < path.length - 2
? KswapLibrary.pairFor(address(factory), output, path[i + 2])
: to_;
IKswapPair(
KswapLibrary.pairFor(address(factory), input, output)
).swap(amount0Out, amount1Out, to);
}
}
function _calculateLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin
) internal returns (uint256 amountA, uint256 amountB) {
(uint256 reserveA, uint256 reserveB) = KswapLibrary.getReserves(
address(factory),
tokenA,
tokenB
);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint256 amountBOptimal = KswapLibrary.quote(
amountADesired,
reserveA,
reserveB
); //calculates output amount
if (amountBOptimal <= amountBDesired) {
if (amountBOptimal <= amountBMin) revert InsufficientBAmount();
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint256 amountAOptimal = KswapLibrary.quote(
amountBDesired,
reserveB,
reserveA
);
assert(amountAOptimal <= amountADesired);
if (amountAOptimal <= amountAMin) revert InsufficientAAmount();
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
function _safeTransferFrom(
address token,
address from,
address to,
uint256 value
) private {
(bool success, bytes memory data) = token.call(
abi.encodeWithSignature(
"transferFrom(address,address,uint256)",
from,
to,
value
)
);
if (!success || (data.length != 0 && !abi.decode(data, (bool))))
revert SafeTransferFailed();
}
//
//
// LIBRARY FUNCTIONS
//
//
function quote(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) public pure returns (uint256 amountOut) {
return KswapLibrary.quote(amountIn, reserveIn, reserveOut);
}
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) public pure returns (uint256 amountOut) {
return KswapLibrary.getAmountOut(amountIn, reserveIn, reserveOut);
}
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) public pure returns (uint256 amountIn) {
return KswapLibrary.getAmountIn(amountOut, reserveIn, reserveOut);
}
function getAmountsOut(uint256 amountIn, address[] memory path)
public
returns (uint256[] memory amounts)
{
return KswapLibrary.getAmountsOut(address(factory), amountIn, path);
}
function getAmountsIn(uint256 amountOut, address[] memory path)
public
returns (uint256[] memory amounts)
{
return KswapLibrary.getAmountsIn(address(factory), amountOut, path);
}
}