Untitled
unknown
plain_text
a year ago
43 kB
8
Indexable
const approveAbi = [ { constant: false, inputs: [ { name: "spender", type: "address", }, { name: "amount", type: "uint256", }, ], name: "approve", outputs: [ { name: "", type: "bool", }, ], payable: false, stateMutability: "nonpayable", type: "function", }, ]; const traderJoeRouterAbi = // File: contracts/traderjoe/interfaces/IJoePair.sol // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0; interface IJoePair { event Approval( address indexed owner, address indexed spender, uint256 value ); event Transfer(address indexed from, address indexed to, uint256 value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom( address from, address to, uint256 value ) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint256); function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; event Mint(address indexed sender, uint256 amount0, uint256 amount1); event Burn( address indexed sender, uint256 amount0, uint256 amount1, address indexed to ); event Swap( address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint256); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns ( uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast ); function price0CumulativeLast() external view returns (uint256); function price1CumulativeLast() external view returns (uint256); function kLast() external view returns (uint256); function mint(address to) external returns (uint256 liquidity); function burn(address to) external returns (uint256 amount0, uint256 amount1); function swap( uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data ) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } // File: contracts/traderjoe/libraries/SafeMath.sol pragma solidity =0.6.12; // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) library SafeMathJoe { function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } } // File: contracts/traderjoe/libraries/JoeLibrary.sol pragma solidity >=0.5.0; library JoeLibrary { using SafeMathJoe for uint256; // returns sorted token addresses, used to handle return values from pairs sorted in this order function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { require(tokenA != tokenB, "JoeLibrary: IDENTICAL_ADDRESSES"); (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); require(token0 != address(0), "JoeLibrary: ZERO_ADDRESS"); } // calculates the CREATE2 address for a pair without making any external calls function pairFor( address factory, address tokenA, address tokenB ) internal pure returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); pair = address( uint256( keccak256( abi.encodePacked( hex"ff", factory, keccak256(abi.encodePacked(token0, token1)), hex"0bbca9af0511ad1a1da383135cf3a8d2ac620e549ef9f6ae3a4c33c2fed0af91" ) ) ) ); } // fetches and sorts the reserves for a pair function getReserves( address factory, address tokenA, address tokenB ) internal view returns (uint256 reserveA, uint256 reserveB) { (address token0, ) = sortTokens(tokenA, tokenB); (uint256 reserve0, uint256 reserve1, ) = IJoePair( pairFor(factory, tokenA, tokenB) ).getReserves(); (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); } // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) internal pure returns (uint256 amountB) { require(amountA > 0, "JoeLibrary: INSUFFICIENT_AMOUNT"); require( reserveA > 0 && reserveB > 0, "JoeLibrary: INSUFFICIENT_LIQUIDITY" ); amountB = amountA.mul(reserveB) / reserveA; } // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) internal pure returns (uint256 amountOut) { require(amountIn > 0, "JoeLibrary: INSUFFICIENT_INPUT_AMOUNT"); require( reserveIn > 0 && reserveOut > 0, "JoeLibrary: INSUFFICIENT_LIQUIDITY" ); uint256 amountInWithFee = amountIn.mul(997); uint256 numerator = amountInWithFee.mul(reserveOut); uint256 denominator = reserveIn.mul(1000).add(amountInWithFee); amountOut = numerator / denominator; } // given an output amount of an asset and pair reserves, returns a required input amount of the other asset function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) internal pure returns (uint256 amountIn) { require(amountOut > 0, "JoeLibrary: INSUFFICIENT_OUTPUT_AMOUNT"); require( reserveIn > 0 && reserveOut > 0, "JoeLibrary: INSUFFICIENT_LIQUIDITY" ); uint256 numerator = reserveIn.mul(amountOut).mul(1000); uint256 denominator = reserveOut.sub(amountOut).mul(997); amountIn = (numerator / denominator).add(1); } // performs chained getAmountOut calculations on any number of pairs function getAmountsOut( address factory, uint256 amountIn, address[] memory path ) internal view returns (uint256[] memory amounts) { require(path.length >= 2, "JoeLibrary: INVALID_PATH"); amounts = new uint256[](path.length); amounts[0] = amountIn; for (uint256 i; i < path.length - 1; i++) { (uint256 reserveIn, uint256 reserveOut) = getReserves( factory, path[i], path[i + 1] ); amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); } } // performs chained getAmountIn calculations on any number of pairs function getAmountsIn( address factory, uint256 amountOut, address[] memory path ) internal view returns (uint256[] memory amounts) { require(path.length >= 2, "JoeLibrary: INVALID_PATH"); amounts = new uint256[](path.length); amounts[amounts.length - 1] = amountOut; for (uint256 i = path.length - 1; i > 0; i--) { (uint256 reserveIn, uint256 reserveOut) = getReserves( factory, path[i - 1], path[i] ); amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); } } } // File: contracts/traderjoe/libraries/TransferHelper.sol pragma solidity >=0.6.0; // helper methods for interacting with ERC20 tokens and sending AVAX that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 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, uint256 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_FAILED" ); } function safeTransferFrom( address token, address from, address to, uint256 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 safeTransferAVAX(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "TransferHelper: AVAX_TRANSFER_FAILED"); } } pragma solidity >=0.5.0; interface IJoeFactory { event PairCreated( address indexed token0, address indexed token1, address pair, uint256 ); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function migrator() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint256) external view returns (address pair); function allPairsLength() external view returns (uint256); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; function setMigrator(address) external; } // File: contracts/traderjoe/interfaces/IJoeRouter01.sol pragma solidity >=0.6.2; interface IJoeRouter01 { function factory() external pure returns (address); function WAVAX() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns ( uint256 amountA, uint256 amountB, uint256 liquidity ); function addLiquidityAVAX( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountAVAX, uint256 liquidity ); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityAVAX( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountAVAX); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityAVAXWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountAVAX); 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 swapExactAVAXForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function swapTokensForExactAVAX( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForAVAX( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapAVAXForExactTokens( uint256 amountOut, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) external pure returns (uint256 amountB); function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountOut); function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountIn); 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); } // File: contracts/traderjoe/interfaces/IJoeRouter02.sol pragma solidity >=0.6.2; interface IJoeRouter02 is IJoeRouter01 { function removeLiquidityAVAXSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external returns (uint256 amountAVAX); function removeLiquidityAVAXWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountAVAX); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactAVAXForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForAVAXSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; } // File: contracts/traderjoe/interfaces/IJoeFactory.sol pragma solidity >=0.5.0; interface IERC20Joe { event Approval( address indexed owner, address indexed spender, uint256 value ); event Transfer(address indexed from, address indexed to, uint256 value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom( address from, address to, uint256 value ) external returns (bool); } // File: contracts/traderjoe/interfaces/IWAVAX.sol pragma solidity >=0.5.0; interface IWAVAX { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; } // File: contracts/traderjoe/JoeRouter02.sol pragma solidity =0.6.12; contract JoeRouter02 is IJoeRouter02 { using SafeMathJoe for uint256; address public immutable override factory; address public immutable override WAVAX; modifier ensure(uint256 deadline) { require(deadline >= block.timestamp, "JoeRouter: EXPIRED"); _; } constructor(address _factory, address _WAVAX) public { factory = _factory; WAVAX = _WAVAX; } receive() external payable { assert(msg.sender == WAVAX); // only accept AVAX via fallback from the WAVAX contract } // **** ADD LIQUIDITY **** function _addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin ) internal virtual returns (uint256 amountA, uint256 amountB) { // create the pair if it doesn't exist yet if (IJoeFactory(factory).getPair(tokenA, tokenB) == address(0)) { IJoeFactory(factory).createPair(tokenA, tokenB); } (uint256 reserveA, uint256 reserveB) = JoeLibrary.getReserves( factory, tokenA, tokenB ); if (reserveA == 0 && reserveB == 0) { (amountA, amountB) = (amountADesired, amountBDesired); } else { uint256 amountBOptimal = JoeLibrary.quote( amountADesired, reserveA, reserveB ); if (amountBOptimal <= amountBDesired) { require( amountBOptimal >= amountBMin, "JoeRouter: INSUFFICIENT_B_AMOUNT" ); (amountA, amountB) = (amountADesired, amountBOptimal); } else { uint256 amountAOptimal = JoeLibrary.quote( amountBDesired, reserveB, reserveA ); assert(amountAOptimal <= amountADesired); require( amountAOptimal >= amountAMin, "JoeRouter: INSUFFICIENT_A_AMOUNT" ); (amountA, amountB) = (amountAOptimal, amountBDesired); } } } function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external virtual override ensure(deadline) returns ( uint256 amountA, uint256 amountB, uint256 liquidity ) { (amountA, amountB) = _addLiquidity( tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin ); address pair = JoeLibrary.pairFor(factory, tokenA, tokenB); TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA); TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); liquidity = IJoePair(pair).mint(to); } function addLiquidityAVAX( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external payable virtual override ensure(deadline) returns ( uint256 amountToken, uint256 amountAVAX, uint256 liquidity ) { (amountToken, amountAVAX) = _addLiquidity( token, WAVAX, amountTokenDesired, msg.value, amountTokenMin, amountAVAXMin ); address pair = JoeLibrary.pairFor(factory, token, WAVAX); TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); IWAVAX(WAVAX).deposit{value: amountAVAX}(); assert(IWAVAX(WAVAX).transfer(pair, amountAVAX)); liquidity = IJoePair(pair).mint(to); // refund dust eth, if any if (msg.value > amountAVAX) TransferHelper.safeTransferAVAX(msg.sender, msg.value - amountAVAX); } // **** REMOVE LIQUIDITY **** function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) public virtual override ensure(deadline) returns (uint256 amountA, uint256 amountB) { address pair = JoeLibrary.pairFor(factory, tokenA, tokenB); IJoePair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair (uint256 amount0, uint256 amount1) = IJoePair(pair).burn(to); (address token0, ) = JoeLibrary.sortTokens(tokenA, tokenB); (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); require(amountA >= amountAMin, "JoeRouter: INSUFFICIENT_A_AMOUNT"); require(amountB >= amountBMin, "JoeRouter: INSUFFICIENT_B_AMOUNT"); } function removeLiquidityAVAX( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) public virtual override ensure(deadline) returns (uint256 amountToken, uint256 amountAVAX) { (amountToken, amountAVAX) = removeLiquidity( token, WAVAX, liquidity, amountTokenMin, amountAVAXMin, address(this), deadline ); TransferHelper.safeTransfer(token, to, amountToken); IWAVAX(WAVAX).withdraw(amountAVAX); TransferHelper.safeTransferAVAX(to, amountAVAX); } function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external virtual override returns (uint256 amountA, uint256 amountB) { address pair = JoeLibrary.pairFor(factory, tokenA, tokenB); uint256 value = approveMax ? uint256(-1) : liquidity; IJoePair(pair).permit( msg.sender, address(this), value, deadline, v, r, s ); (amountA, amountB) = removeLiquidity( tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline ); } function removeLiquidityAVAXWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external virtual override returns (uint256 amountToken, uint256 amountAVAX) { address pair = JoeLibrary.pairFor(factory, token, WAVAX); uint256 value = approveMax ? uint256(-1) : liquidity; IJoePair(pair).permit( msg.sender, address(this), value, deadline, v, r, s ); (amountToken, amountAVAX) = removeLiquidityAVAX( token, liquidity, amountTokenMin, amountAVAXMin, to, deadline ); } // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) **** function removeLiquidityAVAXSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) public virtual override ensure(deadline) returns (uint256 amountAVAX) { (, amountAVAX) = removeLiquidity( token, WAVAX, liquidity, amountTokenMin, amountAVAXMin, address(this), deadline ); TransferHelper.safeTransfer( token, to, IERC20Joe(token).balanceOf(address(this)) ); IWAVAX(WAVAX).withdraw(amountAVAX); TransferHelper.safeTransferAVAX(to, amountAVAX); } function removeLiquidityAVAXWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external virtual override returns (uint256 amountAVAX) { address pair = JoeLibrary.pairFor(factory, token, WAVAX); uint256 value = approveMax ? uint256(-1) : liquidity; IJoePair(pair).permit( msg.sender, address(this), value, deadline, v, r, s ); amountAVAX = removeLiquidityAVAXSupportingFeeOnTransferTokens( token, liquidity, amountTokenMin, amountAVAXMin, to, deadline ); } // **** SWAP **** // requires the initial amount to have already been sent to the first pair function _swap( uint256[] memory amounts, address[] memory path, address _to ) internal virtual { for (uint256 i; i < path.length - 1; i++) { (address input, address output) = (path[i], path[i + 1]); (address token0, ) = JoeLibrary.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 ? JoeLibrary.pairFor(factory, output, path[i + 2]) : _to; IJoePair(JoeLibrary.pairFor(factory, input, output)).swap( amount0Out, amount1Out, to, new bytes(0) ); } } function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external virtual override ensure(deadline) returns (uint256[] memory amounts) { amounts = JoeLibrary.getAmountsOut(factory, amountIn, path); require( amounts[amounts.length - 1] >= amountOutMin, "JoeRouter: INSUFFICIENT_OUTPUT_AMOUNT" ); TransferHelper.safeTransferFrom( path[0], msg.sender, JoeLibrary.pairFor(factory, path[0], path[1]), amounts[0] ); _swap(amounts, path, to); } function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external virtual override ensure(deadline) returns (uint256[] memory amounts) { amounts = JoeLibrary.getAmountsIn(factory, amountOut, path); require(amounts[0] <= amountInMax, "JoeRouter: EXCESSIVE_INPUT_AMOUNT"); TransferHelper.safeTransferFrom( path[0], msg.sender, JoeLibrary.pairFor(factory, path[0], path[1]), amounts[0] ); _swap(amounts, path, to); } function swapExactAVAXForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable virtual override ensure(deadline) returns (uint256[] memory amounts) { require(path[0] == WAVAX, "JoeRouter: INVALID_PATH"); amounts = JoeLibrary.getAmountsOut(factory, msg.value, path); require( amounts[amounts.length - 1] >= amountOutMin, "JoeRouter: INSUFFICIENT_OUTPUT_AMOUNT" ); IWAVAX(WAVAX).deposit{value: amounts[0]}(); assert( IWAVAX(WAVAX).transfer( JoeLibrary.pairFor(factory, path[0], path[1]), amounts[0] ) ); _swap(amounts, path, to); } function swapTokensForExactAVAX( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external virtual override ensure(deadline) returns (uint256[] memory amounts) { require(path[path.length - 1] == WAVAX, "JoeRouter: INVALID_PATH"); amounts = JoeLibrary.getAmountsIn(factory, amountOut, path); require(amounts[0] <= amountInMax, "JoeRouter: EXCESSIVE_INPUT_AMOUNT"); TransferHelper.safeTransferFrom( path[0], msg.sender, JoeLibrary.pairFor(factory, path[0], path[1]), amounts[0] ); _swap(amounts, path, address(this)); IWAVAX(WAVAX).withdraw(amounts[amounts.length - 1]); TransferHelper.safeTransferAVAX(to, amounts[amounts.length - 1]); } function swapExactTokensForAVAX( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external virtual override ensure(deadline) returns (uint256[] memory amounts) { require(path[path.length - 1] == WAVAX, "JoeRouter: INVALID_PATH"); amounts = JoeLibrary.getAmountsOut(factory, amountIn, path); require( amounts[amounts.length - 1] >= amountOutMin, "JoeRouter: INSUFFICIENT_OUTPUT_AMOUNT" ); TransferHelper.safeTransferFrom( path[0], msg.sender, JoeLibrary.pairFor(factory, path[0], path[1]), amounts[0] ); _swap(amounts, path, address(this)); IWAVAX(WAVAX).withdraw(amounts[amounts.length - 1]); TransferHelper.safeTransferAVAX(to, amounts[amounts.length - 1]); } function swapAVAXForExactTokens( uint256 amountOut, address[] calldata path, address to, uint256 deadline ) external payable virtual override ensure(deadline) returns (uint256[] memory amounts) { require(path[0] == WAVAX, "JoeRouter: INVALID_PATH"); amounts = JoeLibrary.getAmountsIn(factory, amountOut, path); require(amounts[0] <= msg.value, "JoeRouter: EXCESSIVE_INPUT_AMOUNT"); IWAVAX(WAVAX).deposit{value: amounts[0]}(); assert( IWAVAX(WAVAX).transfer( JoeLibrary.pairFor(factory, path[0], path[1]), amounts[0] ) ); _swap(amounts, path, to); // refund dust eth, if any if (msg.value > amounts[0]) TransferHelper.safeTransferAVAX(msg.sender, msg.value - amounts[0]); } // **** SWAP (supporting fee-on-transfer tokens) **** // requires the initial amount to have already been sent to the first pair function _swapSupportingFeeOnTransferTokens( address[] memory path, address _to ) internal virtual { for (uint256 i; i < path.length - 1; i++) { (address input, address output) = (path[i], path[i + 1]); (address token0, ) = JoeLibrary.sortTokens(input, output); IJoePair pair = IJoePair( JoeLibrary.pairFor(factory, input, output) ); uint256 amountInput; uint256 amountOutput; { // scope to avoid stack too deep errors (uint256 reserve0, uint256 reserve1, ) = pair.getReserves(); (uint256 reserveInput, uint256 reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0); amountInput = IERC20Joe(input).balanceOf(address(pair)).sub( reserveInput ); amountOutput = JoeLibrary.getAmountOut( amountInput, reserveInput, reserveOutput ); } (uint256 amount0Out, uint256 amount1Out) = input == token0 ? (uint256(0), amountOutput) : (amountOutput, uint256(0)); address to = i < path.length - 2 ? JoeLibrary.pairFor(factory, output, path[i + 2]) : _to; pair.swap(amount0Out, amount1Out, to, new bytes(0)); } } function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external virtual override ensure(deadline) { TransferHelper.safeTransferFrom( path[0], msg.sender, JoeLibrary.pairFor(factory, path[0], path[1]), amountIn ); uint256 balanceBefore = IERC20Joe(path[path.length - 1]).balanceOf(to); _swapSupportingFeeOnTransferTokens(path, to); require( IERC20Joe(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin, "JoeRouter: INSUFFICIENT_OUTPUT_AMOUNT" ); } function swapExactAVAXForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable virtual override ensure(deadline) { require(path[0] == WAVAX, "JoeRouter: INVALID_PATH"); uint256 amountIn = msg.value; IWAVAX(WAVAX).deposit{value: amountIn}(); assert( IWAVAX(WAVAX).transfer( JoeLibrary.pairFor(factory, path[0], path[1]), amountIn ) ); uint256 balanceBefore = IERC20Joe(path[path.length - 1]).balanceOf(to); _swapSupportingFeeOnTransferTokens(path, to); require( IERC20Joe(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin, "JoeRouter: INSUFFICIENT_OUTPUT_AMOUNT" ); } function swapExactTokensForAVAXSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external virtual override ensure(deadline) { require(path[path.length - 1] == WAVAX, "JoeRouter: INVALID_PATH"); TransferHelper.safeTransferFrom( path[0], msg.sender, JoeLibrary.pairFor(factory, path[0], path[1]), amountIn ); _swapSupportingFeeOnTransferTokens(path, address(this)); uint256 amountOut = IERC20Joe(WAVAX).balanceOf(address(this)); require( amountOut >= amountOutMin, "JoeRouter: INSUFFICIENT_OUTPUT_AMOUNT" ); IWAVAX(WAVAX).withdraw(amountOut); TransferHelper.safeTransferAVAX(to, amountOut); } // **** LIBRARY FUNCTIONS **** function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) public pure virtual override returns (uint256 amountB) { return JoeLibrary.quote(amountA, reserveA, reserveB); } function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) public pure virtual override returns (uint256 amountOut) { return JoeLibrary.getAmountOut(amountIn, reserveIn, reserveOut); } function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) public pure virtual override returns (uint256 amountIn) { return JoeLibrary.getAmountIn(amountOut, reserveIn, reserveOut); } function getAmountsOut(uint256 amountIn, address[] memory path) public view virtual override returns (uint256[] memory amounts) { return JoeLibrary.getAmountsOut(factory, amountIn, path); } function getAmountsIn(uint256 amountOut, address[] memory path) public view virtual override returns (uint256[] memory amounts) { return JoeLibrary.getAmountsIn(factory, amountOut, path); } }; import {ethers} from 'ethers'; import dotenv from "dotenv"; dotenv.config(); const AVALANCHE_ENDPOINT = process.env.AVALANCHE_ENDPOINT; const PRIVATE_KEY = process.env.PRIVATE_KEY; const WALLET_ADDRESS = process.env.WALLET_ADDRESS; // Connect to Avalanche C-Chain provider const provider = new ethers.JsonRpcProvider(AVALANCHE_ENDPOINT); // Set up your wallet const privateKey = PRIVATE_KEY; const wallet = new ethers.Wallet(privateKey, provider); // Trader Joe Router contract address and ABI (replace with actual values) const traderJoeRouterAddress = "0x60aE616a2155Ee3d9A68541Ba4544862310933d4"; const traderJoeRouter = new ethers.Contract( traderJoeRouterAddress, traderJoeRouterAbi, wallet ); // Your token and pool details const tokenAddress = "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7"; const poolAddress = "0xD446eb1660F766d533BeCeEf890Df7A69d26f7d1"; const amountToSwapInNative = 0.005; const amountIn = ethers.parseUnits( amountToSwapInNative.toString(), "ether" ); // Adjust the amount to swap // Swap tokens async function swapTokens() { try { const path = [tokenAddress, poolAddress]; // Token path for the swap const to = wallet.address; // Address to receive the swapped tokens const deadline = Math.floor(Date.now() / 1000) + 60 * 10; // 10 minutes from now const avaxContract = new ethers.Contract( '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', ['function approve(address spender, uint256 amount)'], wallet); const approveTx = await avaxContract.approve( traderJoeRouterAddress, ethers.MaxUint256 ); await approveTx.wait(); // Perform the swap const tx = await traderJoeRouter.swapExactTokensForTokens( amountIn, 0, // Min amount of tokens you want to receive path, to, deadline ); // Wait for the transaction to be mined await tx.wait(); console.log("Swap successful!"); } catch (error) { console.error("Error swapping tokens:", error.message); } } // Call the function to initiate the swap swapTokens();
Editor is loading...
Leave a Comment