When a chain hard fork (that changes the chain ID) occurs in the future, all meta transactions will be replayable on both chains.
The contract EIP712Base sets the domain separator at construction and queries the chain ID then. Afterwards, getDomainSeperator always returns this cached separator with the chain ID when the contracts were deployed. However, there can be hard forks (happened in the past with e.g. Ethereum / Ethereum Classic and can certainly happen in the future with Polygon) where the chain ID on the new chain is different. In these cases, all meta transactions will be replayable across both chains, which EIP712 explicitly tries to prevent (by including the chain ID).
When a chain hard fork occurs, a user can replay all transactions from the "canonical" chain (with the original ID) on the new one. They can therefore do operations that the user never intended to do (on the new chain), which can lead to a loss of funds there.
OpenZeppelin's EIP712 implementation solves this problem nicely by checking if the chain ID is still equal (further signifying the importance of not having out-dated chain IDs): https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol#L84
A similar approach could be used to avoid having to reconstruct the separator in the happy case (when the chain ID was not changed).
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.