github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/exchange-scrapers/anyswap/anyswaproutereth.sol (about) 1 /** 2 *Submitted for verification at Etherscan.io on 2021-06-18 3 */ 4 5 /** 6 *Submitted for verification at FtmScan.com on 2021-05-31 7 */ 8 9 /** 10 *Submitted for verification at BscScan.com on 2021-04-15 11 */ 12 13 /** 14 *Submitted for verification at BscScan.com on 2021-04-08 15 */ 16 17 /** 18 *Submitted for verification at hecoinfo.com on 2021-04-08 19 */ 20 21 // SPDX-License-Identifier: GPL-3.0-or-later 22 23 pragma solidity >=0.8.0; 24 25 interface ISushiswapV2Pair { 26 function factory() external view returns (address); 27 function token0() external view returns (address); 28 function token1() external view returns (address); 29 function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 30 function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 31 } 32 33 // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) 34 35 library SafeMathSushiswap { 36 function add(uint x, uint y) internal pure returns (uint z) { 37 require((z = x + y) >= x, 'ds-math-add-overflow'); 38 } 39 40 function sub(uint x, uint y) internal pure returns (uint z) { 41 require((z = x - y) <= x, 'ds-math-sub-underflow'); 42 } 43 44 function mul(uint x, uint y) internal pure returns (uint z) { 45 require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); 46 } 47 } 48 49 library SushiswapV2Library { 50 using SafeMathSushiswap for uint; 51 52 // returns sorted token addresses, used to handle return values from pairs sorted in this order 53 function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { 54 require(tokenA != tokenB, 'SushiswapV2Library: IDENTICAL_ADDRESSES'); 55 (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 56 require(token0 != address(0), 'SushiswapV2Library: ZERO_ADDRESS'); 57 } 58 59 // calculates the CREATE2 address for a pair without making any external calls 60 function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) { 61 (address token0, address token1) = sortTokens(tokenA, tokenB); 62 pair = address(uint160(uint256(keccak256(abi.encodePacked( 63 hex'ff', 64 factory, 65 keccak256(abi.encodePacked(token0, token1)), 66 hex'e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303' // init code hash 67 ))))); 68 } 69 70 // fetches and sorts the reserves for a pair 71 function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) { 72 (address token0,) = sortTokens(tokenA, tokenB); 73 (uint reserve0, uint reserve1,) = ISushiswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves(); 74 (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); 75 } 76 77 // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset 78 function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { 79 require(amountA > 0, 'SushiswapV2Library: INSUFFICIENT_AMOUNT'); 80 require(reserveA > 0 && reserveB > 0, 'SushiswapV2Library: INSUFFICIENT_LIQUIDITY'); 81 amountB = amountA.mul(reserveB) / reserveA; 82 } 83 84 // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset 85 function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { 86 require(amountIn > 0, 'SushiswapV2Library: INSUFFICIENT_INPUT_AMOUNT'); 87 require(reserveIn > 0 && reserveOut > 0, 'SushiswapV2Library: INSUFFICIENT_LIQUIDITY'); 88 uint amountInWithFee = amountIn.mul(997); 89 uint numerator = amountInWithFee.mul(reserveOut); 90 uint denominator = reserveIn.mul(1000).add(amountInWithFee); 91 amountOut = numerator / denominator; 92 } 93 94 // given an output amount of an asset and pair reserves, returns a required input amount of the other asset 95 function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { 96 require(amountOut > 0, 'SushiswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT'); 97 require(reserveIn > 0 && reserveOut > 0, 'SushiswapV2Library: INSUFFICIENT_LIQUIDITY'); 98 uint numerator = reserveIn.mul(amountOut).mul(1000); 99 uint denominator = reserveOut.sub(amountOut).mul(997); 100 amountIn = (numerator / denominator).add(1); 101 } 102 103 // performs chained getAmountOut calculations on any number of pairs 104 function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) { 105 require(path.length >= 2, 'SushiswapV2Library: INVALID_PATH'); 106 amounts = new uint[](path.length); 107 amounts[0] = amountIn; 108 for (uint i; i < path.length - 1; i++) { 109 (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]); 110 amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); 111 } 112 } 113 114 // performs chained getAmountIn calculations on any number of pairs 115 function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) { 116 require(path.length >= 2, 'SushiswapV2Library: INVALID_PATH'); 117 amounts = new uint[](path.length); 118 amounts[amounts.length - 1] = amountOut; 119 for (uint i = path.length - 1; i > 0; i--) { 120 (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]); 121 amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); 122 } 123 } 124 } 125 126 // helper methods for interacting with ERC20 tokens and sending NATIVE that do not consistently return true/false 127 library TransferHelper { 128 function safeApprove(address token, address to, uint value) internal { 129 // bytes4(keccak256(bytes('approve(address,uint256)'))); 130 (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); 131 require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); 132 } 133 134 function safeTransfer(address token, address to, uint value) internal { 135 // bytes4(keccak256(bytes('transfer(address,uint256)'))); 136 (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); 137 require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); 138 } 139 140 function safeTransferFrom(address token, address from, address to, uint value) internal { 141 // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); 142 (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); 143 require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); 144 } 145 146 function safeTransferNative(address to, uint value) internal { 147 (bool success,) = to.call{value:value}(new bytes(0)); 148 require(success, 'TransferHelper: NATIVE_TRANSFER_FAILED'); 149 } 150 } 151 152 interface IwNATIVE { 153 function deposit() external payable; 154 function transfer(address to, uint value) external returns (bool); 155 function withdraw(uint) external; 156 } 157 158 interface AnyswapV1ERC20 { 159 function mint(address to, uint256 amount) external returns (bool); 160 function burn(address from, uint256 amount) external returns (bool); 161 function changeVault(address newVault) external returns (bool); 162 function depositVault(uint amount, address to) external returns (uint); 163 function withdrawVault(address from, uint amount, address to) external returns (uint); 164 function underlying() external view returns (address); 165 } 166 167 /** 168 * @dev Interface of the ERC20 standard as defined in the EIP. 169 */ 170 interface IERC20 { 171 function totalSupply() external view returns (uint256); 172 function balanceOf(address account) external view returns (uint256); 173 function transfer(address recipient, uint256 amount) external returns (bool); 174 function allowance(address owner, address spender) external view returns (uint256); 175 function approve(address spender, uint256 amount) external returns (bool); 176 function permit(address target, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; 177 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 178 function transferWithPermit(address target, address to, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external returns (bool); 179 180 event Transfer(address indexed from, address indexed to, uint256 value); 181 event Approval(address indexed owner, address indexed spender, uint256 value); 182 } 183 184 contract AnyswapV4Router { 185 using SafeMathSushiswap for uint; 186 187 address public immutable factory; 188 address public immutable wNATIVE; 189 190 modifier ensure(uint deadline) { 191 require(deadline >= block.timestamp, 'AnyswapV3Router: EXPIRED'); 192 _; 193 } 194 195 constructor(address _factory, address _wNATIVE, address _mpc) { 196 _newMPC = _mpc; 197 _newMPCEffectiveTime = block.timestamp; 198 factory = _factory; 199 wNATIVE = _wNATIVE; 200 } 201 202 receive() external payable { 203 assert(msg.sender == wNATIVE); // only accept Native via fallback from the wNative contract 204 } 205 206 address private _oldMPC; 207 address private _newMPC; 208 uint256 private _newMPCEffectiveTime; 209 210 211 event LogChangeMPC(address indexed oldMPC, address indexed newMPC, uint indexed effectiveTime, uint chainID); 212 event LogChangeRouter(address indexed oldRouter, address indexed newRouter, uint chainID); 213 event LogAnySwapIn(bytes32 indexed txhash, address indexed token, address indexed to, uint amount, uint fromChainID, uint toChainID); 214 event LogAnySwapOut(address indexed token, address indexed from, address indexed to, uint amount, uint fromChainID, uint toChainID); 215 event LogAnySwapTradeTokensForTokens(address[] path, address indexed from, address indexed to, uint amountIn, uint amountOutMin, uint fromChainID, uint toChainID); 216 event LogAnySwapTradeTokensForNative(address[] path, address indexed from, address indexed to, uint amountIn, uint amountOutMin, uint fromChainID, uint toChainID); 217 218 modifier onlyMPC() { 219 require(msg.sender == mpc(), "AnyswapV3Router: FORBIDDEN"); 220 _; 221 } 222 223 function mpc() public view returns (address) { 224 if (block.timestamp >= _newMPCEffectiveTime) { 225 return _newMPC; 226 } 227 return _oldMPC; 228 } 229 230 function cID() public view returns (uint id) { 231 assembly {id := chainid()} 232 } 233 234 function changeMPC(address newMPC) public onlyMPC returns (bool) { 235 require(newMPC != address(0), "AnyswapV3Router: address(0x0)"); 236 _oldMPC = mpc(); 237 _newMPC = newMPC; 238 _newMPCEffectiveTime = block.timestamp + 2*24*3600; 239 emit LogChangeMPC(_oldMPC, _newMPC, _newMPCEffectiveTime, cID()); 240 return true; 241 } 242 243 function changeVault(address token, address newVault) public onlyMPC returns (bool) { 244 require(newVault != address(0), "AnyswapV3Router: address(0x0)"); 245 return AnyswapV1ERC20(token).changeVault(newVault); 246 } 247 248 function _anySwapOut(address from, address token, address to, uint amount, uint toChainID) internal { 249 AnyswapV1ERC20(token).burn(from, amount); 250 emit LogAnySwapOut(token, from, to, amount, cID(), toChainID); 251 } 252 253 // Swaps `amount` `token` from this chain to `toChainID` chain with recipient `to` 254 function anySwapOut(address token, address to, uint amount, uint toChainID) external { 255 _anySwapOut(msg.sender, token, to, amount, toChainID); 256 } 257 258 // Swaps `amount` `token` from this chain to `toChainID` chain with recipient `to` by minting with `underlying` 259 function anySwapOutUnderlying(address token, address to, uint amount, uint toChainID) external { 260 TransferHelper.safeTransferFrom(AnyswapV1ERC20(token).underlying(), msg.sender, token, amount); 261 AnyswapV1ERC20(token).depositVault(amount, msg.sender); 262 _anySwapOut(msg.sender, token, to, amount, toChainID); 263 } 264 265 function anySwapOutUnderlyingWithPermit( 266 address from, 267 address token, 268 address to, 269 uint amount, 270 uint deadline, 271 uint8 v, 272 bytes32 r, 273 bytes32 s, 274 uint toChainID 275 ) external { 276 address _underlying = AnyswapV1ERC20(token).underlying(); 277 IERC20(_underlying).permit(from, address(this), amount, deadline, v, r, s); 278 TransferHelper.safeTransferFrom(_underlying, from, token, amount); 279 AnyswapV1ERC20(token).depositVault(amount, from); 280 _anySwapOut(from, token, to, amount, toChainID); 281 } 282 283 function anySwapOutUnderlyingWithTransferPermit( 284 address from, 285 address token, 286 address to, 287 uint amount, 288 uint deadline, 289 uint8 v, 290 bytes32 r, 291 bytes32 s, 292 uint toChainID 293 ) external { 294 IERC20(AnyswapV1ERC20(token).underlying()).transferWithPermit(from, token, amount, deadline, v, r, s); 295 AnyswapV1ERC20(token).depositVault(amount, from); 296 _anySwapOut(from, token, to, amount, toChainID); 297 } 298 299 function anySwapOut(address[] calldata tokens, address[] calldata to, uint[] calldata amounts, uint[] calldata toChainIDs) external { 300 for (uint i = 0; i < tokens.length; i++) { 301 _anySwapOut(msg.sender, tokens[i], to[i], amounts[i], toChainIDs[i]); 302 } 303 } 304 305 // swaps `amount` `token` in `fromChainID` to `to` on this chainID 306 function _anySwapIn(bytes32 txs, address token, address to, uint amount, uint fromChainID) internal { 307 AnyswapV1ERC20(token).mint(to, amount); 308 emit LogAnySwapIn(txs, token, to, amount, fromChainID, cID()); 309 } 310 311 // swaps `amount` `token` in `fromChainID` to `to` on this chainID 312 // triggered by `anySwapOut` 313 function anySwapIn(bytes32 txs, address token, address to, uint amount, uint fromChainID) external onlyMPC { 314 _anySwapIn(txs, token, to, amount, fromChainID); 315 } 316 317 // swaps `amount` `token` in `fromChainID` to `to` on this chainID with `to` receiving `underlying` 318 function anySwapInUnderlying(bytes32 txs, address token, address to, uint amount, uint fromChainID) external onlyMPC { 319 _anySwapIn(txs, token, to, amount, fromChainID); 320 AnyswapV1ERC20(token).withdrawVault(to, amount, to); 321 } 322 323 // swaps `amount` `token` in `fromChainID` to `to` on this chainID with `to` receiving `underlying` if possible 324 function anySwapInAuto(bytes32 txs, address token, address to, uint amount, uint fromChainID) external onlyMPC { 325 _anySwapIn(txs, token, to, amount, fromChainID); 326 AnyswapV1ERC20 _anyToken = AnyswapV1ERC20(token); 327 address _underlying = _anyToken.underlying(); 328 if (_underlying != address(0) && IERC20(_underlying).balanceOf(token) >= amount) { 329 _anyToken.withdrawVault(to, amount, to); 330 } 331 } 332 333 // extracts mpc fee from bridge fees 334 function anySwapFeeTo(address token, uint amount) external onlyMPC { 335 address _mpc = mpc(); 336 AnyswapV1ERC20(token).mint(_mpc, amount); 337 AnyswapV1ERC20(token).withdrawVault(_mpc, amount, _mpc); 338 } 339 340 function anySwapIn(bytes32[] calldata txs, address[] calldata tokens, address[] calldata to, uint256[] calldata amounts, uint[] calldata fromChainIDs) external onlyMPC { 341 for (uint i = 0; i < tokens.length; i++) { 342 _anySwapIn(txs[i], tokens[i], to[i], amounts[i], fromChainIDs[i]); 343 } 344 } 345 346 // **** SWAP **** 347 // requires the initial amount to have already been sent to the first pair 348 function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual { 349 for (uint i; i < path.length - 1; i++) { 350 (address input, address output) = (path[i], path[i + 1]); 351 (address token0,) = SushiswapV2Library.sortTokens(input, output); 352 uint amountOut = amounts[i + 1]; 353 (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0)); 354 address to = i < path.length - 2 ? SushiswapV2Library.pairFor(factory, output, path[i + 2]) : _to; 355 ISushiswapV2Pair(SushiswapV2Library.pairFor(factory, input, output)).swap( 356 amount0Out, amount1Out, to, new bytes(0) 357 ); 358 } 359 } 360 361 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 362 function anySwapOutExactTokensForTokens( 363 uint amountIn, 364 uint amountOutMin, 365 address[] calldata path, 366 address to, 367 uint deadline, 368 uint toChainID 369 ) external virtual ensure(deadline) { 370 AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn); 371 emit LogAnySwapTradeTokensForTokens(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID); 372 } 373 374 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 375 function anySwapOutExactTokensForTokensUnderlying( 376 uint amountIn, 377 uint amountOutMin, 378 address[] calldata path, 379 address to, 380 uint deadline, 381 uint toChainID 382 ) external virtual ensure(deadline) { 383 TransferHelper.safeTransferFrom(AnyswapV1ERC20(path[0]).underlying(), msg.sender, path[0], amountIn); 384 AnyswapV1ERC20(path[0]).depositVault(amountIn, msg.sender); 385 AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn); 386 emit LogAnySwapTradeTokensForTokens(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID); 387 } 388 389 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 390 function anySwapOutExactTokensForTokensUnderlyingWithPermit( 391 address from, 392 uint amountIn, 393 uint amountOutMin, 394 address[] calldata path, 395 address to, 396 uint deadline, 397 uint8 v, 398 bytes32 r, 399 bytes32 s, 400 uint toChainID 401 ) external virtual ensure(deadline) { 402 address _underlying = AnyswapV1ERC20(path[0]).underlying(); 403 IERC20(_underlying).permit(from, address(this), amountIn, deadline, v, r, s); 404 TransferHelper.safeTransferFrom(_underlying, from, path[0], amountIn); 405 AnyswapV1ERC20(path[0]).depositVault(amountIn, from); 406 AnyswapV1ERC20(path[0]).burn(from, amountIn); 407 { 408 address[] memory _path = path; 409 address _from = from; 410 address _to = to; 411 uint _amountIn = amountIn; 412 uint _amountOutMin = amountOutMin; 413 uint _cID = cID(); 414 uint _toChainID = toChainID; 415 emit LogAnySwapTradeTokensForTokens(_path, _from, _to, _amountIn, _amountOutMin, _cID, _toChainID); 416 } 417 } 418 419 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 420 function anySwapOutExactTokensForTokensUnderlyingWithTransferPermit( 421 address from, 422 uint amountIn, 423 uint amountOutMin, 424 address[] calldata path, 425 address to, 426 uint deadline, 427 uint8 v, 428 bytes32 r, 429 bytes32 s, 430 uint toChainID 431 ) external virtual ensure(deadline) { 432 IERC20(AnyswapV1ERC20(path[0]).underlying()).transferWithPermit(from, path[0], amountIn, deadline, v, r, s); 433 AnyswapV1ERC20(path[0]).depositVault(amountIn, from); 434 AnyswapV1ERC20(path[0]).burn(from, amountIn); 435 emit LogAnySwapTradeTokensForTokens(path, from, to, amountIn, amountOutMin, cID(), toChainID); 436 } 437 438 // Swaps `amounts[path.length-1]` `path[path.length-1]` to `to` on this chain 439 // Triggered by `anySwapOutExactTokensForTokens` 440 function anySwapInExactTokensForTokens( 441 bytes32 txs, 442 uint amountIn, 443 uint amountOutMin, 444 address[] calldata path, 445 address to, 446 uint deadline, 447 uint fromChainID 448 ) external onlyMPC virtual ensure(deadline) returns (uint[] memory amounts) { 449 amounts = SushiswapV2Library.getAmountsOut(factory, amountIn, path); 450 require(amounts[amounts.length - 1] >= amountOutMin, 'SushiswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); 451 _anySwapIn(txs, path[0], SushiswapV2Library.pairFor(factory, path[0], path[1]), amounts[0], fromChainID); 452 _swap(amounts, path, to); 453 } 454 455 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 456 function anySwapOutExactTokensForNative( 457 uint amountIn, 458 uint amountOutMin, 459 address[] calldata path, 460 address to, 461 uint deadline, 462 uint toChainID 463 ) external virtual ensure(deadline) { 464 AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn); 465 emit LogAnySwapTradeTokensForNative(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID); 466 } 467 468 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 469 function anySwapOutExactTokensForNativeUnderlying( 470 uint amountIn, 471 uint amountOutMin, 472 address[] calldata path, 473 address to, 474 uint deadline, 475 uint toChainID 476 ) external virtual ensure(deadline) { 477 TransferHelper.safeTransferFrom(AnyswapV1ERC20(path[0]).underlying(), msg.sender, path[0], amountIn); 478 AnyswapV1ERC20(path[0]).depositVault(amountIn, msg.sender); 479 AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn); 480 emit LogAnySwapTradeTokensForNative(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID); 481 } 482 483 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 484 function anySwapOutExactTokensForNativeUnderlyingWithPermit( 485 address from, 486 uint amountIn, 487 uint amountOutMin, 488 address[] calldata path, 489 address to, 490 uint deadline, 491 uint8 v, 492 bytes32 r, 493 bytes32 s, 494 uint toChainID 495 ) external virtual ensure(deadline) { 496 address _underlying = AnyswapV1ERC20(path[0]).underlying(); 497 IERC20(_underlying).permit(from, address(this), amountIn, deadline, v, r, s); 498 TransferHelper.safeTransferFrom(_underlying, from, path[0], amountIn); 499 AnyswapV1ERC20(path[0]).depositVault(amountIn, from); 500 AnyswapV1ERC20(path[0]).burn(from, amountIn); 501 { 502 address[] memory _path = path; 503 address _from = from; 504 address _to = to; 505 uint _amountIn = amountIn; 506 uint _amountOutMin = amountOutMin; 507 uint _cID = cID(); 508 uint _toChainID = toChainID; 509 emit LogAnySwapTradeTokensForNative(_path, _from, _to, _amountIn, _amountOutMin, _cID, _toChainID); 510 } 511 } 512 513 // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to` 514 function anySwapOutExactTokensForNativeUnderlyingWithTransferPermit( 515 address from, 516 uint amountIn, 517 uint amountOutMin, 518 address[] calldata path, 519 address to, 520 uint deadline, 521 uint8 v, 522 bytes32 r, 523 bytes32 s, 524 uint toChainID 525 ) external virtual ensure(deadline) { 526 IERC20(AnyswapV1ERC20(path[0]).underlying()).transferWithPermit(from, path[0], amountIn, deadline, v, r, s); 527 AnyswapV1ERC20(path[0]).depositVault(amountIn, from); 528 AnyswapV1ERC20(path[0]).burn(from, amountIn); 529 emit LogAnySwapTradeTokensForNative(path, from, to, amountIn, amountOutMin, cID(), toChainID); 530 } 531 532 // Swaps `amounts[path.length-1]` `path[path.length-1]` to `to` on this chain 533 // Triggered by `anySwapOutExactTokensForNative` 534 function anySwapInExactTokensForNative( 535 bytes32 txs, 536 uint amountIn, 537 uint amountOutMin, 538 address[] calldata path, 539 address to, 540 uint deadline, 541 uint fromChainID 542 ) external onlyMPC virtual ensure(deadline) returns (uint[] memory amounts) { 543 require(path[path.length - 1] == wNATIVE, 'AnyswapV3Router: INVALID_PATH'); 544 amounts = SushiswapV2Library.getAmountsOut(factory, amountIn, path); 545 require(amounts[amounts.length - 1] >= amountOutMin, 'AnyswapV3Router: INSUFFICIENT_OUTPUT_AMOUNT'); 546 _anySwapIn(txs, path[0], SushiswapV2Library.pairFor(factory, path[0], path[1]), amounts[0], fromChainID); 547 _swap(amounts, path, address(this)); 548 IwNATIVE(wNATIVE).withdraw(amounts[amounts.length - 1]); 549 TransferHelper.safeTransferNative(to, amounts[amounts.length - 1]); 550 } 551 552 // **** LIBRARY FUNCTIONS **** 553 function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual returns (uint amountB) { 554 return SushiswapV2Library.quote(amountA, reserveA, reserveB); 555 } 556 557 function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) 558 public 559 pure 560 virtual 561 returns (uint amountOut) 562 { 563 return SushiswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); 564 } 565 566 function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) 567 public 568 pure 569 virtual 570 returns (uint amountIn) 571 { 572 return SushiswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); 573 } 574 575 function getAmountsOut(uint amountIn, address[] memory path) 576 public 577 view 578 virtual 579 returns (uint[] memory amounts) 580 { 581 return SushiswapV2Library.getAmountsOut(factory, amountIn, path); 582 } 583 584 function getAmountsIn(uint amountOut, address[] memory path) 585 public 586 view 587 virtual 588 returns (uint[] memory amounts) 589 { 590 return SushiswapV2Library.getAmountsIn(factory, amountOut, path); 591 } 592 }