50916 sc high token creators can bypass factory upgrade controls via wrong code implementation of default admin role in arctokenfactory sol
Submitted on Jul 29th 2025 at 17:17:21 UTC by @demonhat for Attackathon | Plume Network
Report ID: #50916
Report Type: Smart Contract
Report severity: High
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/arc/src/ArcTokenFactory.sol
Impacts: Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief / Intro
In the ArcTokenFactory.sol contract, the createToken() implementation grants DEFAULT_ADMIN_ROLE to the token creator (the msg.sender of createToken) instead of keeping the factory as the default admin. That is:
// Grant all necessary roles to the owner
// Grant the DEFAULT_ADMIN_ROLE to the deployer <--------
token.grantRole(token.DEFAULT_ADMIN_ROLE(), msg.sender); //issue! not following the comment, this grants the highest role to the Token creator!
token.grantRole(token.ADMIN_ROLE(), msg.sender);
token.grantRole(token.MANAGER_ROLE(), msg.sender);
token.grantRole(token.YIELD_MANAGER_ROLE(), msg.sender);
token.grantRole(token.YIELD_DISTRIBUTOR_ROLE(), msg.sender);
token.grantRole(token.MINTER_ROLE(), msg.sender);
token.grantRole(token.BURNER_ROLE(), msg.sender);
token.grantRole(token.UPGRADER_ROLE(), address(this));Because DEFAULT_ADMIN_ROLE is the highest privileged role in an AccessControl setup, token creators who receive it can grant themselves any other role (including UPGRADER_ROLE) and then call upgrade functions on the token proxy directly to replace the implementation with malicious code. This completely bypasses the factory's intended upgrade controls (which are supposed to be enforced by the factory's own upgradeToken() function).
High-level impact
Token creators can grant themselves
UPGRADER_ROLEand call the proxy'supgradeToAndCall()to replace the implementation with malicious implementations that steal funds or freeze transfers.The factory's
upgradeToken()security checks (only callable by factory admins, whitelist checks, tracking) are bypassed by direct proxy upgrades from the token creator.Once malicious implementation is installed, factory admins cannot recover control; funds are at risk permanently for the affected token(s).
Vulnerability Details
Root cause: Excessive (and incorrect) role granting — granting
DEFAULT_ADMIN_ROLEto token creators during creation rather than to the factory itself.Example problematic line (ArcTokenFactory.sol):
Bypass mechanism:
Creator grants self
UPGRADER_ROLE(because they holdDEFAULT_ADMIN_ROLE).Creator calls proxy upgrade directly:
This replaces proxy implementation with malicious code (examples below) that can steal transfers or freeze user transfers while allowing attacker to bypass restrictions.
Malicious implementation technique:
Implementations can hardcode an attacker address so they don't rely on preserved storage layout when used as an implementation, e.g.:
Hardcoded attacker addresses and overriding core logic leads to reliable theft even when storage/layout differs.
Complete Factory Invariant Bypass
Factory intended invariants:
Only factory admins can upgrade tokens.
Only whitelisted implementations can be used.
Factory maintains control over token upgrades.
Attack breaks all invariants:
Creator can upgrade without factory permission.
Malicious implementations bypass whitelist checks.
Factory loses authoritative control and tracking of final implementation.
Impact Details
Direct Fund Theft: demonstrated in PoC below — transfers redirected to attacker.
Permanent Control: malicious creator retains upgrade ability and can deploy multiple malicious implementations.
Multiple attack vectors: complete theft, transfer freeze, overriding factory upgrades.
Recovery: impossible for factory admins once malicious implementation is installed.
Scope: all tokens created by malicious creators via this factory pattern.
Estimated loss potential: potentially total TVL of tokens created by malicious creators (e.g., $1M TVL could be fully stolen).
References
ArcTokenFactory.sol: lines granting
DEFAULT_ADMIN_ROLEto creator (approx lines 192-193 in referenced file).ArcTokenFactory.sol:
upgradeTokenfunction (approx lines 260-285) showing factory-side checks that are bypassable by direct upgrades.
Proof of Concept
Below is the POC test (Forge-style) submitted. It demonstrates creation of a token by a malicious creator, the granting of upgrade privileges, direct upgrade to malicious implementations, and theft/freeze behaviors.
Do not modify — original PoC code preserved:
FIX
Correct behavior: grant DEFAULT_ADMIN_ROLE to the factory contract (so the factory retains the highest privilege) and keep UPGRADER_ROLE and other operational roles consistent with factory control.
Suggested minimal code change in ArcTokenFactory.sol:
Ensure the factory is the DEFAULT_ADMIN_ROLE. Only grant the token creator the operational roles they require (e.g., MINTER, BURNER, MANAGER) but not the default admin role. Also review any other role-granting calls for similar privilege elevation.
If you want, I can:
create a minimal patch/PR diff for ArcTokenFactory.sol showing the exact change(s) and locations, or
statically analyze ArcTokenFactory.sol to confirm the exact line numbers and produce a suggested commit.
Was this helpful?