Dominion Info

Silver has been money for three thousand years and a hedge for as long as anyone has tried to debase a currency. It has not been easy to hold. Coins are bulky. Vaulted accounts are illiquid. ETFs introduce counterparty layers that defeat the point of holding metal in the first place. Dominion fixes that. We work with regulated custodians and licensed brokers to put real, allocated, audited silver behind a permissionless Solana token, SILV. You can hold it, swap it, earn on it, or redeem it for the underlying metal, without giving up custody, trust, or transparency.

Dominion Logo

TrustNet Score

The TrustNet Score evaluates crypto projects based on audit results, security, KYC verification, and social media presence. This score offers a quick, transparent view of a project's credibility, helping users make informed decisions in the Web3 space.

73.26
Poor Excellent

Real-Time Threat Detection

Real-time threat detection, powered by Cyvers.io, is currently not activated for this project.

This advanced feature provides continuous monitoring and instant alerts to safeguard your assets from potential security threats. Real-time detection enhances your project's security by proactively identifying and mitigating risks. For more information, click here.

Security Assessments

"Static Analysis Dynamic Analysis Symbolic Execution SWC Check Manual Review"
Contract address
SiLVFM...B35L
Network
Solana - Mainnet
License N/A
Compiler N/A
Type N/A
Language Rust / Solana
Onboard date 2026/07/24
Revision date 2026/08/12

Summary and Final Words

No crucial issues found

The contract does not contain issues of high or medium criticality. This means that no known vulnerabilities were found in the source code.

Contract owner cannot mint

It is not possible to mint new tokens.

Contract owner can blacklist addresses

It is possible to lock user funds by blacklisting addresses.

Contract owner cannot set high fees

The fees, if applicable, can be a maximum of 25% or lower. The contract can therefore not be locked. Please take a look in the comment section for more details.

Token transfer can be locked

Owner can lock user funds with owner functions.

Token cannot be burned

There is no burning within the contract without any allowances

Ownership is not renounced

The owner retains significant control, which could potentially be used to modify key contract parameters.

Contract is upgradeable

The contract uses a proxy pattern or similar mechanism, enabling future upgrades. This can introduce risks if the upgrade mechanism is not securely managed.

Scope of Work

This audit encompasses the evaluation of the files listed below, each verified with a SHA-1 Hash. The team referenced above has provided the necessary files for assessment.

The auditing process consists of the following systematic steps:

  1. Specification Review: Analyze the provided specifications, source code, and instructions to fully understand the smart contract's size, scope, and functionality.
  2. Manual Code Examination: Conduct a thorough line-by-line review of the source code to identify potential vulnerabilities and areas for improvement.
  3. Specification Alignment: Ensure that the code accurately implements the provided specifications and intended functionalities.
  4. Test Coverage Assessment: Evaluate the extent and effectiveness of test cases in covering the codebase, identifying any gaps in testing.
  5. Symbolic Execution: Analyze the smart contract to determine how various inputs affect execution paths, identifying potential edge cases and vulnerabilities.
  6. Best Practices Evaluation: Assess the smart contracts against established industry and academic best practices to enhance efficiency, maintainability, and security.
  7. Actionable Recommendations: Provide detailed, specific, and actionable steps to secure and optimize the smart contracts.

A file with a different Hash has been intentionally or otherwise modified after the security review. A different Hash may indicate a changed condition or potential vulnerability that was not within the scope of this review.

Final Words

The following provides a concise summary of the audit report, accompanied by insightful comments from the auditor. This overview captures the key findings and observations, offering valuable context and clarity.


Smart Contract Analysis Statement

Program Analysis

The Dominion Silver (SILV) program implements a USDC-collateralized mint and redeem system for a silver-backed Token-2022 asset, priced from a signed Pyth Lazer feed, with a queued-redemption lifecycle, a 24 hour admin timelock, and a guardian veto layer on the Solana blockchain. The engineering quality is high and the design shows the results of several prior review passes; the review found no critical or high severity issues in the program logic. While the overall design follows common Anchor patterns, a few areas need attention:

  • On the reviewed deployment the upgrade authority, the administrator, the seizure delegate and the freeze authority are all the same single wallet, and no guardians are registered, so a single key compromise is a complete takeover. The design intends three separate multisigs and these must be put in place before mainnet.
  • The administrator can point the inventory wallet at any address and pre-mint up to the hard supply cap into it in a single transaction with no delay; this should be time-delayed and made observable through events.
  • The initialize instruction is not restricted to the deployer, so it can in principle be front-run into a state that forces a redeploy; binding it to the program's upgrade authority closes that race.
  • For queued redemptions, the administrator can mark a request settled off-chain, which permanently removes the holder's ability to claim on-chain even though their tokens were already burned; there is no on-chain proof of payment and no holder fallback. This path is closed at launch and should gain an on-chain safeguard before redemptions open.
  • Several administrative actions change security-relevant state without emitting events, including the cancellation of a pending administrator handover, which weakens off-chain monitoring and forensics.

