Flash.sol 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 outAmount;
  47. uint256 inAmount;
  48. uint160 sqrtPriceLimitX96;
  49. address inToken;
  50. }
  51. function flashLoan(FlashLoanParams memory params) public onlyOwner returns (int256 amount0, int256 amount1) {
  52. IUniswapV3PoolActions pool = IUniswapV3PoolActions(params.pool);
  53. bytes memory callBackData = abi.encodeWithSelector(
  54. bytes4(keccak256(bytes("transfer(address,address,uint256)"))),
  55. params.inToken, params.pool, params.inAmount
  56. );
  57. poolMap[params.pool] = true;
  58. return pool.swap(
  59. address(this),
  60. params.inToken0,
  61. params.outAmount,
  62. params.sqrtPriceLimitX96 == 0
  63. ? (params.inToken0 ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)
  64. : params.sqrtPriceLimitX96,
  65. callBackData
  66. );
  67. }
  68. function uniswapV3SwapCallback(
  69. int256 amount0Delta,
  70. int256 amount1Delta,
  71. bytes calldata data
  72. ) override public onlyPool {
  73. Address.functionCall(address(this), data);
  74. }
  75. function transfer(address token, address to, uint256 amount) public onlyOwner {
  76. TransferHelper.safeTransfer(token, to, amount);
  77. }
  78. }