Skip to content

Commit 2c80fdd

Browse files
authored
Fix the issue of handling decimals. (#2886)
* add StringShift library * fix assembleAssertions * fix StringShift * rollback function type * fix comments * fix comment
1 parent b6611be commit 2c80fdd

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2020-2024 Trust Computing GmbH.
2+
// This file is part of Litentry.
3+
//
4+
// Litentry is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Litentry is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.
16+
17+
// SPDX-License-Identifier: GPL-3.0-or-later
18+
19+
pragma solidity ^0.8.0;
20+
import "../openzeppelin/Strings.sol";
21+
import "../openzeppelin/math/Math.sol";
22+
library StringShift {
23+
/**
24+
* @dev Converts a uint256 input to a string and shifts the decimal point to the left by the specified number of places.
25+
* @param value The uint256 parameter to be processed.
26+
* @param decimal The number of decimal places to shift.
27+
* @return The processed string.
28+
*/
29+
function toShiftedString(
30+
uint256 value,
31+
uint256 decimal
32+
) internal pure returns (string memory) {
33+
// Convert uint256 to string
34+
35+
if (value == 0) {
36+
return "0";
37+
} else {
38+
string memory str = Strings.toString(value);
39+
40+
// Calculate the position to insert the decimal point
41+
uint256 len = bytes(str).length;
42+
uint256 digit = Math.log10(decimal);
43+
44+
if (len <= digit) {
45+
// If the length is less than or equal to the number of digits, pad with leading zeros and add '0.'
46+
string memory leadingZeros = new string(digit - len);
47+
for (uint256 i = 0; i < digit - len; i++) {
48+
leadingZeros = string(abi.encodePacked("0", leadingZeros));
49+
}
50+
str = string(abi.encodePacked("0.", leadingZeros, str));
51+
} else {
52+
// Otherwise, insert the decimal point at the correct position
53+
str = string(
54+
abi.encodePacked(
55+
substring(str, 0, len - digit),
56+
".",
57+
substring(str, len - digit, len)
58+
)
59+
);
60+
}
61+
62+
// Remove trailing zeros after the decimal point
63+
str = removeTrailingZeros(str);
64+
65+
return str;
66+
}
67+
}
68+
69+
/**
70+
* @dev Extracts a substring from a given string.
71+
* @param str The original string.
72+
* @param start The starting position of the original string.
73+
* @param end The ending position of the original string.
74+
* @return The extracted substring.
75+
*/
76+
function substring(
77+
string memory str,
78+
uint256 start,
79+
uint256 end
80+
) internal pure returns (string memory) {
81+
bytes memory strBytes = bytes(str);
82+
bytes memory result = new bytes(end - start);
83+
for (uint256 i = start; i < end; i++) {
84+
result[i - start] = strBytes[i];
85+
}
86+
return string(result);
87+
}
88+
89+
/**
90+
* @dev Removes trailing zeros after the decimal point in a string.
91+
* @param str The input string.
92+
* @return The processed string with trailing zeros removed.
93+
*/
94+
function removeTrailingZeros(
95+
string memory str
96+
) internal pure returns (string memory) {
97+
bytes memory strBytes = bytes(str);
98+
uint256 len = strBytes.length;
99+
100+
// Traverse from the end to find the position of the first non-zero character
101+
uint256 newLen = len;
102+
while (newLen > 0 && strBytes[newLen - 1] == "0") {
103+
newLen--;
104+
}
105+
106+
// If the last character is a decimal point, remove it as well
107+
if (newLen > 0 && strBytes[newLen - 1] == ".") {
108+
newLen--;
109+
}
110+
111+
// Create a new byte array and copy the content
112+
bytes memory trimmedBytes = new bytes(newLen);
113+
for (uint256 i = 0; i < newLen; i++) {
114+
trimmedBytes[i] = strBytes[i];
115+
}
116+
117+
return string(trimmedBytes);
118+
}
119+
}

tee-worker/litentry/core/assertion-build/src/dynamic/contracts/token_holding_amount/TokenHoldingAmount.sol

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import "../libraries/AssertionLogic.sol";
2323
import "../libraries/Identities.sol";
2424
import "../DynamicAssertion.sol";
2525
import "./Constants.sol";
26+
import "../libraries/StringShift.sol";
2627

2728
abstract contract TokenHoldingAmount is DynamicAssertion {
2829
mapping(string => string) internal tokenNames;
@@ -157,15 +158,18 @@ abstract contract TokenHoldingAmount is DynamicAssertion {
157158
1,
158159
variable,
159160
AssertionLogic.Op.GreaterEq,
160-
Strings.toString(min / Constants.decimals_factor)
161+
StringShift.toShiftedString(min, Constants.decimals_factor)
161162
);
162163
if (max > 0) {
163164
AssertionLogic.andOp(
164165
cc,
165166
2,
166167
variable,
167168
AssertionLogic.Op.LessThan,
168-
Strings.toString(uint256(max) / Constants.decimals_factor)
169+
StringShift.toShiftedString(
170+
uint256(max),
171+
Constants.decimals_factor
172+
)
169173
);
170174
}
171175

0 commit comments

Comments
 (0)