#54887 [SC-Insight] mitigation regression pool token suffix length excludes valid 1 and 20 char values the fix rejects valid edge lengths and breaks agent creation
Submitted on Sep 18th 2025 at 11:55:26 UTC by @Disqualified-User for Mitigation Audit | Flare | FAssets
Report ID: #54887
Report Type: Smart Contract
Report severity: Insight
Target: https://github.com/flare-foundation/fassets/commit/59373cee12e6d2a9fa0a9cc8735bb486faa51b36
Impacts: Griefing (no profit motive for an attacker, but damage to the users or the protocol)
Description
Brief/Intro While fixing #45439 to disallow empty pool token suffixes, the contract introduced a boundary regression that narrows the allowed suffix length range to 2–19 characters. The mitigation added a new minimum check len >= 2 while the maximum check remained exclusive len < 20. As a result, both a one-character suffix and a twenty-character suffix are now rejected on-chain in createAgentVault. The change is in commit 59373cee (“require pool token suffix length >= 2 – immunify 45439”), which modifies AgentsCreateDestroy.sol and adjusts unit tests accordingly. The end result is an inconsistent and unnecessarily strict validator that causes reverts for otherwise reasonable and expected suffix choices.
This is a single validation-range mismatch that manifests through two boundary choices (raising the minimum to 2 and keeping the maximum exclusive). The fix is minimal, restores a natural 1–20 range, and the added tests pin the boundary so this class of drift doesn’t recur.
Severity
Medium — Griefing (no profit motive for an attacker, but damage to the users or the protocol). No funds are stolen or frozen, but valid configurations are rejected at the contract layer, blocking otherwise legitimate agent setups and creating avoidable friction/failed transactions.
Vulnerability Details
The validator lives in contracts/assetManager/library/AgentsCreateDestroy.sol and is reached from createAgentVault, where the pool token suffix is reserved and checked before creating the agent. In the mitigation commit, two key lines were added:
uint256 internal constant MIN_SUFFIX_LEN = 2;
uint256 internal constant MAX_SUFFIX_LEN = 20;
...
require(len >= MIN_SUFFIX_LEN, "suffix too short");
require(len < MAX_SUFFIX_LEN, "suffix too long");Because the upper bound uses a strict “less than,” the accepted length set becomes 2…19. That rejects len == 1 and len == 20. Everything else in the validator remains the same: only A–Z, 0–9, and - are allowed, with hyphens not permitted at the start or end. The commit diff and the accompanying test change make this easy to verify. The test file adds an assertion that an empty suffix reverts as “suffix too short,” but there are no positive tests pinning the len == 1 or len == 20 boundaries, which is how this drift slipped through CI.
This is a real, user-visible regression: short branding-style suffixes (e.g., A) and exactly twenty-character suffixes now hard-revert, preventing otherwise legitimate agent setups. People frequently choose one-character suffixes (branding, initials) or hit the round figure of exactly twenty characters when they construct mechanized identifiers. With the current checks, those reasonable inputs hard-revert, and agent creation can’t proceed. The behavior is purely a byproduct of the boundary arithmetic in the mitigation; there is no deeper protocol reason to forbid 1 or 20.
Impact Details
The issue denies service for a subset of otherwise sensible suffixes. Attempting to create an agent with a one-character or exactly twenty-character suffix reverts during validation, so the agent cannot be created without changing the chosen name. This is damaging without any attacker profit motive: it burns gas, blocks deployments, and forces users to alter naming conventions, while leaving all funds safe.
In practice, an agent owner who picks a one-letter suffix like A or a 20-character suffix will hit a hard revert in createAgentVault. That is not a loss-of-funds event, but it’s a contract-level rejection of otherwise sensible inputs that breaks parity with user expectations and tooling. At scale, this presents as repeated failed transactions, support load, and inconsistent naming across deployments—classic “griefing” style damage with no attacker profit required. That's the basis for Medium severity under the posted scope.
Recommendation
Align the validator to inclusive, human-friendly bounds and protect the intent with explicit boundary tests. The simplest change is to accept 1…20 characters by lowering the minimum to one and making the maximum check inclusive. If you prefer keeping an exclusive upper bound, rename the constant to reflect exclusivity and set it to 21, but the inclusive form below is clearer and matches how the rest of the code reads.
Proposed patch (contract):
Proof of Concept
Step-by-step reproduction
3. Boundary tests (add tests that should pass)
Apply the following additions to test/unit/fasset/library/Agents.ts to assert acceptance of 1- and 20-character suffixes and continued rejection of invalid cases:
Re-run the tests:
You will observe that attempts to create an agent with "A" (length 1) and "ABCDEFGHIJKLMNOPQRST" (length 20) revert during createAgentVault on the mitigation commit, confirming the regression.
4. Apply the fix and verify
Apply the contract patch shown in the Recommendation section (changing MIN_SUFFIX_LEN to 1 and using <= for MAX_SUFFIX_LEN). Then re-run the full test suite:
Observed result: the new 1-char and 20-char acceptance tests will pass. Existing negative cases (empty string, length 21, invalid characters, hyphen at either end) will continue to revert as before, proving the intent is preserved and the regression is fixed.
References
Flare FAssets | Mitigation Audit: https://immunefi.com/audit-competition/flare-fassets--mitigation-audit/scope/#top
#45439 [SC-Low] Empty String Allowed as Pool Token Suffix in _reserveAndValidatePoolTokenSuffix: https://reports.immunefi.com/flare-fassets/45439-sc-low-empty-string-allowed-as-pool-token-suffix-in-_reserveandvalidatepooltokensuffix
Smart Contract - Fix of Report - 45439: https://github.com/flare-foundation/fassets/commit/59373cee12e6d2a9fa0a9cc8735bb486faa51b36
(End of report)
Last updated
Was this helpful?