Authority Privileges

The upgrade authority of the program has been deployed under the upgradeable loader with a live authority that, on the reviewed environment, is a single keypair rather than the intended multisig, and it has not been renounced. The authority retains full privileges including:

  • Replacing the program with new code at any time, which overrides every in-program safeguard.
  • Minting SILV through the program up to the hard supply cap, and pre-minting inventory to a chosen wallet.
  • Freezing or thawing any holder's token account, and transferring or burning any holder's tokens through the permanent delegate, exercised directly on the token.
  • Pausing and unpausing the protocol, and scheduling a treasury withdrawal that pays out after the 24 hour delay.
  • Premiums are bounded by fixed ceilings of 3 percent on mint and 5 percent on redeem, well below any punitive level, and every premium change passes through the 24 hour timelock.
  • The supply cap can only be lowered instantly; raising it is blocked on-chain, so the administrator cannot instantly inflate the mintable supply.
  • Public direct redemption is closed at launch and re-enabling it is blocked on-chain, so pre-minted tokens cannot be redeemed against the treasury.
  • Treasury withdrawals are time-delayed for 24 hours and can be cancelled by a guardian during that window, and administrator transfer is a two-step, time-delayed process.

Security Features

The program implements several positive security features:

  • All arithmetic uses checked operations on wide integers with overflow checks enabled in the release profile, and the pricing math rounds in the protocol's favour; a bounded proof confirmed the redeem pricing never exceeds the oracle price and never overflows across the full supported range.
  • The token is constrained to a strict extension allowlist (metadata and permanent delegate only); transfer hooks and transfer fees are explicitly rejected at creation and re-checked on every user instruction, removing the callback-reentrancy and hidden-fee classes.
  • The oracle path verifies a signed, multi-publisher price through the price provider's own program and then enforces staleness, confidence, publisher-count, monotonic-timestamp and price-band guards; the fee for that verification is paid from an isolated program-owned account so a hostile upgrade of the price program cannot reach a user wallet.
  • Program addresses are re-derived on-chain with canonical bumps, every cross-program call targets a pinned program, there is no unsafe code in the program, account closing uses the framework's safe close, and the parser that reads the signed price payload was exercised with tens of millions of random inputs without a single crash.

Note - This Audit report consists of a security analysis of the Dominion Silver (SILV) Solana program. This analysis did not include economic analysis of the project's tokenomics. Moreover, we only audited the main program for the Dominion Silver (SILV) team. Other programs associated with the project were not audited by our team. We recommend investors do their own research before investing.

Files and details

Findings and Audit result

medium Issues | 4 findings

Acknowledged

#1 medium Issue
Broad, upgradeable authority concentrated in a single key on the live deployment
programs/dominion_silver_mint_v2/src/lib.rs
L42
Description

The program is deployed under the upgradeable loader with a live upgrade authority (it is not immutable), and on the reviewed deployment the upgrade authority, the program admin, the expected permanent-delegate and the expected freeze authority are all the same single keypair. The upgrade authority alone can replace the program with arbitrary code and therefore override every in-program safeguard, so it is the ultimate trust root. Concentrating it together with the admin, freeze and seize powers in one externally-owned key means a single key compromise is a total loss of the protocol and of every holder's tokens. This is expected on a devnet staging deployment, but it is the single most important item to resolve before mainnet: the authorities must be split across the separate multisigs the design already names, and the upgrade authority should sit behind a multisig or be renounced once the code is final.

Acknowledged

#2 medium Issue
Issuer can freeze and seize or claw back any holder's tokens
programs/dominion_silver_mint_v2/src/assertions.rs
L35-67
Description

The SILV mint is created with a freeze authority and a Token-2022 permanent delegate, and the program actively asserts both are present and match the configured compliance keys in every instruction that moves SILV. The freeze authority can freeze and thaw any SILV token account, and the permanent delegate can transfer or burn tokens out of any account without the holder's consent. These are mint-level powers exercised directly through the token program by the compliance signer, outside this program. This is an intentional design choice for a regulated silver-backed token and is enforced consistently, but from a holder's and integrator's perspective it is a significant centralization property: balances can be frozen or confiscated by the issuer. It must be clearly disclosed rather than assumed.

