Q2 2026 Security & Compliance Report67 incidents, $764M in losses, 88% from operational failures.
Get the report →

Audit name:

[SCA] Rain | Prediction Markets | May2026

Date:

Jun 5, 2026

Table of Content

Introduction
Audit Summary
System Overview
Potential Risks
Findings
Appendix 1. Definitions
Appendix 2. Scope
Appendix 3. Additional Valuables
Disclaimer

Want a comprehensive audit report like this?

Introduction

We express our gratitude to the RAIN team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.

RAIN V2 is a decentralized prediction-market protocol deployed on Arbitrum One, enabling users to create binary-option markets (each subdivided into multiple independent options) and trade outcome shares via either an internal Constant Product Market Maker (CPMM) or a fully on-chain order book, with post-resolution fund distribution and a two-tier AI-plus-oracle dispute system.

Document

NameSmart Contract Code Review and Security Analysis Report for RAIN
Audited ByIvan Bondar; Atanas Dimulski
Approved ByOlesia Bilenka
Websitehttps://www.rain.one
Changelog01/06/2026 - Preliminary Report
05/06/2026 - Final Report
18/06/2026 - Retest Report
PlatformArbitrum
LanguageSolidity
TagsPrediction Market; Automated Market Maker (AMM); Oracle; Factory; Claims
Methodologyhttps://docs.hacken.io/methodologies/smart-contracts
  • Document

    Name
    Smart Contract Code Review and Security Analysis Report for RAIN
    Audited By
    Ivan Bondar; Atanas Dimulski
    Approved By
    Olesia Bilenka
    Changelog
    01/06/2026 - Preliminary Report
    05/06/2026 - Final Report
    18/06/2026 - Retest Report
    Platform
    Arbitrum
    Language
    Solidity
    Tags
    Prediction Market; Automated Market Maker (AMM); Oracle; Factory; Claims

Review Scope

Repositoryhttps://github.com/rain1-labs/rain-contracts/
Initial Commit6e17125
Final Commita91bdb3
Retest Commit77eb85c

Audit Summary

49Total Findings
40Resolved
8Accepted
1Mitigated

The system users should acknowledge all the risks summed up in the risks section of the report

Documentation quality

  • Functional requirements are detailed.

    • Project overview is detailed

    • All roles in the system are described.

    • Use cases are described and detailed.

    • For each contract, all futures are described.

    • All interactions are described.

  • Technical description is detailed.

    • Run instructions are provided.

    • Technical specification is provided.

    • The NatSpec documentation is sufficient.

Code quality

  • The development environment is configured.

Test coverage

Code coverage of the project is 43.22% (branch coverage).

  • Deployment and basic user interactions are covered with tests.

  • Negative cases coverage is partially missed.

  • Interactions by several users are tested.

System Overview

The protocol is organized around three deployment-time layers. The first layer is RainDeployer, a UUPS-upgradeable singleton that holds all protocol configuration—fee parameters, oracle factory address, platform address, and the implementation addresses of all eleven diamond facets. When a pool creator calls createPool, RainDeployer assembles a FacetCut[] array and delegates to RainDiamondFactory, which deploys a new RainPoolDiamond instance. The deployer then transfers the oracle-fixed-fee and initial liquidity from the creator into the newly deployed pool. Every deployed RainPoolDiamond records RainDeployer as its FACTORY address, granting it the sole authority to invoke diamondCut on the pool.

Each RainPoolDiamond is an EIP-2535 Diamond proxy. Its constructor calls LibDiamond.initializeDiamond to write pool parameters into the shared DiamondStorage struct, then calls LibDiamond.diamondCut to install all eleven facets. Because diamondCut sets isInitialized = true permanently, individual pools are immutable after deployment; only future pools created by the deployer reflect updated facet addresses. All protocol state—AMM reserves, LP shares, order book linked lists, resolution outcomes, dispute records, and fee accumulators—lives in the single DiamondStorage struct managed by LibDiamond.

