#36501 [SC-Medium] Signature Front-Running Vulnerability in CollateralVault
Submitted on Nov 4th 2024 at 13:24:08 UTC by @Hoverfly9132 for Audit Comp | Anvil
Report ID: #36501
Report Type: Smart Contract
Report severity: Medium
Target: https://etherscan.io/address/0x5d2725fdE4d7Aa3388DA4519ac0449Cc031d675f
Impacts:
Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
Description
Bug Description
The similar issue has found by the previous OpenZeppelin audit but they don't specify all the affected actions, and anvil team only fix the `depositAndStake` function, the other affected actions aren't reported and fixed in the previous audits, so this issue shouldn't be considered as known issue from my perspective.
The `modifyCollateralizableTokenAllowanceWithSignature` function in CollateralVault is vulnerable to signature front-running attacks. When the `TimeBasedCollateralPool` contract `stake` and `stakeReleasableTokensFrom` functions call the `modifyCollateralizableTokenAllowanceWithSignature` function to modify the allowance by signature, an attacker can monitor the mempool and front-run the transaction by calling the `modifyCollateralizableTokenAllowanceWithSignature` function first, then the original transaction will fail because the nonce is already used.
The vulnerability exists because:
The signature verification uses a nonce system that increments upon each use.
The `modifyCollateralizableTokenAllowanceWithSignature` function can be called by anyone to cause the signature nonce to be incremented.
Once a signature is used and the nonce is incremented, the original transaction will fail
Impact
Any users `stake` or `stakeReleasableTokensFrom` txs can be front-run by attackers to revert.
Recommendation
Fix as the `depositAndStake` function.
Proof of Concept
Proof of Concept
```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.19;
import "forge-std/Test.sol";
abstract contract EIP712 { bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID;
}
abstract contract SignatureNonces { mapping(address => mapping(bytes32 => uint256)) private _accountTypeNonces;
}
contract CollateralVault is EIP712, SignatureNonces { bytes32 public constant COLLATERALIZABLE_TOKEN_ALLOWANCE_ADJUSTMENT_TYPEHASH = keccak256( "CollateralizableTokenAllowanceAdjustment(address collateralizableAddress,address tokenAddress,int256 allowanceAdjustment,uint256 approverNonce)" );
}
interface ICollateral { function modifyCollateralizableTokenAllowanceWithSignature( address _accountAddress, address _collateralizableContractAddress, address _tokenAddress, int256 _allowanceAdjustment, bytes calldata _signature ) external;
}
contract TimeBasedCollateralPool { ICollateral public immutable collateral; constructor(address _collateral) { collateral = ICollateral(_collateral); }
}
contract SignatureReplayTest is Test { CollateralVault public vault; address public victim; uint256 public victimPrivateKey; address public token; TimeBasedCollateralPool public pool;
} ```
Run the test by: ```bash forge test --match-test testFrontRunGriefing ```
Last updated
Was this helpful?