Quantum Audit Logo

Is RAIN Safe?

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

RAIN RAIN
0x2511…099d
Arbitrum Not verifiedLast checked 3d ago 2 audits on record
How is this score calculated? → Medium Risk
Executive SummaryAI Copilot

The audit of the Rain Token (implementation `Rain`) reveals significant architectural and design concerns. A critical initialization flaw means the contract's core functionalities (ERC20, ownership) are not explicitly initialized within the provided source code, relying on opaque external calls. Furthermore, the contract includes extensive unused variables and errors suggesting a USD-pegged inflation mechanism, which is entirely absent from the actual `dailyMinting` logic, leading to a misleading economic model. Other findings include hardcoded initial values, an unused initial supply constant, and explicitly disabled UUPS upgrades.

2 Critical1 Medium2 Low2 Informational
Volume 24h
$1.13M
Liquidity
$1.66M
Price
$0.01709
Token Age
1mo
Top 10 Holders
86.2%

Security Findings

Critical

Architectural Flaw: Missing Chained Initialization Function

C-01The `Rain` contract, despite inheriting from multiple OpenZeppelin upgradeable contracts (ERC20Upgradeable, Ownable2StepUpgradeable, etc.), lacks a primary `initialize()` function that explicitly calls the `__<ContractName>_init()` functions of its base contracts. While external deployment scripts might have called these `_init` functions directly on the proxy, the absence of this chained initialization in the contract's source code is an architectural flaw. It makes the contract's initialization process opaque, harder to audit, and prone to errors if not handled perfectly by external tooling. The `initialize2()` function, marked as a `reinitializer(2)`, further complicates this, as it impl…
IssueThe `Rain` contract, despite inheriting from multiple OpenZeppelin upgradeable contracts (ERC20Upgradeable, Ownable2StepUpgradeable, etc.), lacks a primary `initialize()` function that explicitly calls the `__<ContractName>_init()` functions of its base contracts. While external deployment scripts might have called these `_init` functions directly on the proxy, the absence of this chained initialization in the contract's source code is an architectural flaw. It makes the contract's initialization process opaque, harder to audit, and prone to errors if not handled perfectly by external tooling. The `initialize2()` function, marked as a `reinitializer(2)`, further complicates this, as it impl…
FixImplement a comprehensive `initialize()` function in the `Rain` contract that explicitly calls all necessary `__<ContractName>_init()` functions from its inherited OpenZeppelin base contracts. Ensure proper chaining and versioning of initializers, and consider moving `initialize2`'s logic into the primary `initialize` if it's intended for initial setup.
StatusUnresolved
Critical

Misleading/Unused Inflation Mechanism

C-02The contract defines several state variables (`DAILY_INFLATION_USD`, `oraclePriceFeed`, `deploymentTimestamp`, `LOCKUP_PERIOD`) and custom errors (`MintingNotAllowedYet`, `InvalidPrice`, `OraclePriceFeedNotSet`) that strongly suggest a USD-pegged, time-locked inflation mechanism. However, the `dailyMinting` function, which is the sole minting mechanism, does not utilize any of this logic. Instead, it mints a fixed percentage (10%) of `dailyBurned` tokens. This significant discrepancy between declared intent/variables and actual implementation is highly misleading, indicates incomplete development or a major design change, and could lead to incorrect assumptions about the token's economic mo…
IssueThe contract defines several state variables (`DAILY_INFLATION_USD`, `oraclePriceFeed`, `deploymentTimestamp`, `LOCKUP_PERIOD`) and custom errors (`MintingNotAllowedYet`, `InvalidPrice`, `OraclePriceFeedNotSet`) that strongly suggest a USD-pegged, time-locked inflation mechanism. However, the `dailyMinting` function, which is the sole minting mechanism, does not utilize any of this logic. Instead, it mints a fixed percentage (10%) of `dailyBurned` tokens. This significant discrepancy between declared intent/variables and actual implementation is highly misleading, indicates incomplete development or a major design change, and could lead to incorrect assumptions about the token's economic mo…
FixEither fully implement the USD-pegged inflation mechanism using the declared variables and oracle, or remove all unused variables, errors, and comments related to it. Ensure the contract's code accurately reflects its intended economic model to avoid confusion and potential misinterpretations by users or integrators.
StatusUnresolved
Medium

Hardcoded Initial Burned Values in `initialize2`

