Risk of reuse of signatures across forks due to lack of chain ID validation
Summary
The permit function in the GSPVault contract implements EIP-2612 functionality, allowing users to modify the allowance mapping using a signed message rather than relying solely on the msg.sender. However, the way it handles the chainID presents a potential security vulnerability.
Vulnerability Detail
The chainID is included in the DOMAIN_SEPARATOR. And it is only initialized once and cannot be reinitialized, so the chainID remains fixed.
However, In the event of a post-deployment hard fork of the chain, the chain ID cannot be updated, and signatures may be replayed across both versions of the chain.
Impact
This can lead to signature reuse attack. Here is an exploit scenario :
Bob holds tokens worth $1,000 on the mainnet. Bob submits a signature to permit Eve to spend those tokens on his behalf. Later, the mainnet is hard-forked and retains the same chain ID. As a result, there are two parallel chains with the same chain ID, and Eve can use Bob’s signature to transfer funds on both chains.
Either compute the DOMAIN_SEPARATOR with the latest chainID each time permit is called.
Like Openzeppelin, compute the DOMAIN_SEPARATOR and cache the chainID at the time of initialization. On each permit call, check if chainID != cachedChainID, then recompute the DOMAIN_SEPARATOR.
PranavGarg
medium
Risk of reuse of signatures across forks due to lack of chain ID validation
Summary
The
permit
function in the GSPVault contract implements EIP-2612 functionality, allowing users to modify the allowance mapping using a signed message rather than relying solely on the msg.sender. However, the way it handles the chainID presents a potential security vulnerability.Vulnerability Detail
The chainID is included in the
DOMAIN_SEPARATOR
. And it is only initialized once and cannot be reinitialized, so the chainID remains fixed.GSP.sol https://github.com/sherlock-audit/2023-12-dodo-gsp/blob/main/dodo-gassaving-pool/contracts/GasSavingPool/impl/GSP.sol#L80-L96
However, In the event of a post-deployment hard fork of the chain, the chain ID cannot be updated, and signatures may be replayed across both versions of the chain.
Impact
This can lead to signature reuse attack. Here is an exploit scenario : Bob holds tokens worth $1,000 on the mainnet. Bob submits a signature to permit Eve to spend those tokens on his behalf. Later, the mainnet is hard-forked and retains the same chain ID. As a result, there are two parallel chains with the same chain ID, and Eve can use Bob’s signature to transfer funds on both chains.
Code Snippet
https://github.com/sherlock-audit/2023-12-dodo-gsp/blob/main/dodo-gassaving-pool/contracts/GasSavingPool/impl/GSPVault.sol#L311-L346
https://github.com/sherlock-audit/2023-12-dodo-gsp/blob/main/dodo-gassaving-pool/contracts/GasSavingPool/impl/GSP.sol#L80-L96
Tool used
Manual Review
Recommendation
Possible solutions :
DOMAIN_SEPARATOR
with the latest chainID each timepermit
is called.DOMAIN_SEPARATOR
and cache the chainID at the time of initialization. On eachpermit
call, check if chainID != cachedChainID, then recompute theDOMAIN_SEPARATOR
.Duplicate of #113