Skip to content

Commit

Permalink
currency name plus more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dianakocsis committed Oct 4, 2024
1 parent 072102f commit bd90cee
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 60 deletions.
4 changes: 2 additions & 2 deletions script/DeployPosm.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ contract DeployPosmTest is Script {
address poolManager,
address permit2,
uint256 unsubscribeGasLimit,
address weth,
address wrappedNative,
string memory nativeCurrencyLabel
) public returns (PositionDescriptor positionDescriptor, PositionManager posm) {
vm.startBroadcast();

positionDescriptor = new PositionDescriptor(IPoolManager(poolManager), weth, nativeCurrencyLabel);
positionDescriptor = new PositionDescriptor(IPoolManager(poolManager), wrappedNative, nativeCurrencyLabel);
console2.log("PositionDescriptor", address(positionDescriptor));

posm = new PositionManager{salt: hex"03"}(
Expand Down
10 changes: 5 additions & 5 deletions src/PositionDescriptor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {IPositionDescriptor} from "./interfaces/IPositionDescriptor.sol";
import {PositionInfo, PositionInfoLibrary} from "./libraries/PositionInfoLibrary.sol";
import {Descriptor} from "./libraries/Descriptor.sol";
import {CurrencyRatioSortOrder} from "./libraries/CurrencyRatioSortOrder.sol";
import {SafeERC20Metadata} from "./libraries/SafeERC20Metadata.sol";
import {SafeCurrencyMetadata} from "./libraries/SafeCurrencyMetadata.sol";

/// @title Describes NFT token positions
/// @notice Produces a string containing the data URI for a JSON metadata string
Expand Down Expand Up @@ -63,10 +63,10 @@ contract PositionDescriptor is IPositionDescriptor {
tokenId: tokenId,
quoteCurrency: quoteCurrency,
baseCurrency: baseCurrency,
quoteCurrencySymbol: SafeERC20Metadata.currencySymbol(quoteCurrency, nativeCurrencyLabel),
baseCurrencySymbol: SafeERC20Metadata.currencySymbol(baseCurrency, nativeCurrencyLabel),
quoteCurrencyDecimals: SafeERC20Metadata.currencyDecimals(quoteCurrency),
baseCurrencyDecimals: SafeERC20Metadata.currencyDecimals(baseCurrency),
quoteCurrencySymbol: SafeCurrencyMetadata.currencySymbol(quoteCurrency, nativeCurrencyLabel),
baseCurrencySymbol: SafeCurrencyMetadata.currencySymbol(baseCurrency, nativeCurrencyLabel),
quoteCurrencyDecimals: SafeCurrencyMetadata.currencyDecimals(quoteCurrency),
baseCurrencyDecimals: SafeCurrencyMetadata.currencyDecimals(baseCurrency),
flipRatio: _flipRatio,
tickLower: positionInfo.tickLower(),
tickUpper: positionInfo.tickUpper(),
Expand Down
14 changes: 7 additions & 7 deletions src/libraries/Descriptor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -439,16 +439,16 @@ library Descriptor {
} else {
// represents fee less than 1%
// else if decimal < 1
nZeros = 5 - digits; // number of zeros, inlcuding the zero before decimal
params.zerosStartIndex = 2; // leading zeros will start after the decimal point
params.zerosEndIndex = uint8(nZeros + params.zerosStartIndex - 1); // end index for leading zeros
params.bufferLength = uint8(nZeros + numSigfigs + 2); // total length of string buffer, including "0." and "%"
params.sigfigIndex = uint8(params.bufferLength - 2); // index of starting signficant figure
nZeros = 5 - digits;
params.zerosStartIndex = 2;
params.zerosEndIndex = uint8(nZeros + params.zerosStartIndex - 1);
params.bufferLength = uint8(nZeros + numSigfigs + 2);
params.sigfigIndex = uint8(params.bufferLength - 2);
params.isLessThanOne = true;
}
params.sigfigs = uint256(fee) / (10 ** (digits - numSigfigs)); // the signficant figures of the fee
params.sigfigs = uint256(fee) / (10 ** (digits - numSigfigs));
params.isPercent = true;
params.decimalIndex = digits > 4 ? uint8(digits - 4) : 0; // based on total number of digits in the fee
params.decimalIndex = digits > 4 ? uint8(digits - 4) : 0;
return generateDecimalString(params);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,12 @@ import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IER
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {AddressStringUtil} from "./AddressStringUtil.sol";

/// @title SafeERC20Metadata
/// @title SafeCurrencyMetadata
/// @notice can produce symbols and decimals from inconsistent or absent ERC20 implementations
/// @dev Reference: https://github.com/Uniswap/solidity-lib/blob/master/contracts/libraries/SafeERC20Namer.sol
library SafeERC20Metadata {
library SafeCurrencyMetadata {
using CurrencyLibrary for Currency;

function bytes32ToString(bytes32 x) private pure returns (string memory) {
bytes memory bytesString = new bytes(32);
uint256 charCount = 0;
for (uint256 j = 0; j < 32; j++) {
bytes1 char = x[j];
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint256 j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}

/// @notice produces a token symbol from the address - the first 6 hex of the address string in upper case
/// @param token the token address
/// @return the token symbol
function addressToSymbol(address token) private pure returns (string memory) {
return AddressStringUtil.toAsciiString(token, 6);
}

/// @notice calls an external view token contract method that returns a symbol, and parses the output into a string
/// @param token the token address
/// @param selector the selector of the symbol method
/// @return the token symbol
function callAndParseStringReturn(address token, bytes4 selector) private view returns (string memory) {
(bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(selector));
// if not implemented, return empty string
if (!success) {
return "";
}
// bytes32 data always has length 32
if (data.length == 32) {
bytes32 decoded = abi.decode(data, (bytes32));
return bytes32ToString(decoded);
} else if (data.length > 64) {
return abi.decode(data, (string));
}
return "";
}

/// @notice attempts to extract the token symbol. if it does not implement symbol, returns a symbol derived from the address
/// @param currency The currency
/// @param nativeLabel The native label
Expand Down Expand Up @@ -89,4 +45,48 @@ library SafeERC20Metadata {
}
return 0;
}

function bytes32ToString(bytes32 x) private pure returns (string memory) {
bytes memory bytesString = new bytes(32);
uint256 charCount = 0;
for (uint256 j = 0; j < 32; j++) {
bytes1 char = x[j];
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint256 j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}

/// @notice produces a symbol from the address - the first 6 hex of the address string in upper case
/// @param currencyAddress the address of the currency
/// @return the symbol
function addressToSymbol(address currencyAddress) private pure returns (string memory) {
return AddressStringUtil.toAsciiString(currencyAddress, 6);
}

/// @notice calls an external view contract method that returns a symbol, and parses the output into a string
/// @param currencyAddress the address of the currency
/// @param selector the selector of the symbol method
/// @return the symbol
function callAndParseStringReturn(address currencyAddress, bytes4 selector) private view returns (string memory) {
(bool success, bytes memory data) = currencyAddress.staticcall(abi.encodeWithSelector(selector));
// if not implemented, return empty string
if (!success) {
return "";
}
// bytes32 data always has length 32
if (data.length == 32) {
bytes32 decoded = abi.decode(data, (bytes32));
return bytes32ToString(decoded);
} else if (data.length > 64) {
return abi.decode(data, (string));
}
return "";
}
}
32 changes: 32 additions & 0 deletions test/libraries/Descriptor.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";

contract DescriptorTest is Test {
function test_feeToPercentString_succeeds() public pure {
assertEq(Descriptor.feeToPercentString(0x800000), "Dynamic");
assertEq(Descriptor.feeToPercentString(0), "0%");
assertEq(Descriptor.feeToPercentString(1), "0.0001%");
assertEq(Descriptor.feeToPercentString(30), "0.003%");
Expand Down Expand Up @@ -115,4 +116,35 @@ contract DescriptorTest is Test {
assertEq(Descriptor.tickToDecimalString(1000, tickSpacing, 18, 10, true), "90484000");
assertEq(Descriptor.tickToDecimalString(1000, tickSpacing, 10, 18, true), "0.0000000090484");
}

function test_fixedPointToDecimalString() public pure {
assertEq(
Descriptor.fixedPointToDecimalString(1457647476727839560029885420909913413788472405159, 18, 18),
"338490000000000000000000000000000000000"
);
assertEq(
Descriptor.fixedPointToDecimalString(4025149349925610116743993887520032712, 18, 18), "2581100000000000"
);
assertEq(Descriptor.fixedPointToDecimalString(3329657202331788924044422905302854, 18, 18), "1766200000");
assertEq(Descriptor.fixedPointToDecimalString(16241966553695418990605751641065, 18, 18), "42026");
assertEq(Descriptor.fixedPointToDecimalString(2754475062069337566441091812235, 18, 18), "1208.7");
assertEq(Descriptor.fixedPointToDecimalString(871041495427277622831427623669, 18, 18), "120.87");
assertEq(Descriptor.fixedPointToDecimalString(275447506206933756644109181223, 18, 18), "12.087");

assertEq(Descriptor.fixedPointToDecimalString(88028870788706913884596530851, 18, 18), "1.2345");
assertEq(Descriptor.fixedPointToDecimalString(79228162514264337593543950336, 18, 18), "1.0000");
assertEq(Descriptor.fixedPointToDecimalString(27837173154497669652482281089, 18, 18), "0.12345");
assertEq(Descriptor.fixedPointToDecimalString(1559426812423768092342, 18, 18), "0.00000000000000038741");
assertEq(Descriptor.fixedPointToDecimalString(74532606916587, 18, 18), "0.00000000000000000000000000000088498");
assertEq(
Descriptor.fixedPointToDecimalString(4947797163, 18, 18), "0.0000000000000000000000000000000000000029387"
);

assertEq(Descriptor.fixedPointToDecimalString(79228162514264337593543950336, 18, 16), "100.00");
assertEq(Descriptor.fixedPointToDecimalString(250541448375047931186413801569, 18, 17), "100.00");
assertEq(Descriptor.fixedPointToDecimalString(79228162514264337593543950336, 24, 5), "1.0000");

assertEq(Descriptor.fixedPointToDecimalString(79228162514264337593543950336, 10, 18), "0.000000010000");
assertEq(Descriptor.fixedPointToDecimalString(79228162514264337593543950336, 7, 18), "0.000000000010000");
}
}

0 comments on commit bd90cee

Please sign in to comment.