107 lines
4.1 KiB
Solidity
107 lines
4.1 KiB
Solidity
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
pragma solidity =0.7.6;
|
|
pragma abicoder v2;
|
|
|
|
import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
|
|
import '@uniswap/lib/contracts/libraries/SafeERC20Namer.sol';
|
|
|
|
import './libraries/ChainId.sol';
|
|
import './interfaces/INonfungiblePositionManager.sol';
|
|
import './interfaces/INonfungibleTokenPositionDescriptor.sol';
|
|
import './interfaces/IERC20Metadata.sol';
|
|
import './libraries/PoolAddress.sol';
|
|
import './libraries/NFTDescriptor.sol';
|
|
import './libraries/TokenRatioSortOrder.sol';
|
|
|
|
/// @title Describes NFT token positions
|
|
/// @notice Produces a string containing the data URI for a JSON metadata string
|
|
contract NonfungibleTokenPositionDescriptor is INonfungibleTokenPositionDescriptor {
|
|
address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
|
|
address private constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
|
|
address private constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
|
|
address private constant TBTC = 0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa;
|
|
address private constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
|
|
|
|
address public immutable WETH9;
|
|
|
|
constructor(address _WETH9) {
|
|
WETH9 = _WETH9;
|
|
}
|
|
|
|
/// @inheritdoc INonfungibleTokenPositionDescriptor
|
|
function tokenURI(INonfungiblePositionManager positionManager, uint256 tokenId)
|
|
external
|
|
view
|
|
override
|
|
returns (string memory)
|
|
{
|
|
(, , address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, , , , , ) =
|
|
positionManager.positions(tokenId);
|
|
|
|
IUniswapV3Pool pool =
|
|
IUniswapV3Pool(
|
|
PoolAddress.computeAddress(
|
|
positionManager.factory(),
|
|
PoolAddress.PoolKey({token0: token0, token1: token1, fee: fee})
|
|
)
|
|
);
|
|
|
|
bool _flipRatio = flipRatio(token0, token1, ChainId.get());
|
|
address quoteTokenAddress = !_flipRatio ? token1 : token0;
|
|
address baseTokenAddress = !_flipRatio ? token0 : token1;
|
|
(, int24 tick, , , , , ) = pool.slot0();
|
|
|
|
return
|
|
NFTDescriptor.constructTokenURI(
|
|
NFTDescriptor.ConstructTokenURIParams({
|
|
tokenId: tokenId,
|
|
quoteTokenAddress: quoteTokenAddress,
|
|
baseTokenAddress: baseTokenAddress,
|
|
quoteTokenSymbol: quoteTokenAddress == WETH9
|
|
? 'ETH'
|
|
: SafeERC20Namer.tokenSymbol(quoteTokenAddress),
|
|
baseTokenSymbol: baseTokenAddress == WETH9 ? 'ETH' : SafeERC20Namer.tokenSymbol(baseTokenAddress),
|
|
quoteTokenDecimals: IERC20Metadata(quoteTokenAddress).decimals(),
|
|
baseTokenDecimals: IERC20Metadata(baseTokenAddress).decimals(),
|
|
flipRatio: _flipRatio,
|
|
tickLower: tickLower,
|
|
tickUpper: tickUpper,
|
|
tickCurrent: tick,
|
|
tickSpacing: pool.tickSpacing(),
|
|
fee: fee,
|
|
poolAddress: address(pool)
|
|
})
|
|
);
|
|
}
|
|
|
|
function flipRatio(
|
|
address token0,
|
|
address token1,
|
|
uint256 chainId
|
|
) public view returns (bool) {
|
|
return tokenRatioPriority(token0, chainId) > tokenRatioPriority(token1, chainId);
|
|
}
|
|
|
|
function tokenRatioPriority(address token, uint256 chainId) public view returns (int256) {
|
|
if (token == WETH9) {
|
|
return TokenRatioSortOrder.DENOMINATOR;
|
|
}
|
|
if (chainId == 1) {
|
|
if (token == USDC) {
|
|
return TokenRatioSortOrder.NUMERATOR_MOST;
|
|
} else if (token == USDT) {
|
|
return TokenRatioSortOrder.NUMERATOR_MORE;
|
|
} else if (token == DAI) {
|
|
return TokenRatioSortOrder.NUMERATOR;
|
|
} else if (token == TBTC) {
|
|
return TokenRatioSortOrder.DENOMINATOR_MORE;
|
|
} else if (token == WBTC) {
|
|
return TokenRatioSortOrder.DENOMINATOR_MOST;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
}
|