creation_sourcecode: // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;
  pragma abicoder v2;
  
  interface ICurveMetaRegister {
  
      function get_balances(address _pool) external view returns (uint256[8] memory);
  
      function get_underlying_balances(address _pool) external view returns (uint256[8] memory);
  
      function get_coins(address _pool) external view returns (address[8] memory);
  
      function get_underlying_coins(address _pool) external view returns (address[8] memory);
  
      function is_meta(address _pool) external view returns (bool);
  
      function get_n_coins(address _pool) external view returns (uint256);
  
  }
  
  interface ICurveV2Pool {
  
      function gamma() external view returns (uint256);
  
      function D() external view returns (uint256);
  
      function price_scale(uint256 k) external view returns (uint256);
  
      function fee_gamma() external view returns (uint256);
  
      function mid_fee() external view returns (uint256);
  
      function out_fee() external view returns (uint256);
  
  }
  
  interface ICurveNGPool {
  
      function offpeg_fee_multiplier() external view returns (uint256);
  
      function stored_rates() external view returns (uint256[] memory);
  
  }
  
  interface ICurveNG2Pool {
  
      function stored_rates() external view returns (uint256[2] memory);
  
  }
  
  interface ICurvePool {
  
      function A() external view returns (uint256);
  
      function fee() external view returns (uint256);
  
      function price_scale() external view returns (uint256);
  
      function get_virtual_price() external view returns (uint256);
  
  }
  
  interface IRai {
  
      function redemption_price_snap() external view returns (address);
  
      function snappedRedemptionPrice() external view returns (uint256);
  
  }
  
  contract QueryCurve {
  
      address public metaRegister;
      address public owner;
  
      constructor(address register) {
          metaRegister = register;
          owner = msg.sender;
      }
  
      function get_balances(
          address pool
      ) public view returns (uint256[8] memory balances) {
  
          bool is_meta = ICurveMetaRegister(metaRegister).is_meta(pool);
  
          if (is_meta) {
              return ICurveMetaRegister(metaRegister).get_balances(pool);
          } else {
              return ICurveMetaRegister(metaRegister).get_underlying_balances(pool);
          }
  
      }
  
      function get_tokens(
          address pool
      ) public view returns (address[8] memory tokens) {
  
          if (pool == 0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714) {
              return ICurveMetaRegister(metaRegister).get_coins(pool);
          }
  
          bool is_meta = ICurveMetaRegister(metaRegister).is_meta(pool);
  
          if (is_meta) {
              return ICurveMetaRegister(metaRegister).get_coins(pool);
          } else {
              return ICurveMetaRegister(metaRegister).get_underlying_coins(pool);
          }
  
      }
  
      function get_coins(
          address pool
      ) public view returns (address[8] memory tokens) {
          return ICurveMetaRegister(metaRegister).get_coins(pool);
      }
  
      function get_params(
          address pool
      ) public view returns (int24 name, uint256 A, uint256 fee, uint256 D, uint256 gamma, uint256 price,
          uint256 fee_gamma, uint256 mid_fee, uint256 out_fee, uint256 liquidity, uint256 gas_fee, uint256[] memory price_scale) {
          //params[0] 1-v1  2-v2  3-NG
          name = 1;
          gamma = 0;
          D = 0;
          price = 0;
          fee_gamma = 0;
          mid_fee = 0;
          out_fee = 0;
          liquidity = 0;
          gas_fee = 0;
          uint256 n = ICurveMetaRegister(metaRegister).get_n_coins(pool);
          price_scale = new uint256[](n - 1);
          try ICurveV2Pool(pool).gamma() returns (uint256 result0) {
              gamma = result0;
              name = 2;
              D = ICurveV2Pool(pool).D();
              if (n > 2) {
                  for (uint256 i = 0; i < n - 1; i ++) {
                      price_scale[i] = ICurveV2Pool(pool).price_scale(i);
                  }
              } else {
                  price_scale[0] = ICurvePool(pool).price_scale();
              }
              fee_gamma = ICurveV2Pool(pool).fee_gamma();
              mid_fee = ICurveV2Pool(pool).mid_fee();
              out_fee = ICurveV2Pool(pool).out_fee();
          } catch {
              price = ICurvePool(pool).get_virtual_price();
              try ICurveNGPool(pool).offpeg_fee_multiplier() returns (uint256 result1) {
                  gas_fee = result1;
                  name = 3;
                  price_scale = new uint256[](n);
                  price_scale = ICurveNGPool(pool).stored_rates();
              } catch {
                  for (uint256 i = 0; i < n - 1; i ++) {
                      price_scale[i] = 0;
                  }
                  if (pool == 0x618788357D0EBd8A37e763ADab3bc575D54c2C7d) {
                      address snap = IRai(pool).redemption_price_snap();
                      liquidity = IRai(snap).snappedRedemptionPrice();
                  } else if (pool == 0xBfAb6FA95E0091ed66058ad493189D2cB29385E6) {
                      uint256[2] memory price_scale0 = ICurveNG2Pool(pool).stored_rates();
                      price_scale = new uint256[](n);
                      price_scale[0] = price_scale0[0];
                      price_scale[1] = price_scale0[1];
                  }
              }
          }
          A = ICurvePool(pool).A();
          fee = ICurvePool(pool).fee();
  
      }
  
      function setRegister(address newRegister) public {
          require(owner == msg.sender, "Ownable: caller is not the owner");
          metaRegister = newRegister;
      }
  
  }