Resolved

#3 medium Issue
Instant pre-mint to an admin-chosen wallet with no timelock
programs/dominion_silver_mint_v2/src/instructions/admin/premint.rs
L110-121
Description

The admin can pre-mint SILV to the inventory wallet instantly and with no timelock, up to the hard supply cap, and at the time of the original review could also redirect that wallet in the same block. A compromised or malicious admin can therefore mint the remaining cap headroom into the configured destination in a single transaction. The exposure was originally judged bounded because the cap cannot be raised instantly and the pre-minted tokens could not be redeemed for treasury USDC, so the worst case was unbacked tokens dumped on the secondary market rather than a direct treasury drain. This is the intended launch mechanism for seeding market-maker inventory and is documented as an accepted risk, but the instant nature of it warrants a delay and an event.

Resolved

#4 medium Issue
Admin can finalize a queued redemption off-chain with no on-chain proof of payment
programs/dominion_silver_mint_v2/src/instructions/mod.rs
L8
Description

The queued redemption path burns the user's SILV at request time and records a pending request; the user later claims USDC on-chain once the delay elapses. The admin holds an instruction that flips any pending request to settled-off-chain, and once a request is in that state the claim path rejects it, so the owner can no longer obtain USDC on-chain and can only close the account to recover rent. The settle instruction does not require that a claim was attempted, that the treasury was short, or any on-chain evidence that an off-chain payment happened, and there is no user-side timeout that restores the claim right; the transition is irreversible on-chain. A user whose SILV is already burned therefore depends entirely on off-chain settlement, and if that settlement is disputed, delayed, or not performed - or if the admin key is misused - the position is effectively confiscated with no on-chain recourse.

low Issues | 12 findings

Resolved

#1 low Issue
Initialize is not restricted to the program deployer or upgrade authority
programs/dominion_silver_mint_v2/src/instructions/initialize.rs
L102-114
Description

The initialize instruction creates the single global config PDA and sets every trust anchor of the protocol (admin, permanent-delegate-expected, freeze-authority-expected, oracle feed and premiums), but the deployer signer is unconstrained - there is no check that it is the program's upgrade authority. Because the config PDA is seeded to a fixed constant it can only be created once, so anyone who calls initialize before the legitimate operator can seize the admin role by passing arguments that match the already-created SILV mint's on-chain authorities. The impact is bounded: the mint starts paused, the treasury is empty at this point and the situation is easy to detect, so the practical consequence is a denial of service that forces a redeploy under a new program id rather than a direct loss of funds. It still deserves a fix because it removes an entire class of deployment race.

Resolved

#2 low Issue
Program id configuration is inconsistent across manifests and documentation
Anchor.toml
L12-23
Description

The program declares one id in source and in the devnet manifest entry, but the localnet and mainnet manifest entries point at a different id that the source comments themselves describe as retired, and the README status section also names the retired id as the devnet program. Mismatched ids between the declared program id, the manifest per-cluster entries and the documentation are a real operational hazard: a build or a source-verification run keyed off the wrong entry will silently target or verify the wrong address. On a fresh-deploy-only project this is easy to trip over. It is not exploitable on its own but should be reconciled before mainnet.

Resolved

#3 low Issue
State-changing admin setters emit no events
programs/dominion_silver_mint_v2/src/instructions/admin/caps.rs
L77-379
Description

Several privileged instructions mutate state without emitting an on-chain event: the supply-cap setter, the redemptions on/off switch, the emergency tighten-redeem-limits fast lane, the inventory-wallet setter, and the admin-transfer cancellation. The setters change security-relevant parameters (the hard supply cap, whether redemptions are open, the instant-redeem throttles and the destination of pre-minted inventory). The admin-transfer cancellation clears the pending admin, the eta and the expiry - a governance-critical transition - yet, unlike the propose and accept steps which do emit, it produces no event at all. An off-chain indexer cannot observe any of these without diffing full account snapshots. This is an observability weakness rather than a directly exploitable bug, but it hampers incident detection and forensics on exactly the transitions that matter most.

Acknowledged

#4 low Issue
Treasury can be withdrawn down to a zero floor by default
programs/dominion_silver_mint_v2/src/instructions/admin/execute.rs
L229-232
Description

