github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/exchange-scrapers/velodrome/velodrome.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity ^0.8.0;
     3  
     4  library Clones {
     5      /**
     6       * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     7       *
     8       * This function uses the create opcode, which should never revert.
     9       */
    10      function clone(address implementation) internal returns (address instance) {
    11          /// @solidity memory-safe-assembly
    12          assembly {
    13              // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
    14              // of the `implementation` address with the bytecode before the address.
    15              mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
    16              // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
    17              mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
    18              instance := create(0, 0x09, 0x37)
    19          }
    20          require(instance != address(0), "ERC1167: create failed");
    21      }
    22  
    23      /**
    24       * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
    25       *
    26       * This function uses the create2 opcode and a `salt` to deterministically deploy
    27       * the clone. Using the same `implementation` and `salt` multiple time will revert, since
    28       * the clones cannot be deployed twice at the same address.
    29       */
    30      function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
    31          /// @solidity memory-safe-assembly
    32          assembly {
    33              // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
    34              // of the `implementation` address with the bytecode before the address.
    35              mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
    36              // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
    37              mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
    38              instance := create2(0, 0x09, 0x37, salt)
    39          }
    40          require(instance != address(0), "ERC1167: create2 failed");
    41      }
    42  
    43      /**
    44       * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
    45       */
    46      function predictDeterministicAddress(
    47          address implementation,
    48          bytes32 salt,
    49          address deployer
    50      ) internal pure returns (address predicted) {
    51          /// @solidity memory-safe-assembly
    52          assembly {
    53              let ptr := mload(0x40)
    54              mstore(add(ptr, 0x38), deployer)
    55              mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
    56              mstore(add(ptr, 0x14), implementation)
    57              mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
    58              mstore(add(ptr, 0x58), salt)
    59              mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
    60              predicted := keccak256(add(ptr, 0x43), 0x55)
    61          }
    62      }
    63  
    64      /**
    65       * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
    66       */
    67      function predictDeterministicAddress(
    68          address implementation,
    69          bytes32 salt
    70      ) internal view returns (address predicted) {
    71          return predictDeterministicAddress(implementation, salt, address(this));
    72      }
    73  }
    74  
    75  interface IPoolFactory {
    76      event SetFeeManager(address feeManager);
    77      event SetPauser(address pauser);
    78      event SetPauseState(bool state);
    79      event SetVoter(address voter);
    80      event PoolCreated(address indexed token0, address indexed token1, bool indexed stable, address pool, uint256);
    81      event SetCustomFee(address indexed pool, uint256 fee);
    82  
    83      error FeeInvalid();
    84      error FeeTooHigh();
    85      error InvalidPool();
    86      error NotFeeManager();
    87      error NotPauser();
    88      error NotSinkConverter();
    89      error NotVoter();
    90      error PoolAlreadyExists();
    91      error SameAddress();
    92      error ZeroFee();
    93      error ZeroAddress();
    94  
    95      /// @notice returns the number of pools created from this factory
    96      function allPoolsLength() external view returns (uint256);
    97  
    98      /// @notice Is a valid pool created by this factory.
    99      /// @param .
   100      function isPool(address pool) external view returns (bool);
   101  
   102      /// @notice Support for Velodrome v1 which wraps around isPool(pool);
   103      /// @param .
   104      function isPair(address pool) external view returns (bool);
   105  
   106      /// @notice Return address of pool created by this factory
   107      /// @param tokenA .
   108      /// @param tokenB .
   109      /// @param stable True if stable, false if volatile
   110      function getPool(address tokenA, address tokenB, bool stable) external view returns (address);
   111  
   112      /// @notice Support for v3-style pools which wraps around getPool(tokenA,tokenB,stable)
   113      /// @dev fee is converted to stable boolean.
   114      /// @param tokenA .
   115      /// @param tokenB .
   116      /// @param fee  1 if stable, 0 if volatile, else returns address(0)
   117      function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address);
   118  
   119      /// @notice Support for Velodrome v1 pools as a "pool" was previously referenced as "pair"
   120      /// @notice Wraps around getPool(tokenA,tokenB,stable)
   121      function getPair(address tokenA, address tokenB, bool stable) external view returns (address);
   122  
   123      /// @dev Only called once to set to Voter.sol - Voter does not have a function
   124      ///      to call this contract method, so once set it's immutable.
   125      ///      This also follows convention of setVoterAndDistributor() in VotingEscrow.sol
   126      /// @param _voter .
   127      function setVoter(address _voter) external;
   128  
   129      function setSinkConverter(address _sinkConvert, address _velo, address _veloV2) external;
   130  
   131      function setPauser(address _pauser) external;
   132  
   133      function setPauseState(bool _state) external;
   134  
   135      function setFeeManager(address _feeManager) external;
   136  
   137      /// @notice Set default fee for stable and volatile pools.
   138      /// @dev Throws if higher than maximum fee.
   139      ///      Throws if fee is zero.
   140      /// @param _stable Stable or volatile pool.
   141      /// @param _fee .
   142      function setFee(bool _stable, uint256 _fee) external;
   143  
   144      /// @notice Set overriding fee for a pool from the default
   145      /// @dev A custom fee of zero means the default fee will be used.
   146      function setCustomFee(address _pool, uint256 _fee) external;
   147  
   148      /// @notice Returns fee for a pool, as custom fees are possible.
   149      function getFee(address _pool, bool _stable) external view returns (uint256);
   150  
   151      /// @notice Create a pool given two tokens and if they're stable/volatile
   152      /// @dev token order does not matter
   153      /// @param tokenA .
   154      /// @param tokenB .
   155      /// @param stable .
   156      function createPool(address tokenA, address tokenB, bool stable) external returns (address pool);
   157  
   158      /// @notice Support for v3-style pools which wraps around createPool(tokena,tokenB,stable)
   159      /// @dev fee is converted to stable boolean
   160      /// @dev token order does not matter
   161      /// @param tokenA .
   162      /// @param tokenB .
   163      /// @param fee 1 if stable, 0 if volatile, else revert
   164      function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool);
   165  
   166      /// @notice Support for Velodrome v1 which wraps around createPool(tokenA,tokenB,stable)
   167      function createPair(address tokenA, address tokenB, bool stable) external returns (address pool);
   168  
   169      function isPaused() external view returns (bool);
   170  
   171      function velo() external view returns (address);
   172  
   173      function veloV2() external view returns (address);
   174  
   175      function voter() external view returns (address);
   176  
   177      function sinkConverter() external view returns (address);
   178  
   179      function implementation() external view returns (address);
   180  }
   181  
   182  contract PoolFactory is IPoolFactory {
   183      address public immutable implementation;
   184  
   185      bool public isPaused;
   186      address public pauser;
   187  
   188      uint256 public stableFee;
   189      uint256 public volatileFee;
   190      uint256 public constant MAX_FEE = 100; // 1%
   191      // Override to indicate there is custom 0% fee - as a 0 value in the customFee mapping indicates
   192      // that no custom fee rate has been set
   193      uint256 public constant ZERO_FEE_INDICATOR = 420;
   194      address public feeManager;
   195  
   196      /// @dev used to change the name/symbol of the pool by calling emergencyCouncil
   197      address public voter;
   198  
   199      /// @dev used to enable Router conversion of v1 => v2 VEL0
   200      address public velo;
   201      address public veloV2;
   202      address public sinkConverter;
   203  
   204      mapping(address => mapping(address => mapping(bool => address))) private _getPool;
   205      address[] public allPools;
   206      mapping(address => bool) private _isPool; // simplified check if its a pool, given that `stable` flag might not be available in peripherals
   207      mapping(address => uint256) public customFee; // override for custom fees
   208  
   209      address internal _temp0;
   210      address internal _temp1;
   211      bool internal _temp;
   212  
   213      constructor(address _implementation) {
   214          implementation = _implementation;
   215          voter = msg.sender;
   216          pauser = msg.sender;
   217          feeManager = msg.sender;
   218          sinkConverter = msg.sender;
   219          isPaused = false;
   220          stableFee = 5; // 0.05%
   221          volatileFee = 30; // 0.3%
   222      }
   223  
   224      /// @inheritdoc IPoolFactory
   225      function allPoolsLength() external view returns (uint256) {
   226          return allPools.length;
   227      }
   228  
   229      /// @inheritdoc IPoolFactory
   230      function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address) {
   231          return fee > 1 ? address(0) : fee == 1 ? _getPool[tokenA][tokenB][true] : _getPool[tokenA][tokenB][false];
   232      }
   233  
   234      /// @inheritdoc IPoolFactory
   235      function getPool(address tokenA, address tokenB, bool stable) external view returns (address) {
   236          return _getPool[tokenA][tokenB][stable];
   237      }
   238  
   239      /// @inheritdoc IPoolFactory
   240      function getPair(address tokenA, address tokenB, bool stable) external view returns (address) {
   241          return _getPool[tokenA][tokenB][stable];
   242      }
   243  
   244      /// @inheritdoc IPoolFactory
   245      function isPool(address pool) external view returns (bool) {
   246          return _isPool[pool];
   247      }
   248  
   249      /// @inheritdoc IPoolFactory
   250      function isPair(address pool) external view returns (bool) {
   251          return _isPool[pool];
   252      }
   253  
   254      /// @inheritdoc IPoolFactory
   255      function setVoter(address _voter) external {
   256          if (msg.sender != voter) revert NotVoter();
   257          voter = _voter;
   258          emit SetVoter(_voter);
   259      }
   260  
   261      /// @inheritdoc IPoolFactory
   262      function setSinkConverter(address _sinkConverter, address _velo, address _veloV2) external {
   263          if (msg.sender != sinkConverter) revert NotSinkConverter();
   264          sinkConverter = _sinkConverter;
   265          velo = _velo;
   266          veloV2 = _veloV2;
   267  
   268          // Follow logic of createPool() - except add getPool values for both volatile
   269          // and stable so there is no way to create an additional velo => veloV2 pool
   270          (address token0, address token1) = _velo < _veloV2 ? (_velo, _veloV2) : (_veloV2, _velo);
   271          _getPool[token0][token1][true] = sinkConverter;
   272          _getPool[token1][token0][true] = sinkConverter;
   273          _getPool[token0][token1][false] = sinkConverter;
   274          _getPool[token1][token0][false] = sinkConverter;
   275          allPools.push(sinkConverter);
   276          _isPool[sinkConverter] = true;
   277  
   278          // emit two events - for both the "stable" and "volatile" pool being created
   279          emit PoolCreated(token0, token1, true, sinkConverter, allPools.length);
   280          emit PoolCreated(token0, token1, false, sinkConverter, allPools.length);
   281      }
   282  
   283      function setPauser(address _pauser) external {
   284          if (msg.sender != pauser) revert NotPauser();
   285          if (_pauser == address(0)) revert ZeroAddress();
   286          pauser = _pauser;
   287          emit SetPauser(_pauser);
   288      }
   289  
   290      function setPauseState(bool _state) external {
   291          if (msg.sender != pauser) revert NotPauser();
   292          isPaused = _state;
   293          emit SetPauseState(_state);
   294      }
   295  
   296      function setFeeManager(address _feeManager) external {
   297          if (msg.sender != feeManager) revert NotFeeManager();
   298          if (_feeManager == address(0)) revert ZeroAddress();
   299          feeManager = _feeManager;
   300          emit SetFeeManager(_feeManager);
   301      }
   302  
   303      /// @inheritdoc IPoolFactory
   304      function setFee(bool _stable, uint256 _fee) external {
   305          if (msg.sender != feeManager) revert NotFeeManager();
   306          if (_fee > MAX_FEE) revert FeeTooHigh();
   307          if (_fee == 0) revert ZeroFee();
   308          if (_stable) {
   309              stableFee = _fee;
   310          } else {
   311              volatileFee = _fee;
   312          }
   313      }
   314  
   315      /// @inheritdoc IPoolFactory
   316      function setCustomFee(address pool, uint256 fee) external {
   317          if (msg.sender != feeManager) revert NotFeeManager();
   318          if (fee > MAX_FEE && fee != ZERO_FEE_INDICATOR) revert FeeTooHigh();
   319          if (!_isPool[pool]) revert InvalidPool();
   320  
   321          customFee[pool] = fee;
   322          emit SetCustomFee(pool, fee);
   323      }
   324  
   325      /// @inheritdoc IPoolFactory
   326      function getFee(address pool, bool _stable) public view returns (uint256) {
   327          uint256 fee = customFee[pool];
   328          return fee == ZERO_FEE_INDICATOR ? 0 : fee != 0 ? fee : _stable ? stableFee : volatileFee;
   329      }
   330  
   331      /// @inheritdoc IPoolFactory
   332      function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool) {
   333          if (fee > 1) revert FeeInvalid();
   334          bool stable = fee == 1;
   335          return createPool(tokenA, tokenB, stable);
   336      }
   337  
   338      /// @inheritdoc IPoolFactory
   339      function createPool(address tokenA, address tokenB, bool stable) public returns (address pool) {
   340          if (tokenA == tokenB) revert SameAddress();
   341          (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
   342          if (token0 == address(0)) revert ZeroAddress();
   343          if (_getPool[token0][token1][stable] != address(0)) revert PoolAlreadyExists();
   344          bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // salt includes stable as well, 3 parameters
   345          pool = Clones.cloneDeterministic(implementation, salt);
   346          IPool(pool).initialize(token0, token1, stable);
   347          _getPool[token0][token1][stable] = pool;
   348          _getPool[token1][token0][stable] = pool; // populate mapping in the reverse direction
   349          allPools.push(pool);
   350          _isPool[pool] = true;
   351          emit PoolCreated(token0, token1, stable, pool, allPools.length);
   352      }
   353  
   354      /// @inheritdoc IPoolFactory
   355      function createPair(address tokenA, address tokenB, bool stable) external returns (address pool) {
   356          return createPool(tokenA, tokenB, stable);
   357      }
   358  }
   359  
   360  interface IPool {
   361      error DepositsNotEqual();
   362      error BelowMinimumK();
   363      error FactoryAlreadySet();
   364      error InsufficientLiquidity();
   365      error InsufficientLiquidityMinted();
   366      error InsufficientLiquidityBurned();
   367      error InsufficientOutputAmount();
   368      error InsufficientInputAmount();
   369      error IsPaused();
   370      error InvalidTo();
   371      error K();
   372      error NotEmergencyCouncil();
   373  
   374      event Fees(address indexed sender, uint256 amount0, uint256 amount1);
   375      event Mint(address indexed sender, uint256 amount0, uint256 amount1);
   376      event Burn(address indexed sender, address indexed to, uint256 amount0, uint256 amount1);
   377      event Swap(
   378          address indexed sender,
   379          address indexed to,
   380          uint256 amount0In,
   381          uint256 amount1In,
   382          uint256 amount0Out,
   383          uint256 amount1Out
   384      );
   385      event Sync(uint256 reserve0, uint256 reserve1);
   386      event Claim(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1);
   387  
   388      function metadata()
   389          external
   390          view
   391          returns (uint256 dec0, uint256 dec1, uint256 r0, uint256 r1, bool st, address t0, address t1);
   392  
   393      function claimFees() external returns (uint256, uint256);
   394  
   395      function tokens() external view returns (address, address);
   396  
   397      function token0() external view returns (address);
   398  
   399      function token1() external view returns (address);
   400  
   401      function stable() external view returns (bool);
   402  
   403      function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
   404  
   405      function burn(address to) external returns (uint256 amount0, uint256 amount1);
   406  
   407      function mint(address to) external returns (uint256 liquidity);
   408  
   409      function getReserves() external view returns (uint256 _reserve0, uint256 _reserve1, uint256 _blockTimestampLast);
   410  
   411      function getAmountOut(uint256, address) external view returns (uint256);
   412  
   413      function skim(address to) external;
   414  
   415      function initialize(address _token0, address _token1, bool _stable) external;
   416  }
   417  
   418  /**
   419   * @dev Interface of the ERC20 standard as defined in the EIP.
   420   */
   421  interface IERC20 {
   422      /**
   423       * @dev Emitted when `value` tokens are moved from one account (`from`) to
   424       * another (`to`).
   425       *
   426       * Note that `value` may be zero.
   427       */
   428      event Transfer(address indexed from, address indexed to, uint256 value);
   429  
   430      /**
   431       * @dev Emitted when the allowance of a `spender` for an `owner` is set by
   432       * a call to {approve}. `value` is the new allowance.
   433       */
   434      event Approval(address indexed owner, address indexed spender, uint256 value);
   435  
   436      /**
   437       * @dev Returns the amount of tokens in existence.
   438       */
   439      function totalSupply() external view returns (uint256);
   440  
   441      /**
   442       * @dev Returns the amount of tokens owned by `account`.
   443       */
   444      function balanceOf(address account) external view returns (uint256);
   445  
   446      /**
   447       * @dev Moves `amount` tokens from the caller's account to `to`.
   448       *
   449       * Returns a boolean value indicating whether the operation succeeded.
   450       *
   451       * Emits a {Transfer} event.
   452       */
   453      function transfer(address to, uint256 amount) external returns (bool);
   454  
   455      /**
   456       * @dev Returns the remaining number of tokens that `spender` will be
   457       * allowed to spend on behalf of `owner` through {transferFrom}. This is
   458       * zero by default.
   459       *
   460       * This value changes when {approve} or {transferFrom} are called.
   461       */
   462      function allowance(address owner, address spender) external view returns (uint256);
   463  
   464      /**
   465       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
   466       *
   467       * Returns a boolean value indicating whether the operation succeeded.
   468       *
   469       * IMPORTANT: Beware that changing an allowance with this method brings the risk
   470       * that someone may use both the old and the new allowance by unfortunate
   471       * transaction ordering. One possible solution to mitigate this race
   472       * condition is to first reduce the spender's allowance to 0 and set the
   473       * desired value afterwards:
   474       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   475       *
   476       * Emits an {Approval} event.
   477       */
   478      function approve(address spender, uint256 amount) external returns (bool);
   479  
   480      /**
   481       * @dev Moves `amount` tokens from `from` to `to` using the
   482       * allowance mechanism. `amount` is then deducted from the caller's
   483       * allowance.
   484       *
   485       * Returns a boolean value indicating whether the operation succeeded.
   486       *
   487       * Emits a {Transfer} event.
   488       */
   489      function transferFrom(address from, address to, uint256 amount) external returns (bool);
   490  }
   491  
   492  interface IERC20Metadata is IERC20 {
   493      /**
   494       * @dev Returns the name of the token.
   495       */
   496      function name() external view returns (string memory);
   497  
   498      /**
   499       * @dev Returns the symbol of the token.
   500       */
   501      function symbol() external view returns (string memory);
   502  
   503      /**
   504       * @dev Returns the decimals places of the token.
   505       */
   506      function decimals() external view returns (uint8);
   507  }