Decimal Scaling with Scientific Notation: How We Fixed Missing Wei Tokens in MATIC-Priced NFT Transactions (Solidity)
Md. Ariful Islam
Web3 Engineer | ?lockchain | ?? Merit Placeholder at INTERNATIONAL BLOCKCHAIN OLYMPIAD 2021 ???
Scenario:
We needed to develop an on-chain marketplace where physical assets were digitally identified with NFTs. The challenge was to handle consumer payment and revenue distribution among multiple stakeholders through our custom smart contract. Usually, these tasks are handled by external/ third-party payment gateway services. But in this case, we had to develop this solution on-chain to make this project Web 3.0 enabled.
As this was a Layer 2 Solution (Polygon PoS Network), MATIC was our native coin. But to ensure the project's price stability, we introduced Stable-Coin in our smart contract. As a result, the stakeholders could enlist the price in Stable-Coin. Since people could pay with different coins, we made sure to check if the paid amount matched the NFT's listed price in Stable-Coin.
For those who wanted to use MATIC instead of Stable-Coin, we integrated an Oracle Service to get the trustworthy conversion rate between Stable-Coin and MATIC. This helped ensure a smooth and reliable transaction process.
Problem Statement:
Our first hurdle involved the Oracle service. The provided Oracle addresses only covered specific currencies, and there was no conversion rate listed for Stable-Coin to MATIC. We did find an Oracle address for the MATIC to USD rate, which was useful, but since we needed to confirm the payable MATIC amount, the conversion had to be handled within the smart contract.
Here's where things got tricky.
Reviewing the Problem Statement, it becomes evident that the basic Unitary method cannot be executed on-chain to ensure precision. Employing the Scientific Notation technique emerges as a viable solution (IEEE 754). Bullet points 2, 3, and 4 introduce unique conversion factors (10?, 10?, 101?) for micro-units, reflecting distinct sources: 10? (Oracle), 10? (stable coin), and 101? (native cryptocurrency). This diversity in decimal places adds a critical dimension to our calculations.
Methodology:
As we were only provided the MATIC to USD rate's Oracle address we are considering this as a Stable-Coin rate (USDC/USDT etc.).
(We know: 1 USD = 1 Stable-Coin)
Let's assume the total NFT price is 143.75 USDC (Stable-Coin)
As this amount should get validated on-chain, we must convert this Stable-Coin to its micro units.
We know: Stable-Coin micro unit conversion = n × 10?
So, the total NFT price in micro-unit = 143.75 × 10? = 143750000 micro-unit USDC
Since, MATIC to USDC Oracle rate = 82110000 (0.82 USDC)
Where, the scientific notation = 10?
Here, we can notice the difference in power values (exponent) between Oracle and our on-chain Stable-Coin price. So we have to Scale this difference first before proceeding to the main calculation.
Decimal Scaling:
领英推荐
Formula = Oracle Rate Decimal Place ÷ Stable Coin Decimal Place
→ 10? ÷ 10? = 10^(8-6) = 102
So, the decimal scaling of Oracle rate = Oracle 8 Decimal Rate ÷102
→ 82110000 ÷ 102 = 821100 (Oracle rate in 10?)
(We know that MATIC prices are converted into 101? Wei for on-chain transactions)
So, NFT price in Wei = (Stable-Coin NFT Price × 101?) ÷ 6 Decimal Oracle Rate
→ (143750000 × 101?) ÷ 821100 = 1750700281120448000 Wei
This is how we can calculate the financial crypto calculation at the Smart Contract level in Solidity without losing any precision.
But on the User end, people are comfortable with the MATIC price. So when our Smart Contract provides the calculated crypto price in Wei the Front-end can just convert the Wei value into MATIC:
→ 1750700281120448000 ÷ 101? = 175.0700281120448 MATIC
Note: The micro-units for both MATIC and ETH are the same (101?). Therefore, this article is suitable for both Polygon and Ethereum developers, particularly those who code in Solidity.
Sample Solidity Code:
function calculatePriceInMATIC(
uint256 _cruiseId,
uint256[] memory _roomIds,
uint256 _startingDate,
uint256 _endingDate
) public view returns (uint256) {
// USDC RATE DECIMALS = 8 converted to 6 DECIMALS
uint256 rate = uint256(getOracleMaticPriceInUSDC()) / 10 ** 2;
// MATIC DECIMALS = 18
return
(sumPerNightPrice(_cruiseId, _roomIds) *
countTotalDays(_startingDate, _endingDate) *
10 ** 18) / rate;
}
Tips:
Developers frequently encounter challenges with integer length, especially in maintaining precision points in Web3 applications. To ensure financial accuracy, Big Integers are commonly used. However, issues arise when transporting this data between the back-end and front-end via the HTTP protocol, where financial data is exchanged as JSON in requests and responses. Some developers mistakenly parse Big Int data into regular integers (32), leading to a loss of precision. To avoid such cases, I recommend converting Big Integers into String types during transportation. Upon receiving the data, the front-end or back-end can easily parse it back into Big Integers for accurate processing.
Conclusion:
I've shared the techniques I follow, recognizing the challenges many professionals encounter in grasping these concepts. I prioritize providing a clear mathematical explanation to aid understanding of the actual processes. While numerous resources are available for implementation, there are relatively fewer focused on the mathematical perspective. To excel as an ideal token economist, these practices are crucial, representing my personal learning journey. However, I acknowledge there might be someone with a better, more optimized solution. Feel free to reach out with your updates—I'm eager to learn and collaborate.
Thanks, Roslin Mahmud Joy for your assistance, and Md Antonin Islam for capturing the moment at Brain Station 23 .
Blockchain Dev | Substrate | DeFi | Smart Contract Security | Decentralized Tech | Sustainability
1 年Outstanding. I appreciate this knowledge transfer. Looking forward to see more such tricky steps you encounter.
?? Full-Stack Engineer(MERN) | ?? Unlocking Tech Talent with FullStack Brilliance | Crafting Efficient Solutions for scalable Applications??
1 年Excellent article ??
Senior Software Engineer @BS23 | TypeScript | AWS | Python | NodeJS | MEAN | NestJS | GO
1 年wow! very excellent article documenting the challenges. Your analysis and solutions were so valuable for the team. Thanks for your initiative and effort! ??
Cloud & DevOps Architect | SRE & Platform Engineering | AWS, Kubernetes, Terraform, CI/CD, Observability | 8+ Years in Scalable Infrastructure & Reliability
1 年Good one. Learned things from your approach. Keep it up. :)