Replay protection in mint() lacks nonce, preventing legitimate repeated mints with same parameters
Mint signatures are hashed only over (to, value, stakingPool). Repeated legitimate mints with identical parameters share the same hash and are blocked as replays after the first.
Description
The mint() function in GenesisLicense.sol uses a signature hash composed of (to_, value_, stakingPool_) to prevent replay attacks:
bytes32 structHash = keccak256(abi.encode(MINT_INFO_TYPEHASH, to_, value_, stakingPool_));bytes32 hash = _hashTypedDataV4(structHash);require(!$._mintHashes[hash], "Used hash"); // Prevent replay$._mintHashes[hash] = true;
Because this hash does not include a nonce, multiple mint attempts with the same parameters produce the same hash, causing valid mints to be rejected as replays.
Impact
A user who legitimately needs to mint the same (value, stakingPool) combination more than once (for example two NFTs at the same price into the same pool) cannot do so without obtaining a different signature. This forces operational workarounds and creates silent failures from the user perspective.
Recommendation
Implement an internal nonce per user (or per address) that is included in the signed data and incremented on every successful mint. This ensures every signature is unique even if the other parameters are the same, preventing replay attacks effectively while allowing repeated mints with identical parameters:
mapping(address => uint256) private _nonces;function mint(address to_,uint256 value_,address stakingPool_,bytes calldata signature_) external nonReentrant {uint256 nonce = _nonces[to_];bytes32 structHash = keccak256(abi.encode(MINT_INFO_TYPEHASH, to_, value_, stakingPool_, nonce));bytes32 hash = _hashTypedDataV4(structHash);require(SignatureChecker.isValidSignatureNow($._verifier, hash, signature_), "Invalid signature");require(!$._mintHashes[hash], "Used hash");$._mintHashes[hash] = true;_nonces[to_] += 1;// Mint logic...}

