Crazy Chocolate Lobster
Medium
ChainId is hardcoded in the calculation of the DOMAIN_SEPARATOR
within the constructor, which can enable replay attacks in case of a hard fork.
In both VVVVCInvestmentLedger.sol
and VVVVCTokenDistributor.sol
, the chainId
used to calculate the DOMAIN_SEPARATOR
for EIP712 is set in the constructor, making it hardcoded. This poses a risk in the event of a hard fork, as the DOMAIN_SEPARATOR
value would become invalid. If the chainId
remains the same after a hard fork, it could lead to incorrect behavior and potential replay attacks.
We'll use VVVVCTokenDistributor.sol
to illustrate the issue, but the same concern applies to VVVVCInvestmentLedger.sol
.
The constructor is implemented as follows:
constructor(
address _signer,
string memory _environmentTag,
address _authorizationRegistryAddress,
uint256 _exchangeRateDenominator
) VVVAuthorizationRegistryChecker(_authorizationRegistryAddress) {
signer = _signer;
exchangeRateDenominator = _exchangeRateDenominator;
// EIP-712 domain separator
DOMAIN_SEPARATOR = keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(abi.encodePacked("VVV", _environmentTag)),
@> block.chainid,
address(this)
)
);
}
-
As we can see the
chainId
is derived and then hardcoded inDOMAIN_SEPARATOR
. -
This means even after hard fork,
DOMAIN_SEPARATOR
value will remain same and point to incorrectchainId
.
An attacker could exploit this vulnerability to perform replay attacks, such as calling claim()
in both chains.
According to the protocol specifications, it will be deployed across 6 different chains, increasing the potential impact of this issue.
Eth, base, bnb, avalanche, polkadot, arbitrum
This heightens the risk that a hard fork could enable replay attacks.
None.
Chain hard fork.
- A chain undergoes a hard fork.
- An attacker exploits the fork by executing a replay attack across chains calling
claim()
. - The attacker claims rewards twice: once on the main chain and again on the forked chain.
A hard fork would enable the possibility of replay attacks.
The preceding sections demonstrated this issue.
To resolve this issue, the DOMAIN_SEPARATOR
should be dynamically recomputed using the current chainId
value each time.