The timelocked USDC withdrawal is bounded only by the treasury minimum float, which defaults to zero. With the float at zero the admin can schedule a withdrawal of the entire treasury balance and execute it after the timelock elapses. The 24 hour delay plus the guardian cancel path are the intended mitigations, but on the reviewed deployment there were no guardians registered, so the delay was the sole protection. This is the expected treasury-management power of the admin and is time-delayed, so it is low severity, but operators should set a meaningful float so the floor is real.

Resolved

#5 low Issue
No guardians registered on the live deployment
programs/dominion_silver_mint_v2/src/instructions/initialize.rs
L409-427
Description

The program implements a guardian role that can pause the protocol and cancel timelocked proposals and admin transfers during their delay window, which is the main check on a compromised admin between propose and execute. On the reviewed deployment the guardian count is zero, so no guardian can act. Combined with the default zero treasury float and the 24 hour withdrawal timelock, this means a single admin key can move the protocol through its privileged flows with no independent veto. The code is correct; this is a deployment-configuration gap that should be closed before any value is at stake.

Resolved

#6 low Issue
Guardian removal is instant and un-timelocked, so the veto layer can be removed by the admin it constrains
programs/dominion_silver_mint_v2/src/instructions/admin/guardian.rs
L124-298
Description

The guardian role is the intended independent check on a compromised admin: a guardian can pause the protocol and can cancel a timelocked proposal or a pending admin transfer during the delay window. Guardian removal, however, is an instant admin-only instruction with no timelock, and it is not among the actions the timelock covers, so a removal can be neither delayed nor vetoed. The removal sets a cooldown on the guardian record, and all three guardian powers - pause, proposal cancel and admin-transfer cancel - require that cooldown to be clear, so a single removal strips every guardian power in the same transaction. Re-adding a guardian requires the admin, so there is no path by which the guardian set restores itself, and the one hour re-add cooldown adds friction to recovery rather than protection. The practical consequence is that a compromised admin can remove every registered guardian, schedule a treasury withdrawal or an admin transfer, wait out the 24 hour delay and execute it with no veto available. Severity is low on its own account, because it requires a prior admin compromise which is already captured as the authority-concentration finding, and because the removal emits an event and is therefore observable by off-chain monitoring. It is nonetheless the reason the guardian layer cannot yet be credited as an independent control.

Pending

#7 low Issue
Redeem premium changes have no front-running defence while mint premium changes do
programs/dominion_silver_mint_v2/src/instructions/redeem_silv.rs
L127-132
Description

The mint side carries a deliberate two-part defence against being front-run ahead of a premium increase: proposing a mint-premium change sets a pause timestamp equal to the execution time, and the mint handler refuses while either that timestamp is in the future or a mint-premium proposal is armed. The source explains correctly why both halves are needed, because between the delay elapsing and the admin executing or cancelling, the timestamp alone would resume minting at the old premium. The redeem side has the mirror-image exposure and no mirror-image defence. Proposing a redeem-premium change records the pending proposal slot and nothing else, and the redeem handler reads neither that slot nor any equivalent. During the announced delay window before a redeem premium increase, holders redeem at the old cheaper rate, consuming the rolling redemption budget and the treasury at precisely the moment the protocol had decided that outflow should cost more. This was latent while redemptions shipped closed and it is live now that initialize opens them.

Pending

#8 low Issue
Matured timelock proposals never expire and remain executable indefinitely
programs/dominion_silver_mint_v2/src/state/timelock.rs
L34-45
Description

The queued-action account records the scheduling time and the execution time but no deadline, and every execute handler checks only that the current time is at or past the execution time. A proposal that matures and is never executed therefore remains a standing authorisation for the life of the program. This is the same hazard the guardian removal path names explicitly and closes with a bounded execution window, described there as a stored coupon that can be pre-armed while things are quiet and spent later with no reaction time, and the reasoning transfers directly and with more value at stake to the treasury withdrawal, the inventory-wallet redirect, the redeem-limit loosening and the public-mint opening. Two mitigations are already present and are the reason this is low rather than medium: only one proposal per action kind can be active, so a stale proposal blocks new ones of its kind and is therefore visible in the configuration rather than hidden, and a guardian can cancel it at any point before execution. Both depend on somebody noticing that an old slot is still armed months later. Replay and post-cancellation execution are separately and correctly blocked, verified across all twelve execute handlers, by two independent mechanisms: each handler requires the configuration slot to still point at its own nonce, and each closes the queued-action account on execution.

Pending

#9 low Issue
Dead redeem-queue parameters remain writable through both redeem-limit paths
programs/dominion_silver_mint_v2/src/instructions/admin/execute.rs
L566-569
Description