M-01The `initialize2` function directly assigns large, specific values to `lifetimeBurned` and `dailyBurned`. While this might be intended for a specific initial state or migration, hardcoding such values in an initialization function reduces flexibility and makes the contract brittle. If the contract were to be redeployed or initialized under different circumstances, these hardcoded values might be inappropriate, leading to unexpected or incorrect minting behavior. (7.2 Code Security, 7.4 Economic, 7.8 Operations)
IssueThe `initialize2` function directly assigns large, specific values to `lifetimeBurned` and `dailyBurned`. While this might be intended for a specific initial state or migration, hardcoding such values in an initialization function reduces flexibility and makes the contract brittle. If the contract were to be redeployed or initialized under different circumstances, these hardcoded values might be inappropriate, leading to unexpected or incorrect minting behavior. (7.2 Code Security, 7.4 Economic, 7.8 Operations)
FixConsider making the initial values for `lifetimeBurned` and `dailyBurned` configurable parameters during initialization, or derive them dynamically based on the contract's actual state or a trusted external source. This improves flexibility and reduces the risk of incorrect initial states.
StatusUnresolved
Low

Unused `INITIAL_SUPPLY` Constant

L-01The contract defines `INITIAL_SUPPLY` as a public constant with a value of `1_150_000_000_000 * WEI`. However, there is no corresponding `_mint` call in any initialization function to actually create and distribute this initial supply. Without an explicit minting operation, the token will have a total supply of zero upon deployment (assuming the critical initialization flaw is fixed), rendering the `INITIAL_SUPPLY` constant effectively unused and misleading. (7.1 Architecture, 7.4 Economic)
IssueThe contract defines `INITIAL_SUPPLY` as a public constant with a value of `1_150_000_000_000 * WEI`. However, there is no corresponding `_mint` call in any initialization function to actually create and distribute this initial supply. Without an explicit minting operation, the token will have a total supply of zero upon deployment (assuming the critical initialization flaw is fixed), rendering the `INITIAL_SUPPLY` constant effectively unused and misleading. (7.1 Architecture, 7.4 Economic)
FixIf an initial supply is intended, ensure that the `initialize()` function (or an appropriate setup function) includes a call to `_mint(recipient, INITIAL_SUPPLY)` to create and distribute the tokens. Otherwise, remove the `INITIAL_SUPPLY` constant if it is not meant to be used.
StatusUnresolved
Low

UUPS Upgrades Explicitly Disabled

L-02The `_authorizeUpgrade` function, which is part of the UUPSUpgradeable pattern, is explicitly overridden to `revert("UUPS upgrades disabled")`. While this clearly signals immutability and prevents unauthorized upgrades, it contradicts the use of the UUPSUpgradeable base contract, which is designed for upgradeability. If future protocol changes require contract logic updates, a full redeployment of the token would be necessary, incurring significant operational overhead and potentially disrupting integrations. (7.7 Upgrades, 7.8 Operations)
IssueThe `_authorizeUpgrade` function, which is part of the UUPSUpgradeable pattern, is explicitly overridden to `revert("UUPS upgrades disabled")`. While this clearly signals immutability and prevents unauthorized upgrades, it contradicts the use of the UUPSUpgradeable base contract, which is designed for upgradeability. If future protocol changes require contract logic updates, a full redeployment of the token would be necessary, incurring significant operational overhead and potentially disrupting integrations. (7.7 Upgrades, 7.8 Operations)
FixConfirm that the decision to disable upgrades is intentional and understood by all stakeholders. If future upgradeability is a possibility, reconsider this override. If immutability is the goal, ensure this is clearly documented and communicated to users and integrators.
StatusUnresolved
Info

Unused `PriceFeed` Interface and Related Logic

I-01The `PriceFeed` interface is imported, and an `oraclePriceFeed` state variable is declared, along with a `PriceFeedSet` event. However, the `oraclePriceFeed` variable is never set (no `setPriceFeed` function) and its `getPrice()` method is never called within the contract's logic. This indicates dead code or an incomplete feature related to an external price oracle. (7.1 Architecture, 7.2 Code Security)
IssueThe `PriceFeed` interface is imported, and an `oraclePriceFeed` state variable is declared, along with a `PriceFeedSet` event. However, the `oraclePriceFeed` variable is never set (no `setPriceFeed` function) and its `getPrice()` method is never called within the contract's logic. This indicates dead code or an incomplete feature related to an external price oracle. (7.1 Architecture, 7.2 Code Security)
FixRemove the unused `PriceFeed` interface, `oraclePriceFeed` variable, and related event/errors if the feature is not intended for implementation. If it is a planned feature, ensure it is fully implemented, including a function to set the oracle address and integrate its price data into relevant logic.
StatusUnresolved
Info

`constructor` calls `_disableInitializers()` but `initialize2` is `reinitializer(2)`

