Xarva
Smart Contract Audit Report

Executive Summary
This report presents the outcomes of our collaborative engagement with the Xarva team, focusing on the comprehensive evaluation of the Xarva, rXRV, IUSDT, PaymentSettler, and BillSubscriptionManager contracts.
Our team conducted an initial security assessment from November 18th to November 25th, 2024 using code from the project team's GitHub repository. This report was updated on December 3rd, 2024 to reflect changes from commit bb1fe8 to commit c310740.
Xarva is a new platform which facilitates billing and payment between users who are subscribed.
Audit Scope
Name |
Source Code (GitHub) |
Visualized |
Xarva |
|
|
rXRV |
|
|
IUSDT |
|
|
PaymentSettler |
|
|
BillSubscriptionManager |
|
Name/Source Code |
Visualized |
Xarva
|
|
rXRV
|
|
IUSDT
|
|
PaymentSettler
|
|
BillSubscriptionManager
|
Audit Findings
All findings have been resolved or acknowledged, though some centralized aspects are present.
Finding #1 |
PaymentSettler |
High Resolved |
|
Finding #1 - PaymentSettler
|
||
|
Description: The settleBill() function multiplies the bill amount by 1e18 to convert to IUSDT; however, IUSDT only has 6 decimals and can be swapped 1:1 for the contract's USDT. Risk/Impact: The IUSDT amount paid to merchants will be 1e12 times larger than intended. Recommendation: The bill amount should only be multiplied by 1e6, assuming the original bill amount does not include decimals. The project team should also ensure that the XRVUSDSettlementRate variable properly accounts for the extra 12 decimals added to the bill amount when converting to XRV. Resolution: The 1e18 multiplier has been removed. As a result, the bill amount should account for the IUSDT token's 6 decimals. |
||
Finding #2 |
PaymentSettler |
High Acknowledged |
|
Finding #2 - PaymentSettler
|
||
|
Description: The following lines transfer the protocol fee to both the bill settler and merchant, however the protocol fees from the bill payment were already transferred to the BillSubscriptionManager contract's payment address.
Risk/Impact: Settlements will fail unless additional XRV is provided to the contract by the owner. Recommendation: These lines should be removed. Update: The team intends to fund the PaymentSettler contract with additional XRV to facilitate this protocol reimbursement. |
||
Finding #3 |
PaymentSettler |
High Acknowledged |
|
Finding #3 - PaymentSettler
|
||
|
Description: XRV price cannot be updated until the existing price has expired. If an inaccurate XRV price exists in the contract, the owner cannot update it until the existing price has expired. Additionally, settlements will not be able to be made in the time between price expiration and a price update. Risk/Impact: Users will be able to take advantage of XRV prices by receiving XRV value in IUSDT for more IUSDT than it is worth, then swapping this IUSDT for USDT at a 1:1 ratio. Recommendation: The project team should allow the price to be updated by the owner at any time, or should consider using a price oracle to fetch the current XRV price. Update: The team has stated that they only intend to include this token on a centralized exchange where the price is controlled. Additionally, the team intends to only update the XRV price before a settlement is made. |
||
Finding #4 |
BillSubscriptionManager |
High Resolved |
|
Finding #4 - BillSubscriptionManager
|
||
|
Description: The BillSubscriptionManager.createBill() and PaymentSettler.settleBill() functions appear to only intend merchants to bill recipients who have a lower subscription tier than them; however, the opposite logic exists.
Risk/Impact: Only merchants with a lower subscription tier than their recipient can create or settle bills. Recommendation: The project team should update this conditional statement to something similar to the following:
Resolution: A merchant's subscription tier now must be equal to the recipient's subscription tier in order for a bill to be created or settled. |
||
Finding #5 |
PaymentSettler |
High Resolved |
|
Finding #5 - PaymentSettler
|
||
|
Description: In the settleBill() function, the contract attempts to compare the merchant and recipient's subscription tiers, but instead compares the merchant to themselves.
Risk/Impact: The logic intending to require a merchant's subscription tier to be at least as high as a recipient's subscription tier will not be enforced. Recommendation: The bill.to address' subscription tier should be fetched and compared to the bill.merchant's. Resolution: The team has implemented the above recommendation. |
||
Finding #6 |
BillSubscriptionManager |
Low Resolved |
|
Finding #6 - BillSubscriptionManager
|
||
|
Description: When calculating payment for a tier upgrade, the number of days to charge for is rounded down.
Risk/Impact: Users can receive upgraded subscriptions at a smaller price than intended. For example, if one day and 23 hours remain on a user's subscription before upgrading, they will only be required to pay for 1 day. Recommendation: The project team may want to consider rounding up by updating the last line of the code above to ensure users do not take advantage of the rounded down discounts.
Resolution: Upgrade price calculations now use hourly precision. |
||
Finding #7 |
BillSubscriptionManager |
Low Resolved |
|
Finding #7 - BillSubscriptionManager
|
||
|
Description: A merchant and recipient's bill lists are each looped through in order to delete a bill. As a result, gas costs to delete a bill will grow increasingly large as a user's bill list increases in size. Risk/Impact: Bill deletions may become expensive or fail if a user's bill list grows too large, either over time or by a malicious merchant flooding users with small bills. Recommendation: While this does not affect other platform functionality, the team may want to consider tracking the IDs of each bill in a user's list for more efficient deletion. Resolution: Bills are no longer removed from the merchant or recipient's list of bills when deleted. |
||
System Overview
Tokens
XRVThe Xarva contract introduces Xarva (XRV) as a token used for bill payments within the platform. Upon deployment, the owner is minted the initial supply of XRV tokens. The owner retains the ability to mint additional XRV tokens to themselves at any time and can also burn their tokens if desired. Ownership of the contract can be transferred at any time.
rXRVrXRV, or RewardXRV, is a new token used as a reward mechanism within the PaymentSettler contract. The Settler Role, initially assigned to the PaymentSettler contract upon deployment, can mint or burn rXRV tokens from any address. The Default Admin role, which is granted to the owner upon deployment, holds authority over role management. The Default Admin can grant or revoke the Settler Role for any address. Additionally, the owner can update the PaymentSettler address, assigning the Settler Role to the new address while revoking it from the previous one.
IUSDTThe IUSDT contract introduces Internal USDT, a token utilized for bill payouts within the platform. Similar to rXRV, the Settler Role, assigned to the PaymentSettler contract upon deployment, has the ability to mint or burn IUSDT tokens from any address. The Default Admin role, assigned to the owner upon deployment, oversees role management and can grant or revoke the Settler Role for any address. The owner also has the authority to update the PaymentSettler address, transferring the Settler Role to a new address and revoking it from the old one.
Subscriptions and Payments
PaymentSettlerThis PaymentSettler contract allows users to settle bills if the bill's payment token is set to either "IUSDT" or XRV. Both the settler and the merchant must have valid subscriptions for a bill to be settled. Additionally, the bill amount must not exceed the maximum single bill settlement limit defined by the merchant's subscription tier, and the merchant's total payments received in a day must remain within their tier's daily settlement threshold. The bill amount is converted into XRV using the contract's current XRV price. The project team must ensure that the XRV price is constantly updated to avoid arbitrage using bill payments, as users can receive stablecoins based on the current XRV price.
When settling a bill, a protocol fee is applied to the bill amount. This fee is added to the amount transferred from the settler and also deducted from the payment received by the merchant. The collected XRV fee is sent to the BillSubscriptionManager's payment address. The total XRV amount, including the fee, is transferred from the user regardless of the original payment type. The merchant receives the bill amount minus the fee, either minted as IUSDT tokens or transferred in XRV. If the merchant receives IUSDT, the equivalent value in XRV is sent to the BillSubscriptionManager's payment address. At the end of the settlement, the protocol fee amount taken is returned back to the bill's merchant and recipient. As protocol fee was already transferred to the BillSubscriptionManager's payment address, the team must ensure that the contract is funded by sufficient XRV to facilitate this payment.
Once settled, the bill is marked as paid in the BillSubscriptionManager contract. Both the settler and the merchant are rewarded with rXRV tokens based on the settler reward and bill raiser reward percentages, respectively. These rewards become claimable after the settler and raiser vesting periods have elapsed. Users can swap their rXRV or IUSDT tokens for the stable token used by the BillSubscriptionManager, typically USDT, at a 1:1 ratio while the contract is active. During a swap, the user's rXRV or IUSDT is burned, and the equivalent amount in USDT is transferred to them, provided the contract holds a sufficient stable token balance.
The XRV price can be updated by the Price Updater address and remains valid for the defined price validity period. Bills can only be settled when there is an unexpired XRV price. The contract owner has extensive administrative control, including updating the XRV, rXRV, IUSDT, BillSubscriptionManager, and Price Updater addresses. The owner can also adjust the protocol fee percentage, settler and raiser reward percentages, vesting periods, and price validity period. Additionally, the owner can pause the contract, disabling bill settlements, reward claims, and token swaps. At any time, the owner can withdraw any XRV held by the contract.
BillSubscriptionManagerThis contract enables users to manage their subscriptions on the platform. Users can purchase a subscription for a specified tier for any number of months, paying in the contract's designated stable token. The subscription cost is determined by the tier's price and the duration purchased. Price changes may apply for multi-month purchases based on the tier's discount percentage. Alternatively, users can claim a one-time subscription to the free trial tier, which is valid for the designated free trial period. Users may also upgrade an existing subscription by paying the price difference between their current tier and the desired one for the remaining duration of the subscription.
The contract allows users to create bills specifying a recipient, amount, and payment token type, provided that both the merchant and recipient hold valid subscriptions. Additional conditions include the recipient having a subscription tier equal to or lower than the merchant, the bill amount being below the tier's maximum single bill limit, and the merchant’s total daily bills not exceeding the tier’s daily permitted amount. Created bills can be settled by the recipient through the PaymentSettler contract, while bill creators can delete unsettled bills if desired.
The contract owner holds various administrative privileges. They can update subscription tiers, including the daily limit, monthly price, multi-month discount, and maximum single bill amount. The free trial period can also be adjusted to a maximum of 30 days. Additionally, the owner can modify the addresses of the payment processor and stable token. The project team must ensure that only stable tokens with 6 decimals are used if they desire to keep a 1:1 ratio between rXRV, IUSDT, and the stable token. The contract can be paused by the owner, which disables user and admin subscription purchases and upgrades, bill creation and deletion, and bill settlements. The owner also has the authority to grant a subscription of any length to a user for any tier at no cost, provided the user does not already have an active subscription, or can upgrade a user's subscription at no cost.
Vulnerability Analysis
| Vulnerability Category | Notes | Result |
|---|---|---|
| Arbitrary Jump/Storage Write | N/A | PASS |
| Centralization of Control |
| WARNING |
| Compiler Issues | N/A | PASS |
| Delegate Call to Untrusted Contract | N/A | PASS |
| Dependence on Predictable Variables | N/A | PASS |
| Ether/Token Theft | N/A | PASS |
| Flash Loans | N/A | PASS |
| Front Running | N/A | PASS |
| Improper Events | N/A | PASS |
| Improper Authorization Scheme | N/A | PASS |
| Integer Over/Underflow | N/A | PASS |
| Logical Issues | N/A | PASS |
| Oracle Issues | N/A | PASS |
| Outdated Compiler Version | N/A | PASS |
| Race Conditions | N/A | PASS |
| Reentrancy | N/A | PASS |
| Signature Issues | N/A | PASS |
| Sybil Attack | N/A | PASS |
| Unbounded Loops | N/A | PASS |
| Unused Code | N/A | PASS |
| Overall Contract Safety | PASS |
About SourceHat
SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1800+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value!
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!
Contact us today to get a free quote for a smart contract audit of your project!
What is a SourceHat Audit?
Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.
How Do I Interpret the Findings?
Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:
- High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
- Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
- Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
- Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.