The factory creates Access Tokens using an off-chain signature which is verified in SignatureVerifier::checkAccessTokenInfo.
The signed message is constructed with abi.encodePacked over multiple dynamic fields (name, symbol, contractURI, feeNumerator, chainId).
This concatenation is ambiguous because abi.encodePacked concatenates raw bytes of dynamic strings without length delimiters. Distinct inputs can collide (for example, "USDC" + "USDC" == "USD" + "CUSDC" when concatenated), enabling signature collisions across different (name, symbol) pairs.
Because abi.encodePacked does not include length separators for dynamic types, different combinations of inputs can produce the same byte sequence and thus the same hash and signature.
Example collision: a signature issued for (name = "USDC", symbol = "USDC") can be reused to create a different collection with (name = "USD", symbol = "CUSDC").
Impact
Authorization bypass for collection creation: an attacker can deploy unauthorized collections using a signature intended for a different collection.
Collection spoofing and loss of control over what the platform signs; potential reputational damage and misdirected user funds.
The same issue appears across the SignatureVerifier contract wherever abi.encodePacked is used for hashing signed data.
Replace abi.encodePacked with abi.encode when building the message to hash. abi.encode includes type and length information, preventing ambiguous concatenation.
Alternatively, use EIP-712 typed structured data signing to robustly encode signed fields.
Proof of Concept
Use the following test inside factory.test.ts under the Deployment describe block.
1
Setup & context
The test demonstrates a signature collision where a signature for (name = "USDC", symbol = "USDC") is reused to create a different collection (name = "USD", symbol = "CUSDC").
Fixture provides: factory, alice, bob, signer, and chainId.
2
1) Alice obtains a valid signature and creates (name = "USDC", symbol = "USDC")
Code:
3
2) Bob reuses the same signature to create (name = "USD", symbol = "CUSDC")
Code (continuation):
Test output after running:
This confirms a successful reuse of the same signature to create two distinct collections due to encoding ambiguity.