I-02The constructor correctly calls `_disableInitializers()` for upgradeable contracts. However, the `initialize2` function is marked as `reinitializer(2)`. This implies that an `initialize` function (version 1) should have been called first. Given the critical initialization flaw (C-01) where the primary `initialize` is missing, the versioning for `initialize2` is either incorrectly applied or part of the larger initialization issue. (7.1 Architecture, 7.2 Code Security)
IssueThe constructor correctly calls `_disableInitializers()` for upgradeable contracts. However, the `initialize2` function is marked as `reinitializer(2)`. This implies that an `initialize` function (version 1) should have been called first. Given the critical initialization flaw (C-01) where the primary `initialize` is missing, the versioning for `initialize2` is either incorrectly applied or part of the larger initialization issue. (7.1 Architecture, 7.2 Code Security)
FixEnsure that the initialization versioning is correctly implemented. If `initialize2` is intended as the first or only initialization, adjust its modifier accordingly (e.g., `initializer`). If it is truly a reinitializer, ensure that `initialize` (version 1) is properly defined and called first.
StatusUnresolved

Category Ratings

TechnicalMedium5/10

The technical architecture leverages OpenZeppelin's upgradeable contracts, including ERC20, Ownable2Step, and UUPS. However, a critical architectural flaw exists where the contract lacks a primary `initialize()` function to properly chain the initialization of these base contracts (7.1 Architecture, 7.2 Code Security). This makes the contract's operational state dependent on external, non-auditable setup. The `dailyMinting` function is properly access-controlled by `onlyOwner` and includes a `MINT_COOLDOWN_PERIOD` (7.3 Access Control). UUPS upgrades are explicitly disabled, providing immutability but limiting future flexibility (7.7 Upgrades).

GovernanceHigh2/10

The economic model for token minting is based on a percentage of burned tokens, controlled by the owner (7.4 Economic). However, the contract contains extensive declarations for a USD-pegged inflation mechanism with an oracle and lockup periods, which are entirely unused in the `dailyMinting` logic. This discrepancy is highly misleading and creates ambiguity regarding the token's intended economic behavior (7.4 Economic). Initial burned values are hardcoded in `initialize2`, which could lead to unexpected behavior if not carefully managed (7.8 Operations). The owner is a 2/4 multisig, providing a degree of decentralized control over critical functions like `dailyMinting` and `updateTreasury` (7.5 Governance).

UpgradesHigh1/10

The contract utilizes the UUPSUpgradeable pattern but explicitly disables upgrades by reverting in `_authorizeUpgrade` (7.7 Upgrades). This design choice ensures immutability of the contract logic, preventing any future on-chain upgrades. While this provides a clear and immutable state, it means any future protocol changes requiring contract modifications would necessitate a full redeployment, incurring significant operational overhead and potential disruption to integrations (7.8 Operations). The `initialize2` function is a `reinitializer(2)`, implying a versioning strategy that is not fully supported by the contract's missing primary `initialize` function.

Security Checklist

Contract VerifiedPass
Ownership RenouncedFail
No Mint FunctionPass
Liquidity LockedFail
Not a ProxyFail

Proxy Upgrade Controls

Proxy TypeEip1967 Uups
ImplementationVerified source
Upgrades (30d)0 · stable

Holder Composition

2.7% in wallets83.6% in contracts
Effective Concentration36.1%

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

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
0xbd80…c331
Unlocked LP Held By
0x7706…53aa0x0963…3df6

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

What Raised This Score

  • Ownership NOT renounced — Multisig (2-of-4)
  • Proxy contract (upgradeable — admin can replace logic)
  • Top-10 concentration > 30% (86.2% total → 36.1% effective; 2.7% in EOAs, 83.6% in contracts — moderate)
  • 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 = 59% of DEX liquidity)
  • LP top3 unlocked holders = 100.0% (independent LP — depth risk, pool = 59% of DEX liquidity)
  • 2 Critical finding(s) from audit
  • 1 Medium finding(s) from audit
  • 2 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

Frequently Asked Questions

Is RAIN a scam?

Based on automated analysis, RAIN scores 66/100 (High Risk) on our risk scale. No honeypot was detected, but always verify independently before investing.

Is RAIN safe to buy?

Our scanner flagged a risk score of 66/100. Ownership has not been renounced, which is a risk factor. DYOR before purchasing any token.

Has RAIN been audited?

The contract has not been verified on-chain. Verification is not the same as a full security audit. Use Quantum Audit's free tool to run a deeper analysis of the contract code.

Related Audits

Wrapped liquid staked Ether 2.0 (WSTETH)Medium RiskAave Token (AAVE)Medium RiskBoopMedium RiskChainLink Token (LINK)Medium RiskAutonomi (ANT)High RiskSubsquid (SQD)High Risk

Would You Like a More Detailed Audit of RAIN?

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

Get Detailed Audit