Quantum Audit Logo

Is Rally Safe?

On-chain security analysis — is it a scam or legit?

Is this your token? Publish your own audit on this page →

Rally RALLY
0x1964…d08c
Ethereum Not verifiedLast checked 3d ago 1 audit on record
How is this score calculated? → Critical Risk
Executive SummaryAI Copilot

The audit of the Token contract identified several areas for improvement, primarily concerning ERC-20 standard compliance and centralization risks. A critical issue is the missing implementation of the `totalSupply()` function, which is essential for ERC-20 compatibility. High centralization of control through the owner and issuer roles presents significant economic risk. Additionally, certain administrative functions carry risks of accidental role locking or irreversible actions. The contract demonstrates good practices in preventing common integer overflows/underflows and includes necessary address checks.

1 Critical1 High2 Medium1 Low1 Informational
Volume 24h
$175.9K
Liquidity
$5.47M
Price
$0.03517
Token Age
5mo
Top 10 Holders
31.9%

Security Findings

Critical

Missing `totalSupply()` Function Implementation

C-01The contract declares `IERC20` but does not implement the `totalSupply()` function as required by the ERC-20 standard. While a public `totalSupply` state variable exists, many dApps and tools rely on the explicit function call for compatibility. This omission can lead to integration issues and unexpected behavior with external systems expecting a standard ERC-20 token.
IssueThe contract declares `IERC20` but does not implement the `totalSupply()` function as required by the ERC-20 standard. While a public `totalSupply` state variable exists, many dApps and tools rely on the explicit function call for compatibility. This omission can lead to integration issues and unexpected behavior with external systems expecting a standard ERC-20 token.
FixImplement the `totalSupply()` function to return the value of the `totalSupply` state variable, ensuring full ERC-20 compliance. Example: `function totalSupply() external view override returns (uint) { return totalSupply; }`
StatusUnresolved
High

High Centralization Risk

H-01The `owner` and `issuer` roles possess significant power. The `owner` can change the `issuer`, and the `issuer` has the ability to `mint` new tokens up to the `maxSupply`. This centralized control means that a compromise of the `owner` or `issuer`'s private key could lead to unauthorized token minting, market manipulation, or a complete loss of trust in the token's supply integrity.
IssueThe `owner` and `issuer` roles possess significant power. The `owner` can change the `issuer`, and the `issuer` has the ability to `mint` new tokens up to the `maxSupply`. This centralized control means that a compromise of the `owner` or `issuer`'s private key could lead to unauthorized token minting, market manipulation, or a complete loss of trust in the token's supply integrity.
FixConsider implementing a multi-signature wallet for the `owner` and `issuer` roles to distribute control and reduce the risk associated with a single point of failure. Explore time-locks or governance mechanisms for critical actions like changing the issuer or minting large amounts of tokens.
StatusUnresolved
Medium

Ownership Transfer to `address(0)` Possible

M-01The `transferOwnership` function allows the current `owner` to set `pendingOwner` to `address(0)`. If this occurs, the `confirmOwnership` function, which requires `msg.sender == pendingOwner`, can never be called, effectively locking the ownership transfer mechanism. The current `owner` would remain the owner indefinitely, unable to transfer ownership to a new, valid address.
IssueThe `transferOwnership` function allows the current `owner` to set `pendingOwner` to `address(0)`. If this occurs, the `confirmOwnership` function, which requires `msg.sender == pendingOwner`, can never be called, effectively locking the ownership transfer mechanism. The current `owner` would remain the owner indefinitely, unable to transfer ownership to a new, valid address.
FixAdd a `require` statement in `transferOwnership` to prevent setting `newOwner` to `address(0)`. For example: `require(newOwner != address(0), 'New owner cannot be the zero address');`
StatusUnresolved
Medium

`setIssuer` to `address(0)` Disables Minting

M-02The `setIssuer` function allows the `owner` to set the `issuer` address to `address(0)`. If `issuer` is set to `address(0)`, the `mint` function becomes permanently unusable because the `only(issuer)` modifier will always fail. While the `owner` can later set a new valid issuer, this action could temporarily halt token issuance and might be an unintended consequence if not carefully managed.
IssueThe `setIssuer` function allows the `owner` to set the `issuer` address to `address(0)`. If `issuer` is set to `address(0)`, the `mint` function becomes permanently unusable because the `only(issuer)` modifier will always fail. While the `owner` can later set a new valid issuer, this action could temporarily halt token issuance and might be an unintended consequence if not carefully managed.
FixConsider adding a `require` statement in `setIssuer` to prevent setting `newIssuer` to `address(0)` unless this is an explicit, intended mechanism to permanently disable minting. If temporary disablement is desired, implement a separate pause/unpause mechanism for minting.
StatusUnresolved
Low

Standard ERC-20 `approve` Front-Running Vulnerability