Trading and resolution are handled by facets that delegate-call into this shared storage. TradingFacet supports two trading models per pool: an AMM phase using constant-product math on per-option YES/NO reserves, and an order-book phase backed by doubly-linked price queues managed by LinkedListLogic. ResolutionFacet allows anyone to finalize an option after its end time by posting a resolver bond; the designated per-option resolver then calls chooseWinner to confirm the outcome. Disputed outcomes trigger DisputeFacet: the initial openDispute call collects a computed dispute fee in base tokens and reassigns the resolver to the protocol's dispute resolver, entering the Disputed state. If the resolution is subsequently contested again, a second openDispute call enters the Appealed state—swapping the resolver-fee share to USDT via LibUtils, calling createOracle on the deployer to provision an external oracle, and commencing a second appeal cycle. Once resolution is complete and the dispute window has elapsed, ClaimFacet distributes payouts and routes fee shares—including a swap-and-burn path for the RAIN token.

Files in Scope

  • RainDeployer.sol — UUPS-upgradeable protocol coordinator; stores all fee parameters and eleven facet implementation addresses; exposes createPool for permissionless market creation and a suite of onlyOwner configuration setters; transfers initial liquidity and oracle fees from pool creators; restricts createOracle to pools it has deployed.

  • RainDiamondFactory.sol — Thin factory contract; deploys a new RainPoolDiamond with the provided FacetCut[] array and pool parameters, returning its address to the caller.

  • RainPoolDiamond.sol — EIP-2535 Diamond proxy entry point; constructor applies initial facet cuts via LibDiamond (permanently setting isInitialized = true); fallback delegates every unknown function selector to the corresponding facet address stored in DiamondStorage.

  • DiamondCutFacet.sol — Exposes the EIP-2535 diamondCut function gated to the deployer factory; in practice immutable because isInitialized is set during construction.

  • DiamondLoupeFacet.sol — Read-only EIP-2535 loupe implementation; exposes facets, facetFunctionSelectors, facetAddresses, facetAddress, and supportsInterface.

  • TradingFacet.sol — Core trading facet; implements AMM-phase enterOption, enterLiquidity, enterLiquidityBatch, and removeLiquidity using constant-product math, and order-book-phase placeSellOrder and placeBuyOrder with linked-list order matching and fee routing.

  • CancelOrderFacet.sol — Implements cancelSellOrders and cancelBuyOrders, allowing order makers to cancel their resting orders in batch; buy-order cancellations refund escrowed base tokens.

  • SplitMergeFacet.sol — Implements split (collateral → equal YES+NO share accounting, bypassing AMM reserves) and merge (symmetric YES+NO shares → collateral refund); available during AMM and order-book phases while the option is not finalized.

  • DisputeFacet.sol — Implements permissionless openDispute, which serves two phases: in the initial dispute phase it collects a computed fee in base tokens and reassigns the per-option resolver to the protocol's dispute resolver; in the appeal phase it additionally swaps the resolver-fee share to USDT via LibUtils and calls createOracle on the deployer factory to provision an external oracle. Also implements unlockCallback for Uniswap V4 PoolManager callbacks during V4 swap execution.

  • ClaimFacet.sol — Implements permissionless claim; on the first invocation per option distributes platform fees via swap-and-burn, creator and referrer shares, resolver bond, and dispute fees; on every invocation transfers the caller's proportional payout of LP fees and winning pool share.

  • ResolutionFacet.sol — Manages option lifecycle closure; closePool (AI path) and closePool with a proposed winner (human path) are permissionless but require a resolver bond from non-owner/resolver callers; chooseWinner and tooEarly are restricted to the per-option resolver address.

  • OracleFeeFacet.sol — Exposes a permissionless fee-quote helper (calculateBaseTokenOracleFixedFee) and a factory-only sweep function (swapOracleFixedFee) that converts the pool's accumulated base-token balance to USDT via LibUtils, transferring the output to the designated platform or oracle-fee recipient.

  • InfoFacet.sol — Read-oriented query façade providing simulated share-entry quotes, LP-return previews, order-book sizing helpers, and dispute-fee and resolver-bond calculators; getDisputeAppealFee and getResolverBondAmount are non-view because they invoke Uniswap quoter contracts.

  • GetterFacet.sol — Pure view getter façade exposing all DiamondStorage fields: protocol constants, address configuration, AMM reserves, LP state, order-book linked-list metadata, and resolution and dispute records.

  • LibDiamond.sol — Core library defining the DiamondStorage struct stored at a deterministic slot; implements pool initialization with parameter validation, the EIP-2535 cut/add/replace/remove mechanics, and all per-option phase and trading-mode guard functions.

  • LibUtils.sol — Swap utility library; implements swapAndBurn (base token → WETH via the token's configured V2/V3/V4 pool, then WETH → RAIN via Uniswap V3 at the hardcoded router address, then IRainToken.burn with a platform-transfer fallback), referrerCreatorClaim (creator-fee split), and Uniswap V2/V3/V4 quoting and swap helpers for base-token ↔ USDT/WETH routing.

  • PathKey.sol — Local copy of the Uniswap V4 PathKey struct and PathKeyLibrary.getPoolAndSwapDirection; used by LibUtils for V4 multi-hop swap construction.

  • Types.sol — Shared type definitions: PoolState enum (NotDisputed, Disputed, Appealed, Refunded) and TradingModel enum (None, AMM, OrderBook).

  • LinkedList.solLinkedListLogic library implementing a doubly-linked list for order-book queues; supports initialize, append, insert, remove, pop-FIFO, and traversal operations.

  • UniswapV2Library.sol — Local copy of Uniswap V2 pair math helpers: pairFor, getReserves, quote, getAmountOut, getAmountIn, getAmountsOut, getAmountsIn; used by LibUtils for V2 routing.

  • SafeMath.sol — Overflow-safe arithmetic library (add, sub, mul) used by UniswapV2Library.

  • Constants.sol — File-level constants specifying Arbitrum One addresses: USDT, WETH, RAINTOKEN, Uniswap V4 `POOLMANAGER, MINSQRTPRICE, MAXSQRTPRICE, and RAINWETHFEE`; referenced throughout LibUtils and DisputeFacet.

  • Globals.sol — Provides the assembly-based _revert(bytes4 selector) helper used protocol-wide to revert with a four-byte custom-error selector.

Privileged roles

  • Owner (inherited from OwnableUpgradeable): Holds complete administrative authority over the protocol's configuration and upgrade path.

    • Can call setDiamondFactory to update the factory address used for future pool deployments.

    • Can call setResolverAI to update the default AI resolver address assigned to new pools.

    • Can call setOracleFactoryAddress to replace the external oracle factory used for dispute resolution.

    • Can call setBaseToken to change the default base-token address for new pools.

    • Can call setOracleFixedFee to modify the fixed oracle fee charged at pool creation.

    • Can call setCreatorFee to adjust the creator fee rate applied to trading activity.

    • Can call setClosingFee to adjust the fee deducted at option closure.

    • Can call setResultResolverFee to adjust the fee share allocated to result resolvers.

    • Can call setPlatformAddress to redirect the platform fee recipient.

    • Can call setLiquidityFee to modify the fee rate charged on LP operations.

    • Can call setPlatformFee to adjust the platform fee share of trading revenue.

    • Can call setDisputeResolverAI to change the AI address used for dispute resolution.

    • Can call setNewDiamondCutFacet, setNewDiamondLoupeFacet, setNewDiamondTradingFacet, setNewDiamondResolutionFacet, setNewDiamondDisputeFacet, setNewDiamondClaimFacet, setNewDiamondCancelOrderFacet, setNewDiamondInfoFacet, setNewDiamondGetterFacet, setNewOracleFeeFacet, and setNewSplitMergeFacet to update the implementation addresses and function selectors for each of the eleven diamond facets used in all future pool deployments.

    • Can call allowNewToken to whitelist a new ERC-20 token as an accepted pool base token.

    • Can call disallowExistingToken to remove an ERC-20 token from the accepted base-token list.

    • Can call _authorizeUpgrade (invoked internally by the UUPS mechanism) to authorize replacement of the RainDeployer proxy implementation with a new logic contract.

  • Created Pool (runtime check: createdPools[msg.sender] true): Granted only to RainPoolDiamond instances deployed through createPool.

    • Can call createOracle to provision an external resolution oracle; the call transfers base tokens from the pool to the deployer and onwards to the oracle factory.

  • DiamondCutFacet.sol

    • Factory (runtime check via LibDiamond.enforceIsFactory: msg.sender ds.FACTORY): Restricted to the RainDeployer address recorded in DiamondStorage at pool initialization.

      • Can call diamondCut to add, replace, or remove facet function selectors; in practice this path is unreachable for existing pools because isInitialized is set to true during construction.

  • CancelOrderFacet.sol

    • Order Maker (runtime check: msg.sender order.maker per order): Restricted to the address that placed each individual order.

      • Can call cancelSellOrders to cancel one or more of their own resting sell orders, releasing the corresponding share escrow.

      • Can call cancelBuyOrders to cancel one or more of their own resting buy orders and receive a refund of the escrowed base tokens.

  • DisputeFacet.sol

    • Pool Manager (runtime check: msg.sender POOL_MANAGER): Restricted to the hardcoded Uniswap V4 PoolManager address defined in Constants.sol.

      • Can call unlockCallback to execute Uniswap V4 swap settlement steps (swap, sync, settle, take) during V4 swap execution initiated by the protocol's fee-routing paths.

  • ResolutionFacet.sol

    • Per-option Resolver (runtime check: msg.sender ds.optionResolver[option]): A per-option address recorded in DiamondStorage at pool initialization; this address is reassigned to the dispute resolver upon a successful openDispute call.

      • Can call chooseWinner to designate the winning outcome side for a finalized option, computing the fee split between platform and winning-share pools.

      • Can call tooEarly to roll back an option's finalization, transferring the escrowed resolver bond to the calling resolver and, if the option was in a Disputed state, refunding the dispute fee to the original disputer; effectively reopens the option for further resolution attempts.

  • OracleFeeFacet.sol

    • Factory (runtime check via LibDiamond.enforceIsFactory: msg.sender ds.FACTORY): Restricted to the RainDeployer address.

      • Can call swapOracleFixedFee to sweep the pool's entire base-token balance and convert it to USDT via LibUtils, transferring the output to the designated platform or oracle-fee recipient.

Potential Risks

Dependency on External Resolution Logic: The claim and dispute flows in ClaimFacet and DisputeFacet invoke IQuestion.winnerFinalized, IQuestion.winnerOption, IQuestion.timeExtended, IQuestion.calculateWinnerReadOnly, IQuestion.getExternalSource, and IQuestion.refund on an oracle question contract provisioned at appeal time. The logic and security guarantees of this external contract are outside the audit scope; unexpected behavior—such as incorrect winner reporting or a revert in refund—could permanently block resolution or misdirect payouts.

System Reliance on External Contracts: Core protocol operations depend on three external systems not in scope: the oracle factory (referenced via oracleFactoryAddress in RainDeployer) is required for appeal-phase oracle provisioning; Uniswap V2/V3/V4 is required for all fee routing, including the swapAndBurn path in LibUtils and the dispute-fee swap in the appeal phase of DisputeFacet; and the RAIN token (IRainToken.burn) is required for fee burning. Unavailability or compromise of any of these systems blocks the corresponding protocol paths.

Interactions with External DeFi Protocols: LibUtils integrates three versions of Uniswap—V2 (via UniswapV2Library and IUniswapV2Router01), V3 (via ISwapRouter at hardcoded address 0xE592427A0AEce92De3Edee1F18E0157C05861564 and IQuoter at 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6, used for the WETH → RAIN burn path), and V4 (via IPoolManager at the address in Constants.POOL_MANAGER)—for oracle fee conversions, platform fee burns, and dispute fee routing. The security and liveness of these paths inherits from each Uniswap version's own correctness, liquidity availability, and pool existence on Arbitrum One.

Unbounded Array Iteration in Batch Operations: enterLiquidityBatch in TradingFacet iterates over a caller-supplied percentages[] array without an enforced length cap; similarly, cancelSellOrders and cancelBuyOrders in CancelOrderFacet iterate caller-supplied order-ID arrays. Sufficiently large arrays could cause transactions to exceed the transaction gas limit, permanently preventing batch operations from completing.

External Calls Within Order-Matching Loops: The private helpers _executeSellOrder and _executeBuyOrder in TradingFacet iterate over the linked-list order book, executing IERC20.safeTransfer per matched order and optionally calling LibUtils.swapAndBurn and LibUtils.referrerCreatorClaim—both of which contain Uniswap external calls—for each executed trade. As the number of resting orders grows, the cumulative gas cost of a single placeBuyOrder or placeSellOrder call rises proportionally, with the risk of gas exhaustion or prohibitively expensive transactions under active order-book conditions.

Arbitrary Oracle Factory Replacement: The setOracleFactoryAddress function in RainDeployer allows the owner to replace the oracle factory address without any timelock, validation, or bounds check. A malicious or erroneously set address would cause all subsequent appeal-phase openDispute calls—which route resolver-fee shares to the deployer and invoke IOracle.createExternalSource via createOracle—to fail or interact with an unintended contract.

Unrestricted Fee Parameter Modification: The owner of RainDeployer can modify all six fee parameters—oracleFixedFee, creatorFee, closingFee, resultResolverFee, liquidityFee, and platformFee—through dedicated set* functions with no upper-bound enforcement and no timelock. Changes take effect immediately on the next createPool call, allowing fee rates to be set to economically harmful values without advance notice to users.

Absence of Timelock on Critical Operations: All twenty-four-plus onlyOwner functions in RainDeployer—including fee setters, facet address updates, oracle factory replacement, and the UUPS _authorizeUpgrade path—execute immediately upon owner invocation with no mandatory delay. There is no on-chain mechanism that grants users or other stakeholders time to review and react to parameter changes before they take effect.

Insufficient Multi-Signature Controls: The owner role in RainDeployer is controlled by a single address (enforced by OwnableUpgradeable), with no multi-signature or governance contract required for any operation. A single compromised owner key grants unrestricted access to all fee parameters, all facet implementation addresses for future pools, the oracle factory and platform address, and the UUPS upgrade mechanism.

Single Point of Control Over Protocol Configuration: The Owner role in RainDeployer holds sweeping authority over the entire protocol: it can simultaneously alter all fee parameters, replace any of the eleven diamond facet implementations used by future pools, redirect the platform fee destination, change the oracle factory, update the base-token allowlist, and upgrade the deployer contract itself. The safety of the protocol is therefore directly tied to the security of this single private key.

Single Entity Upgrade Authority: The _authorizeUpgrade function in RainDeployer is gated exclusively by onlyOwner, granting the same address that controls fee and configuration parameters the authority to replace the deployer's entire logic contract. No governance vote, multi-signature approval, or timelock delay constrains this upgrade path, meaning a malicious or compromised upgrade could alter the behavior of all future pool deployments without prior notice.

Resolution Dependent on External Oracle Availability: For AI-resolved pools (resolverIsAI = true), the winner determination in ClaimFacet depends on calling IQuestion.winnerFinalized and IQuestion.winnerOption on an externally provisioned question contract. If the oracle service is unavailable, the external question contract fails to finalize, or the IQuestion interface is not implemented correctly by the provisioned contract, the corresponding option cannot progress to its claim phase and user funds remain locked in the pool indefinitely.

Silent Failure on Cross-Chain Deployment or Address Migration: Constants.sol embeds the Arbitrum One addresses for USDT (0xFd086bC7…), WETH (0x82aF49A…), RAINTOKEN, and the Uniswap V4 `POOLMANAGER, while **LibUtils** additionally hardcodes the Uniswap V3 router (0xE592427A…) and quoter (0xb27308f9…) for the WETH → RAIN burn path. If the protocol is deployed to a different network, or if Uniswap redeploys its contracts at new addresses, all fee-routing paths—including swapAndBurn, swapTokensForUSDT, getQuoteOut, getQuoteIn`, and the appeal-phase dispute-fee swap in DisputeFacet—would silently fail or interact with incorrect contracts, potentially locking fee flows or corrupting dispute resolution.

Allowlist Restricted to Standard Non-Hooking ERC-20s: The base-token allowlist managed by allowNewToken and disallowExistingToken in RainDeployer is intended (per protocol team confirmation) to be limited to standard ERC-20 tokens such as USDT, USDC, and DAI; hookable or callback-enabled tokens—ERC-777, ERC-1363, tokens with transfer hooks or pre/post-transfer callbacks, fee-on-transfer tokens, and rebasing tokens—are explicitly out of scope. Trading, liquidity, escrow, and fee-routing flows across TradingFacet, CancelOrderFacet, SplitMergeFacet, ClaimFacet, DisputeFacet, and OracleFeeFacet rely on direct IERC20.safeTransfer and safeTransferFrom calls with no reentrancy guards around the transfer-then-update sequence and assume that the amount transferred equals the amount specified. Whitelisting a hookable, fee-on-transfer, or rebasing token would invalidate these assumptions and could enable reentrancy through ERC-777 tokensReceived callbacks, balance-accounting drift from fee-on-transfer deductions, or share/reserve mismatches from rebases, leading to fund loss or stuck collateral; correctness therefore depends entirely on the Owner of RainDeployer never allowlisting a non-standard token.

Findings

Code
Title
Status
Severity
F-2026-1707Inverted Arguments in _swapTokenForWETHV2 Bypass RAIN Burn and Block Settlements Across All V2 Non-WETH Markets
fixed

High
F-2026-1753Push Transfer to OB Maker Blocks Book on Blacklist
accepted

High
F-2026-1727swapAndBurn Catch Drains Pooled Reserves and Strands WETH
fixed

High
F-2026-1715enterOption AMM Path Lacks minSharesOut and deadline, Exposing Users to Ordering-Driven Slippage
fixed

Medium
F-2026-1718AI-Resolved Pool Funds Lock If chooseWinner Never Called
accepted

Medium
F-2026-1754On-chain Quoter Calls in swapAndBurn Cause enterOption to Exhaust Gas on Large OB Orders
fixed

Medium
F-2026-1746calculateWinnerReadOnly Return Value Ignored, Permanently Blocking claim
fixed

Medium
F-2026-1739Permissionless Pool Creation Allows Blacklisted poolOwner or referrer to Lock All Pool Funds
accepted

Medium
F-2026-1739getEntryShares Preview Diverges From enterOption On Multi-Tick Orders
fixed

Medium
F-2026-1739Uniswap Reverts in openDispute Trap Pool in Disputed State
accepted

Medium
1-10 of 49 findings

Identify vulnerabilities in your smart contracts.

Appendix 1. Definitions

Severities

When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.

Reference on how risk scoring is done is available through the repository in our Github organization:

Severity

Description

Critical
Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.

High
High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.

Medium
Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.

Low
Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
  • Severity

    Critical

    Description

    Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.

    Severity

    High

    Description

    High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.

    Severity

    Medium

    Description

    Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.

    Severity

    Low

    Description

    Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.

Potential Risks

The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.

Appendix 2. Scope

The scope of the project includes the following smart contracts from the provided repository:

Scope Details

Repositoryhttps://github.com/rain1-labs/rain-contracts/
Initial Commit6e1712556ae6a40fb7bc5e9ae81a018fc836d9b0
Final Commita91bdb3e23724759d4160322066bb16f343d578d
Retest Commit77eb85c01d57e904cbc9d16387d7afc66e477f82
WhitepaperN/A
Requirementshttps://github.com/rain1-labs/rain-contracts/blob/audit/hacken/CLAUDE.md
Technical Requirementshttps://github.com/rain1-labs/rain-contracts/blob/audit/hacken/README.md

Assets in Scope

src
diamond
facets
DiamondCutFacet.sol - src › diamond › facets › DiamondCutFacet.sol
src
diamond
facets
CancelOrderFacet.sol - src › diamond › facets › CancelOrderFacet.sol
ClaimFacet.sol - src › diamond › facets › ClaimFacet.sol
DiamondLoupeFacet.sol - src › diamond › facets › DiamondLoupeFacet.sol
DisputeFacet.sol - src › diamond › facets › DisputeFacet.sol
GetterFacet.sol - src › diamond › facets › GetterFacet.sol
InfoFacet.sol - src › diamond › facets › InfoFacet.sol
OracleFeeFacet.sol - src › diamond › facets › OracleFeeFacet.sol
ResolutionFacet.sol - src › diamond › facets › ResolutionFacet.sol
SplitMergeFacet.sol - src › diamond › facets › SplitMergeFacet.sol
TradingFacet.sol - src › diamond › facets › TradingFacet.sol
libraries
LibDiamond.sol - src › diamond › libraries › LibDiamond.sol
LibUtils.sol - src › diamond › libraries › LibUtils.sol
PathKey.sol - src › diamond › libraries › PathKey.sol
RainPoolDiamond.sol - src › diamond › RainPoolDiamond.sol

Appendix 3. Additional Valuables

Additional Recommendations

The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.

To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:

  • Detecting changes to ownership or critical permissions.

  • Monitoring large or unexpected transactions and minting events.

  • Pausing operations when irregularities are identified.

These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.

Frameworks and Methodologies

This security assessment was conducted in alignment with recognised penetration testing standards, methodologies and guidelines, including the NIST SP 800-115 – Technical Guide to Information Security Testing and Assessment , and the Penetration Testing Execution Standard (PTES) , These assets provide a structured foundation for planning, executing, and documenting technical evaluations such as vulnerability assessments, exploitation activities, and security code reviews. Hacken’s internal penetration testing methodology extends these principles to Web2 and Web3 environments to ensure consistency, repeatability, and verifiable outcomes.

Disclaimer