The large-redemption threshold, the queue delay and the redemption request nonce lost their only readers when the queued redemption flow was removed. The struct marks the first two as dead and keeps them declared so that field offsets do not move, which is the right call. The problem is that both write paths still accept them. The effective-change gate explicitly discards them, yet the instant tighten instruction and the timelocked execute handler both assign them, and the emitted event reports the new values. An operator responding to an incident can therefore tighten a large-redemption threshold, see a confirmed transaction and a matching event, and have changed nothing. This is the same silent-no-op-on-an-emergency-lever class the team already found and fixed once for the redemption switch, where the source records the right principle, that a silent no-op on an emergency lever is worse than a revert. One further property of this same payload is worth recording, because it bears on whether the guardian veto can be exercised competently. The action is named for the redeem throttles, but its payload also carries the switch that re-opens redemptions, which is the only route by which USDC leaves the treasury to holders. A guardian deciding within the delay window whether to cancel a proposal named for limits must therefore decode the payload to discover whether it also re-opens the exit, and the three inert fields sit in that same payload. Making the payload say what it does would serve the veto as well as the operator.

Pending

#10 low Issue
Assurance artefacts have drifted from the shipped code: a declared regression gate no longer holds and the formal proofs verify helpers that are no longer on the priced path
audit/harnesses/math-kani/src/lib.rs
L41-72
Description

Three artefacts that a reader is invited to treat as assurance no longer describe the code that ships, and all three failed the same way, by not being attached to anything that would notice. First, the remediation checklist carries a short list of properties that must continue to hold after any change, and one states that the premium ceilings remain at three hundred and five hundred basis points with the combined premium logic unchanged. Neither half holds: the mint ceiling was widened from three hundred to five hundred, and the combined floor is set to zero with both comparisons commented in the source as no-ops. The re-audit brief discloses the ceiling move in a single line under changed policy without connecting it to the gate it breaks, and does not mention the combined logic at all. Second, and more substantially, the formal proof harness is a hand-maintained copy of the pricing core whose own header records the obligation to track the original. The original changed structurally: the fee model moved from a premium baked into an effective price to a fee taken off the top at pure spot, which the source marks by labelling both effective-price helpers as quoting only. A call-site search confirms neither is invoked anywhere outside the unit tests in its own module, while the priced instructions call the fee helper and value the net amount at the raw oracle price. Of the three proofs, the one asserting that the redeem price never exceeds the oracle now constrains a function with no caller, and that is precisely the property the published statement cites as evidence. The mint proof keeps partial value because the payout helper it exercises is live and the domain it explores contains the live domain, but it reaches that helper through the dead one, and it still assumes a premium bound of three hundred basis points while naming the ceiling constant that is now five hundred. The round-trip proof is the most representative and also the narrowest, fixed to one price and bounded to a hundred dollars. Third, an attempt to run the harness in this pass did not terminate: the solver was stopped after roughly seventeen hours still inside the first of the three proofs with no verdict emitted, on a harness whose header records that its bounds were already narrowed for tractability. That is recorded as not verified rather than as a failure, and it is the clearest evidence for the process point, since a proof nobody runs can report neither that it has stopped matching the code nor that it has stopped finishing. The practical risk in all three is low and should be stated as such. The launch premiums moved down rather than up, every premium change passes the delay, and a user on the mint side is independently protected by the minimum-output check, so nobody can be priced worse than they agreed. Nothing indicates the live math is wrong; it is simple, unit-tested and independently fuzzed. What is affected is the accuracy of claims made to readers who cannot check them, which is the reason an audit statement exists. The other declared gates were re-checked and do hold: overflow checks enabled in the release profile, the extension allowlist unchanged and still rejecting transfer hooks and fees, a thirty second staleness ceiling, a tighten-only supply cap, instant re-opening of redemptions still refused, and the development and harness features non-default. The publisher floor deserves mention on the other side of the ledger, being enforced at the point of use by taking the maximum of the configured value and the hard floor rather than only at the setter, which is the stronger placement.

Pending

#11 low Issue
The guardian veto is not independent of the admin it constrains, and the program's independence checks cannot detect it
programs/dominion_silver_mint_v2/src/instructions/admin/guardian.rs
L50-104
Description

