Mythical Flaxen Hamster
High
The VVVVCInvestmentLedger
contract relies on off-chain signed exchange rates that remain static during the signature validity window, creating potential arbitrage opportunities during significant price movements of the payment token.
The exchange rate mechanism in invest()
uses a fixed exchangeRateNumerator
that's signed off-chain and remains valid until the deadline:
uint256 preFeeStableAmountEquivalent = (_params.amountToInvest * _params.exchangeRateNumerator) /
exchangeRateDenominator;
- Valid investment parameters signed by authorized signer
- Investment round is active
- User has sufficient payment tokens
- Significant price movement of payment token occurs between signature issuance and execution
- Market conditions allow for profitable arbitrage
- Attacker obtains signed investment parameters with fixed
exchangeRateNumerator
- Monitors payment token for price movements
- When price drops significantly:
function invest(InvestParams memory _params) external {
// Price check absent here
uint256 preFeeStableAmountEquivalent = (_params.amountToInvest * _params.exchangeRateNumerator) /
exchangeRateDenominator;
// Execute investment at old rate
}
- Executes investment using devalued tokens at the original higher exchange rate
- Project receives fewer dollars worth of investment than intended
- Creates unfair advantage over fiat investors
- Particularly risky with volatile tokens or during market stress
Implement on-chain price oracle integration:
interface IPriceOracle {
function getExchangeRate(address token) external view returns (uint256);
}
function invest(InvestParams memory _params) external {
uint256 currentRate = oracle.getExchangeRate(_params.paymentTokenAddress);
require(
currentRate >= _params.exchangeRateNumerator * 95 / 100,
"Price deviation too high"
);
// Continue with investment
}