Poor logic in domainSeparator#
Informational
In Minting.sol there is _domainSeparatorV4 function used to get the domain separator, needed for signature verification. On line 71 there is a check that ds.contractInfo.canvasAddress equals ds._CACHED_THIS and block.chainid equals ds._CACHED_CHAIN_ID. If it is true, _CACHED_DOMAIN_SEPARATOR is returned. However, the if statement will always be true because ds._CACHED_THIS and ds._CACHED_CHAIN_ID are set to exactly those values in the initialize function and are never changed. In case that the result would somehow be false, the other line of code that would be executed would not work either, because it needs ds._TYPE_HASH, ds._HASHED_NAME and ds._HASHED_VERSION, which are only set in the initialize function as well. So you are counting on the contract being initialized in both cases. This means that if one option works, the other does as well, and if one does not work, the other does not either. We can see the constructor in Canvas.sol executes the initialize function, so we can be sure that all the needed values are set. Therefore, _CACHED_DOMAIN_SEPARATOR can be returned and there is no need for the if statement.
Recommendation#
Consider removing the if statement in _domainSeparatorV4 and just return ds._CACHED_DOMAIN_SEPARATOR.
Only store the _CACHED_DOMAIN_SEPARATOR variable and remove other variables, because they are not needed.