The guardian is the designated independent check on the admin, and on this deployment it is not independent, by two separate mechanisms that compound. The first is in the program. The removal side was hardened correctly and thoroughly, but the appointment side was loosened in the same period: the appointee co-signature was removed, so growing the set is a single admin signature with no external consent and no delay. With the active-guardian floor at one, three slots by default and five configured for mainnet, a compromised admin appoints a key it controls, schedules removal of the honest guardian, absorbs that guardian's single self-cancellation, re-schedules and finalises, needing no consent from outside itself and completing in roughly two delay windows, after which every counter still reads healthy because the count counts registrations rather than independence. The recorded reasoning for dropping the co-signature is sound on its own terms, that a compromised operator could generate and sign for the key so it proved participation rather than independence, and that it made appointment unexecutable through the documented ceremony; what it does not address is that the co-signature was the only step that made dilution visible before it landed. The second mechanism is in the deployment and was disclosed by the operator: the vault holding the guardian and the vault holding the admin are both three-of-five over the same five members, so three keys reach both at the same instant and the capture sequence above is not even required. Critically, every independence check the program performs compares addresses, and the two vaults are different addresses, so the appointment check, the authorisation predicate and the unpause precondition all pass while the property they exist to establish is false. That is not a coding error, since signer-set membership behind a multisig address is not visible to the program, but it means the checks cannot be read as evidence of independence and an integrator or auditor reading them alone would conclude the opposite of the truth. Two smaller related weaknesses ride on the same mechanism: the unpause instruction takes the guardian record as a plain account rather than a signer, so it establishes that a guardian exists and not that one consented, and the authorisation predicate carries a documented residual in which an admin transfer onto a guardian key leaves that guardian counted but inert. SEVERITY. Graded Low rather than Medium, on the convention the original register already applies to the guardian layer: a finding whose precondition is itself carried as a separate higher-severity item is scored on what it adds beyond that precondition, not on the combined outcome. What this adds is the failure of a mitigating control rather than a new capability. Every path it opens presupposes either an already-compromised administrator or a quorum that, on the disclosed assignment, simultaneously holds the upgrade authority, and an attacker holding the upgrade authority can replace the program and remove the guardian check outright, so the veto's non-independence grants that attacker nothing it did not already have. The concentration itself remains open at Medium and is where this exposure is scored. It would return to Medium if the authority split were completed without also making the guardian independent, because the veto would then be the layer actually being relied upon.

Pending

#12 low Issue
Unbacked pre-mint reaches the treasury through the open redeem path, bounded only by operational controls that do not yet exist
programs/dominion_silver_mint_v2/src/instructions/admin/premint.rs
L56-108
Description

The pre-mint instruction is instant, admin-only, requires no USDC, reads no oracle, and is bounded only by the lifetime supply cap of 150000 ounces. Since the launch-posture change, initialize ships with redemptions enabled, so pre-minted supply that is not backed by treasury USDC can be burned for treasury USDC. That route has none of the three protections the governed withdrawal has: no delay, no guardian cancellation window, and no minimum treasury float, because the float deliberately gates the administrative path only so a user redemption never fails on an admin-facing threshold. Two mitigations must be credited before the residual is stated. The destination is no longer redirectable, being bound at initialize with the instant setter deleted, so the admin key alone cannot mint into an address it controls. And the pre-mint is gated on the pause, so the exposure begins at go-live rather than at initialization. What remains is a custody problem that the operator identified independently and recorded as a numbered decision, and their analysis matches this one including the correct rolling-window bound. The inventory wallet is an on-curve single-signer hot wallet, deliberately so, and it is intended to hold the pre-minted supply. Its holder signs the redemption directly, with no admin instruction and no delay, so the weakest key in the system controls the unbacked supply that can draw on the backing. Blocking that address in the redemption path would close nothing, because the token is fungible and can be moved first. The only code bound is the rolling window, whose honest limit is close to twice the configured budget across an adversarially aligned span, roughly forty thousand USDC in the first day and twenty thousand per day thereafter while nobody pauses. The accepted mitigation is entirely operational and has two parts, pre-minting only an operational tranche and holding the reserve in a vault, and it rests on two conditions the operator's own register records as not existing as of the date of this review: the tranche size is an input that is not yet fixed, and neither the automated alerting nor the exercised guardian response exists. A bound that depends on an unfixed number and on detection that has not been built is not yet a bound, which is why this stays open and why the recommendation is to place it in the program. SEVERITY. Graded Low rather than Medium, on the convention the original register already applies to the guardian layer: a finding whose precondition is itself carried as a separate higher-severity item is scored on what it adds beyond that precondition, not on the combined outcome. What holds the exposure down is a combination of four bounds that are real and verifiable in source or in the operator's register: the destination cannot be redirected without a delay and a cancellation window, the pre-mint is gated on the pause so nothing is exposed before go-live, the conversion route requires the private key of a wallet held outside the program's control so this is a custody compromise rather than an administrator action, and the rolling window caps the rate at close to twice the configured budget per span regardless of how much unbacked supply exists. The loss is therefore rate-limited and capped by the tranche actually issued rather than by the supply cap. It would return to Medium if the reserve were issued to the hot wallet rather than held in a vault, and it should be treated as Medium in operational terms until the two conditions the operator sets for itself are met, namely a fixed tranche size and working detection, because until then the bound is a policy rather than a control.

