The CentrallyIssuedToken contract implements a standard ERC20 token with burn and migration-based upgrade functionalities. It utilizes SafeMath for arithmetic operations, mitigating common integer overflow/underflow risks. However, the contract exhibits a high degree of centralization through the upgradeMaster role, which controls critical upgrade parameters. Several code security patterns, such as the approve function's front-running mitigation and the use of throw statements, are outdated or introduce usability issues. The upgrade mechanism itself includes important checks for the UpgradeAgent but relies heavily on the trustworthiness of the upgradeMaster.

On-chain security analysis — is it a scam or legit?
Is StorjToken Safe?
Not verified
This record has not gone through deep verification and is not being monitored. The score is a dated snapshot — the token’s risk can change at any time.Own this token? Put it under verification →The CentrallyIssuedToken contract implements a standard ERC20 token with burn and migration-based upgrade functionalities.
Read the full analysis- Ownership status UNKNOWN
- Top-10 concentration > 50%
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 95.2%
- LP top3 unlocked holders = 97.6%
- 1 High finding(s) from audit
- 2 Medium finding(s) from audit
- 1 Low finding(s) from audit
Exact factors
- Ownership status UNKNOWN (owner could not be resolved)
- Top-10 concentration > 50% (63.5% total → 60.4% effective; 58.4% in EOAs, 5.1% in contracts — heavy)
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 95.2% (independent LP — depth risk, pool = 64% of DEX liquidity)
- LP top3 unlocked holders = 97.6% (independent LP — depth risk, pool = 64% of DEX liquidity)
- 1 High finding(s) from audit
- 2 Medium finding(s) from audit
- 1 Low finding(s) from audit
Each factor is an on-chain fact recorded at the time of this analysis. The score is computed from them by a deterministic function, so the same contract returns the same score for anyone who runs the audit. How scores are computed
Security Checklist
as of audit · Sep 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking5.1%
- Walletsanonymous holders, free to sell58.4%
- Everyone elsethe rest of the supply36.5%
How holder types affect the score
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.
Holder balances as recorded by the audit of Sep 4, 2026
Liquidity
as of audit · Sep 4The risk score reads depth across every pair.
The LP tokens of the analysed pool are not locked or burned, so whoever holds them can withdraw that liquidity.
0x3cbe…8e990x50a5…5a3e0xe2e6…0be90xa406…2d990xa118…3cd80x4018…cc940x9fbc…b3010xf873…2cfe0x1698…9e7d0x2e52…ec6aNo privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighCentralized Control by upgradeMaster
The upgradeMaster address holds significant power, including the ability to set the upgradeAgent (which facilitates token migration) and to change the upgradeMaster address itself. This single point of control introduces a high centralization risk, as a compromised or malicious upgradeMaster could lead to unauthorized token migrations or loss of control over the upgrade process. This impacts 7.3 Access Control and 7.5 Governance.H-01
Issue
The upgradeMaster address holds significant power, including the ability to set the upgradeAgent (which facilitates token migration) and to change the upgradeMaster address itself. This single point of control introduces a high centralization risk, as a compromised or malicious upgradeMaster could lead to unauthorized token migrations or loss of control over the upgrade process. This impacts 7.3 Access Control and 7.5 Governance.
Fix
Implement a multi-signature wallet or a decentralized governance mechanism (e.g., a DAO) to control the upgradeMaster role. This would require multiple approvals for critical administrative actions, significantly reducing the risk associated with a single point of failure.
Status
Unresolved
MediumOutdated approve Front-Running Mitigation Pattern
The approve function includes a check if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; which forces users to first set an allowance to zero before increasing it to a new non-zero value. While this pattern attempts to mitigate a specific front-running attack where an attacker can sandwich an approve transaction to drain funds, it introduces a cumbersome user experience and does not fully eliminate all front-running scenarios. Modern ERC20 best practices recommend using increaseAllowance and decreaseAllowance functions. This impacts 7.2 Code Security and 7.4 Economic.M-01
approve Front-Running Mitigation PatternIssue
The approve function includes a check if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; which forces users to first set an allowance to zero before increasing it to a new non-zero value. While this pattern attempts to mitigate a specific front-running attack where an attacker can sandwich an approve transaction to drain funds, it introduces a cumbersome user experience and does not fully eliminate all front-running scenarios. Modern ERC20 best practices recommend using increaseAllowance and decreaseAllowance functions. This impacts 7.2 Code Security and 7.4 Economic.
Fix
Consider replacing the current approve logic with increaseAllowance and decreaseAllowance functions. This provides a safer and more user-friendly way to manage token allowances without requiring a two-step approval process.
Status
Unresolved
MediumDeprecated throw Statements and assert Usage
The contract extensively uses throw for error handling and assert within the SafeMath library. In modern Solidity, require() and revert() are the preferred mechanisms for handling errors related to invalid user input or state, while assert() is typically reserved for checking internal invariants. Using throw and assert for general error conditions can lead to higher gas costs on failure compared to require/revert in newer EVM versions. This impacts 7.2 Code Security.M-02
throw Statements and assert UsageIssue
The contract extensively uses throw for error handling and assert within the SafeMath library. In modern Solidity, require() and revert() are the preferred mechanisms for handling errors related to invalid user input or state, while assert() is typically reserved for checking internal invariants. Using throw and assert for general error conditions can lead to higher gas costs on failure compared to require/revert in newer EVM versions. This impacts 7.2 Code Security.
Fix
Refactor the code to replace throw statements with require() or revert() for external input validation and state checks. While assert in SafeMath is acceptable for invariant checks, consider updating the library to use revert() for clarity and consistency if possible.
Status
Unresolved
LowInconsistent onlyPayloadSize Modifier Usage
The transfer function uses the onlyPayloadSize modifier, which is an outdated pattern intended to prevent short address attacks. This modifier is generally not effective against modern attacks and can cause unexpected issues. Furthermore, the transferFrom function, which also takes address and value arguments, does not use this modifier, leading to inconsistency in the contract's defensive patterns. This impacts 7.2 Code Security.L-01
onlyPayloadSize Modifier UsageIssue
The transfer function uses the onlyPayloadSize modifier, which is an outdated pattern intended to prevent short address attacks. This modifier is generally not effective against modern attacks and can cause unexpected issues. Furthermore, the transferFrom function, which also takes address and value arguments, does not use this modifier, leading to inconsistency in the contract's defensive patterns. This impacts 7.2 Code Security.
Fix
Remove the onlyPayloadSize modifier from the transfer function. This pattern is largely ineffective and can introduce unnecessary complexity or compatibility issues. Modern Solidity compilers and best practices do not recommend its use.
Status
Unresolved
InfoRedundant canUpgrade Function
The canUpgrade() function in UpgradeableToken always returns true. This makes the UpgradeState.NotAllowed branch in getUpgradeState() unreachable and renders the canUpgrade() function itself redundant. If there are no conditions under which an upgrade should be disallowed, the function serves no practical purpose. This impacts 7.1 Architecture.I-01
canUpgrade FunctionIssue
The canUpgrade() function in UpgradeableToken always returns true. This makes the UpgradeState.NotAllowed branch in getUpgradeState() unreachable and renders the canUpgrade() function itself redundant. If there are no conditions under which an upgrade should be disallowed, the function serves no practical purpose. This impacts 7.1 Architecture.
Fix
Either remove the canUpgrade() function if it's not intended to ever return false, or implement actual conditions within it that determine whether an upgrade is allowed. If removed, adjust getUpgradeState() accordingly.
Status
Unresolved
InfoMissing Event for setUpgradeMaster
The setUpgradeMaster function allows the current upgradeMaster to transfer its administrative role to a new address. This is a critical administrative action, but no event is emitted to log this change on-chain. The absence of an event makes it difficult to track changes in the upgradeMaster role, hindering transparency and auditability of administrative actions. This impacts 7.2 Code Security and 7.8 Operations.I-02
setUpgradeMasterIssue
The setUpgradeMaster function allows the current upgradeMaster to transfer its administrative role to a new address. This is a critical administrative action, but no event is emitted to log this change on-chain. The absence of an event makes it difficult to track changes in the upgradeMaster role, hindering transparency and auditability of administrative actions. This impacts 7.2 Code Security and 7.8 Operations.
Fix
Emit an event (e.g., UpgradeMasterChanged(address indexed oldMaster, address indexed newMaster)) whenever the upgradeMaster address is updated. This provides an on-chain record of the change, improving transparency and making administrative actions easier to monitor and audit.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The technical architecture (7.1 Architecture) is a multi-inheritance pattern for an ERC20 token with burn and upgrade features. Code security (7.2 Code Security) benefits from SafeMath for arithmetic, preventing overflows/underflows. However, the contract uses deprecated throw statements and assert for general error handling, which can be less gas-efficient than require/revert. The approve function's front-running mitigation pattern (M-01) is outdated and can cause usability issues. Additionally, the onlyPayloadSize modifier is inconsistently applied and generally not recommended (L-01). Access control (7.3 Access Control) for administrative functions like setUpgradeAgent and setUpgradeMaster is appropriately restricted to the upgradeMaster.
The economic model (7.4 Economic) is a standard centrally issued token with a burn mechanism. The initial supply is minted to a single owner in the constructor. A significant governance risk (7.5 Governance) is the high centralization around the upgradeMaster address (H-01). This address has the sole authority to set the upgradeAgent for token migration and can also transfer its own master role. This single point of control introduces a substantial risk if the upgradeMaster key is compromised or acts maliciously. The approve function's front-running vulnerability (M-01) also presents an economic risk to users.
The contract implements a token migration upgrade pattern (7.7 Upgrades), where users actively transfer their tokens to a new UpgradeAgent contract. The setUpgradeAgent function includes important checks, such as verifying the isUpgradeAgent() interface and ensuring originalSupply() matches totalSupply, which are good practices to prevent misconfiguration. However, the entire upgrade process is controlled by a single upgradeMaster address (H-01), creating a centralized point of failure. There is also no event emitted when the upgradeMaster itself is changed (I-02), hindering transparency for this critical administrative action.
It is recommended to address the high centralization risk by implementing a multi-signature wallet or a decentralized governance mechanism for the upgradeMaster role.
This would distribute control and reduce the risk of a single point of failure. Additionally, consider updating the approve function to use increaseAllowance and decreaseAllowance patterns to improve user experience and mitigate front-running risks more effectively. Replace deprecated throw and assert statements with require and revert for better gas efficiency and modern Solidity compatibility. Finally, ensure all critical administrative actions, such as changing the upgradeMaster, emit corresponding events for transparency and auditability.
Contract & Record
Free for any token on the record. It links to this page and always shows the current score and the date it was checked.
- Aug 14, 202653Medium
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Would You Like a More Detailed Audit of StorjToken?
Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.
Get Detailed Audit Is this your token? Publish your own audit on this page