Flash.sol 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //SPDX-License-Identifier: Unlicense
  2. pragma solidity ^0.7.6;
  3. pragma abicoder v2;
  4. import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
  5. import '@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol';
  6. import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
  7. import '@uniswap/v3-core/contracts/libraries/TickMath.sol';
  8. import './base/TransferHelper.sol';
  9. import './base/Address.sol';
  10. contract Flash is IUniswapV3SwapCallback {
  11. mapping(address => bool) private adminMap;
  12. mapping(address => bool) private poolMap;
  13. mapping(address => mapping(address => uint256)) private approveMap;
  14. address private owner;
  15. constructor() {
  16. owner = msg.sender;
  17. adminMap[owner] = true;
  18. adminMap[address(this)] = true;
  19. }
  20. modifier onlyOwner() {
  21. require(msg.sender == owner || msg.sender == address(this), 'Not is owner.');
  22. _;
  23. }
  24. modifier onlyMaster() {
  25. require(msg.sender == owner || msg.sender == address(this) || adminMap[msg.sender], 'Not is master.');
  26. _;
  27. }
  28. modifier onlyPool() {
  29. require(msg.sender == owner || msg.sender == address(this) || poolMap[msg.sender], 'Not is pool.');
  30. _;
  31. }
  32. function addAdmin(address _addr) public onlyOwner {
  33. adminMap[_addr] = true;
  34. }
  35. function approve(uint256 _volume, address _token, address _to) public onlyOwner {
  36. TransferHelper.safeApprove(_token, _to, _volume);
  37. approveMap[_to][_token] = _volume;
  38. }
  39. function withdraw(address _token) public onlyOwner {
  40. uint256 token_balance = IERC20(_token).balanceOf(address(this));
  41. TransferHelper.safeTransfer(_token, owner, token_balance);
  42. }
  43. struct FlashLoanParams {
  44. address pool;
  45. bool inToken0;
  46. int256 inAmount;
  47. uint160 sqrtPriceLimitX96;
  48. address inToken;
  49. }
  50. function flashLoan(FlashLoanParams memory params) public onlyOwner returns (int256 amount0, int256 amount1) {
  51. IUniswapV3PoolActions pool = IUniswapV3PoolActions(params.pool);
  52. bytes memory callBackData = abi.encodeWithSelector(
  53. bytes4(keccak256(bytes("transfer(address,address,uint256)"))),
  54. params.inToken, params.pool, params.inAmount
  55. );
  56. poolMap[params.pool] = true;
  57. return pool.swap(
  58. address(this),
  59. params.inToken0,
  60. params.inAmount,
  61. params.sqrtPriceLimitX96 == 0
  62. ? (params.inToken0 ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)
  63. : params.sqrtPriceLimitX96,
  64. callBackData
  65. );
  66. }
  67. function uniswapV3SwapCallback(
  68. int256 amount0Delta,
  69. int256 amount1Delta,
  70. bytes calldata data
  71. ) override public onlyPool {
  72. Address.functionCall(address(this), data);
  73. }
  74. function transfer(address token, address to, uint256 amount) public onlyOwner {
  75. TransferHelper.safeTransfer(token, to, amount);
  76. }
  77. }