optimization Issues | 3 findings

Acknowledged

#1 optimization Issue
Mint-authority PDA is re-derived from scratch on every user instruction
programs/dominion_silver_mint_v2/src/assertions.rs
L28-29
Description

The runtime mint invariants check recomputes the mint-authority PDA with a full program-address search on every user instruction. The canonical bump is fixed at deploy time, so the search work is repeated needlessly on the hot path. Deriving from a stored bump would save the search cost. This is a compute optimisation only; correctness is unaffected.

Acknowledged

#2 optimization Issue
Minor redundant work flagged by static analysis
programs/dominion_silver_mint_v2/src/math.rs
L19-31
Description

Static review flagged a handful of small inefficiencies: a constant is cast to the type it already has in the pricing math, several admin bound checks are written as two comparisons where a single range-contains would be clearer, and the price-delta check computes an absolute difference by hand rather than with the standard helper. None affect behaviour; they are trivial readability and compute cleanups.

Acknowledged

#3 optimization Issue
Document and pin the compute budget for the oracle-plus-CPI path
programs/dominion_silver_mint_v2/src/instructions/mint_silv.rs
L185-259
Description

The priced paths each perform an oracle verification cross-program call, parse the returned payload, walk the full set of token-2022 mint extensions for the invariants check, and then do one or two token transfers. This is a comparatively heavy compute profile. Profiling the paths and requesting an explicit compute unit limit from the client keeps them reliable under congestion, and avoiding repeated deserialization of the same mint account trims the cost. This is an efficiency note, not a correctness issue.

informational Issues | 11 findings

Acknowledged

#1 informational Issue
Dead code and a stale error message
programs/dominion_silver_mint_v2/src/errors.rs
L1-500
Description

The code carries several leftovers from earlier designs: error variants that are no longer raised, kept for discriminant stability which is a reasonable choice, and declarations that are defined but never used. None of this affects behaviour, but the unused declarations invite confusion about what is actually enforced, and the reason for keeping the unraisable variants should be explicit rather than inferred.

Acknowledged

#2 informational Issue
Compliance mode flag is never read as a gate
programs/dominion_silver_mint_v2/src/state/config.rs
L122
Description

The compliance-mode boolean is set at initialize and can be toggled through a timelocked action that also pauses the protocol, but no instruction ever reads it to gate behaviour. Its only on-chain effect is triggering an auto-pause when it flips. The actual compliance enforcement is the freeze and permanent-delegate mechanism exercised off-chain. This is consistent with the design but the flag's name implies an on-chain gate that does not exist, so it should be documented or wired up to avoid a false sense of enforcement.

Resolved

#3 informational Issue
A single signed price can be reused within its freshness window
programs/dominion_silver_mint_v2/src/oracle.rs
L54
Description

The oracle enforces a non-decreasing high-water mark on the feed update timestamp but allows equality, so the same signed price print can be submitted for more than one operation as long as it is the newest one seen and still inside the staleness window. The staleness, confidence, publisher-floor and price-band guards all still apply, so the reuse is bounded to intra-window price movement of a low-volatility asset, which the design explicitly accepts. It is called out here so the assumption is on the record and re-examined if the window is widened or the asset becomes more volatile.

Resolved

#4 informational Issue
Price-delta circuit breaker disarms after a period of inactivity
programs/dominion_silver_mint_v2/src/oracle.rs
L97-139
Description

The price-delta breaker skips its check when the last recorded price is older than the decay window, and the dust filter only records a new reference price for operations above a minimum size. As a result a large price move can pass unchecked after a quiet period, and a run of sub-threshold operations will not re-arm the reference. This is by design and is a secondary layer behind the signed feed's own staleness, confidence, publisher-floor and price-band guards, which remain in force. It is noted so operators keep the decay window and dust threshold conservative and do not rely on the breaker as a primary control.

Acknowledged

#5 informational Issue
Style and deprecation warnings from static review
programs/dominion_silver_mint_v2/src/lazer_cpi.rs
L19
Description