L-01The `approve` function, as implemented, is susceptible to a known ERC-20 front-running vulnerability. If a user approves an amount for a spender and then attempts to change that approved amount to a different value (especially a lower one), an attacker can front-run the second transaction. The attacker could spend the original approved amount before the new allowance is set, potentially leading to a double-spend of the allowance.
IssueThe `approve` function, as implemented, is susceptible to a known ERC-20 front-running vulnerability. If a user approves an amount for a spender and then attempts to change that approved amount to a different value (especially a lower one), an attacker can front-run the second transaction. The attacker could spend the original approved amount before the new allowance is set, potentially leading to a double-spend of the allowance.
FixWhile this is a common ERC-20 limitation, consider using `increaseAllowance` and `decreaseAllowance` functions (as seen in OpenZeppelin's ERC-20 implementation) instead of directly setting the allowance. This pattern mitigates the front-running risk by requiring explicit increments or decrements.
StatusUnresolved
Info

Use of `unchecked` Blocks

I-01The contract utilizes `unchecked` blocks for arithmetic operations in functions like `mint`, `transferFrom`, and `updateBalance`. These blocks are correctly preceded by `require` statements (e.g., `require(totalSupply + value <= maxSupply)` or `require(balanceOf[from] >= value)`) that ensure the operations will not overflow or underflow. This is a valid optimization in Solidity 0.8.x to save gas by explicitly opting out of default overflow/underflow checks.
IssueThe contract utilizes `unchecked` blocks for arithmetic operations in functions like `mint`, `transferFrom`, and `updateBalance`. These blocks are correctly preceded by `require` statements (e.g., `require(totalSupply + value <= maxSupply)` or `require(balanceOf[from] >= value)`) that ensure the operations will not overflow or underflow. This is a valid optimization in Solidity 0.8.x to save gas by explicitly opting out of default overflow/underflow checks.
FixNo direct action is required as the `unchecked` blocks are used safely. However, it is crucial to maintain rigorous testing and review of any changes to these functions to ensure that the preceding `require` statements always provide adequate protection against arithmetic overflows/underflows.
StatusUnresolved

Category Ratings

TechnicalMedium5/10

The contract exhibits a generally sound technical foundation, utilizing `unchecked` blocks correctly with preceding `require` statements to prevent integer overflows (7.2 Code Security). Necessary `address(0)` checks are implemented in critical functions like `mint` and `updateBalance`. However, a critical technical flaw is the absence of the `totalSupply()` function, which is a mandatory part of the ERC-20 standard, hindering compatibility with external systems (7.1 Architecture). The standard ERC-20 `approve` function is also susceptible to front-running, a common but notable issue (7.2 Code Security).

GovernanceHigh1/10

The contract design incorporates a highly centralized governance model, where an `owner` can control the `issuer` role, and the `issuer` can mint tokens up to `maxSupply` (7.5 Governance, 7.4 Economic). This centralization introduces a significant single point of failure; compromise of the owner or issuer key could lead to severe economic consequences, including arbitrary token minting. Furthermore, the `transferOwnership` function allows setting `pendingOwner` to `address(0)`, which could permanently lock the ownership transfer mechanism if accidentally invoked (7.3 Access Control). The `setIssuer` function also allows setting the issuer to `address(0)`, effectively disabling minting until the owner re-establishes a valid issuer (7.3 Access Control).

UpgradesHigh2/10

This contract is not designed to be upgradeable, as it does not implement any proxy pattern (7.7 Upgrades). Therefore, there are no upgrade-related risks to assess. Any changes to the contract's logic would require a new deployment and migration of assets, if applicable.

Security Checklist

Contract VerifiedPass
Ownership Renounced?
No Mint FunctionFail
Liquidity LockedFail
Not a ProxyPass

Holder Composition

27.5% in wallets4.3% in contracts
Effective Concentration29.3%

Share held by contracts — treasury, vesting, bridge or staking — is discounted against share held by wallets when the score is computed: a contract cannot decide to sell the way an anonymous holder can, though it can still be drained or voted to sell. Effective concentration is the figure the risk score is actually calculated from.

Liquidity Depth

Show 4 more pairsShow less

The 4 remaining pairs hold $6.9K between them and are not listed.

The risk score reads depth across every pair. The volume figure and the volume-to-liquidity ratio elsewhere on this page describe only the pair this audit analysed, so the two are not directly comparable.

LP Distribution

Top-1 Unlocked Holder100.0%
Top-3 Unlocked100.0%

Key Addresses

Deployer
0xa6b1…495b
Unlocked LP Held By
0x9210…7e7e

No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.

What Raised This Score

  • Ownership status UNKNOWN (owner could not be resolved)
  • Mintable supply — no cap found, dilution unbounded
  • Top-10 concentration > 20% (31.9% total → 29.3% effective; 27.5% in EOAs, 4.3% in contracts — mild)
  • Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
  • LP top1 unlocked holder = 100.0% (independent LP — depth risk, pool = 92% of DEX liquidity)
  • LP top3 unlocked holders = 100.0% (independent LP — depth risk, pool = 92% of DEX liquidity)
  • 1 Critical finding(s) from audit
  • 1 High finding(s) from audit
  • 2 Medium finding(s) from audit
  • 1 Low finding(s) from audit

Each factor is an on-chain fact recorded at the time of this analysis. The score is computed from them by a deterministic function, so the same contract returns the same score for anyone who runs the audit. How scores are computed

Related Audits

Global Dollar (USDG)Critical RiskBigShortBets (BIGSB)Critical RiskFrankencoin (ZCHF)Critical RiskRe Protocol reUSD (REUSD)Critical RiskTurtleCritical RiskSyrup Token (SYRUP)Critical Risk

Would You Like a More Detailed Audit of Rally?

Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.

Get Detailed Audit