Powerful Honeysuckle Anteater
Medium
For CDS withdraw we don't link a signature to a specific address, which leads to nonce not being able to be distinguished
When doing a CDS withdraw we perform signature verification in CDS.sol in verify(), however, there isn't an address that's passed in, so anyone could use signatures from anyone else and potentially get better excessProfitCumulativeValue.
Not having an address linked to a signature, will result in DoS due to signature frontrunning. Also, anyone could use the signatures of others, which have better excessProfitCumulativeValue.
Reference CDS.sol#L878-L916
function _verify(FunctionName functionName, uint256 excessProfitCumulativeValue, uint256 nonce, bytes memory odosExecutionData, bytes memory signature) private view returns (bool) {
bytes32 digest;
if (functionName == FunctionName.CDS_WITHDRAW) {
digest = _hashTypedDataV4(
keccak256(
abi.encode(
keccak256(
"Permit(uint256 excessProfitCumulativeValue,uint256 nonce)"
),
excessProfitCumulativeValue,
@>> nonce // We only pass nonce
)
)
);
} else if (functionName == FunctionName.BORROW_WITHDRAW) {
....
}
address signer = ECDSA.recover(digest, signature);
bytes32 hashedSigner = keccak256(abi.encodePacked(signer));
if (hashedSigner == hashedAdminTwo) {
return true;
} else {
return false;
}
}- User A intends to make a withdrawal.
- User B can front-run User A by capturing their signature and withdrawing User A's position. This would result in a revert, as nonce checks would fail. (It should be noted that currently nonces are not checked, which is a separate issue, and fixing that would not resolve this issue due to a different root cause.)
uint256 currentValue = cdsAmountToReturn(
msg.sender,
index,
omniChainData.cumulativeValue,
omniChainData.cumulativeValueSign,
@>> excessProfitCumulativeValue
) - 1;- Adversary can front-run Users and DoS their ability to withdraw.
- Adversary could get a better excessProfitCumulativeValue from another user, by frontrunning it.
Pass an address and verify it in the signature.