Static review reports a set of non-functional warnings across the program: manual range comparisons that could use range-contains, redundant casts to a type a value already has, a hand-written absolute difference, helpers with more parameters than the style threshold, and uses of standard-library items that are now deprecated in favour of newer equivalents. None affect correctness, but if the project intends to compile with warnings denied they must be resolved, and cleaning them up improves readability.

Resolved

#6 informational Issue
Reserved future-phase fields are present but inert
programs/dominion_silver_mint_v2/src/state/config.rs
L169-179
Description

The config reserves fields for later phases that are initialized but never read at launch. This is a deliberate and reasonable way to keep a future upgrade to pure logic with no account resize. The one thing to carry forward is that the pre-mint path does not gate on the reserved granular mint-pause flag, so whoever activates that flag later must also wire it into pre-mint, which is itself a mint path.

Resolved

#7 informational Issue
Deployed bytecode could not be verified against source in this review
rust-toolchain.toml
L1-5
Description

A byte-for-byte comparison of the on-chain program against a locally built artefact was not possible in the original review because the available compiler and framework versions differed from the versions the project pins, and the repository declared several conflicting pins across its manifests, container definition and continuous integration configuration. To close the gap, reconcile the pins and then run a reproducible build with them and compare hashes against the deployed program before mainnet.

Resolved

#8 informational Issue
Transitive dependency advisories
Cargo.lock
L1
Description

The dependency advisory scan reports no known exploitable vulnerabilities. It does raise informational advisories on four transitive crates: two are unmaintained and two carry soundness notices. All of them are pulled in through the standard blockchain runtime, token and cryptography stack rather than through code paths this program invokes, and the specific unsound functions are not used on the price or accounting paths. They are recorded for completeness and should be updated when the upstream platform and framework crates move to patched versions.

Resolved

#9 informational Issue
Timelock action data is sliced without a prior length check
programs/dominion_silver_mint_v2/src/instructions/admin/execute.rs
L897-900
Description

The admin-timelock execute handler reads its new value by slicing the first four bytes of the stored action data directly, without first checking that the data is at least four bytes long. Every other execute handler guards this with an explicit length check before slicing, and the propose path always writes exactly four bytes, so this is not reachable in practice. It is flagged only for consistency and defensive hardening, since an unchecked slice would be a panic path if the stored state were ever malformed.

Pending

#10 informational Issue
Load-bearing security comments contradict the shipped launch posture
programs/dominion_silver_mint_v2/src/instructions/initialize.rs
L61-62
Description

Three comments on the priced and governance paths describe a posture the code no longer has. Initialize states that every later guardian appointment requires the named key to sign so the set can never grow without that key's consent; the co-signature was removed, so this is now false, and it is the premise of the surrounding argument that binding the first guardian at initialization moves the trust boundary. The redeem handler states that a dust-capture primitive is not exploitable because redemptions are disabled, while initialize enables them. The mint handler states that public direct minting is closed at launch and that pre-mint is the only path, while initialize opens it. A unit test named for the closed default pins a constant that initialize does not use, so it passes while asserting the opposite of the deployed behaviour. These are the first thing an incident responder reads, and the reasoning in the surrounding blocks is otherwise unusually thorough and correct, which makes the stale lines more misleading rather than less.

Pending

#11 informational Issue
Arming the compliance gate is instant, un-delayed and un-vetoable, and enlarges the disclosure owed to holders
programs/dominion_silver_mint_v2/src/instructions/admin/kyc_admin.rs
L52-66
Description

The compliance gate ships dormant, with its scope flags at zero, but both priced instructions read it on every call, so arming it is a configuration change rather than a new version of the program. That is a deliberate and well-flagged design decision and the enforcement path was reviewed as live code on that basis. The observation is about who can arm it and how fast. The scope setter is an instant admin-only instruction, is not among the delayed actions, and is not subject to guardian cancellation, so a single admin signature makes every mint and every redemption conditional on an attestation account that the admin also controls the issuance and revocation of. Halting flows instantly is the correct direction for an emergency lever and is consistent with the tighten-fast asymmetry applied elsewhere, so the instant arming is defensible on its own. Two things distinguish it from the redemption switch, which is the closest comparison. It is selective rather than global, so it is an admit-and-exclude primitive rather than an on-off one, and it reaches minting as well as redemption. And the source itself records an ordering hazard, that attestations must be written before arming or every existing holder is locked out, which a single instant transaction is able to get wrong with no delay in which to catch it. None of this exceeds the trust model already disclosed for the freeze authority and the permanent delegate, so it is not a new class of power. It is a new instance of it, in a different place, and the outstanding holder disclosure does not currently mention it.