solidity.security.balancer-readonly-reentrancy-getrate.balancer-readonly-reentrancy-getrate
semgrep
Author
unknown
Download Count*
License
$VAR.getRate() call on a Balancer pool is not protected from the read-only reentrancy.
Run Locally
Run in CI
Defintion
rules:
- id: balancer-readonly-reentrancy-getrate
message: $VAR.getRate() call on a Balancer pool is not protected from the
read-only reentrancy.
metadata:
category: security
technology:
- solidity
cwe: "CWE-841: Improper Enforcement of Behavioral Workflow"
confidence: HIGH
likelihood: MEDIUM
impact: HIGH
subcategory:
- vuln
references:
- https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Other
patterns:
- pattern: |
function $F(...) {
...
$VAR.getRate();
...
}
- pattern-not-inside: |
function $F(...) {
...
VaultReentrancyLib.ensureNotInVaultContext(...);
...
}
- pattern-not-inside: |
function $F(...) {
...
$VAULT.manageUserBalance(...);
...
}
- pattern-not-inside: |
function _updateTokenRateCache(...) {
...
}
- pattern-not-inside: |
contract PoolRecoveryHelper {
...
}
- pattern-not-inside: |
contract ComposableStablePoolRates {
...
}
- pattern-not-inside: |
contract WeightedPoolProtocolFees {
...
}
- pattern-not-inside: |
contract $C {
...
function $CHECKFUNC(...) {
...
VaultReentrancyLib.ensureNotInVaultContext(...);
...
}
...
function $F(...) {
...
$CHECKFUNC(...);
...
$VAR.getRate();
...
}
...
}
- pattern-not-inside: |
contract $C {
...
function $CHECKFUNC(...) {
...
VaultReentrancyLib.ensureNotInVaultContext(...);
...
}
...
function $F(...) {
...
$VAR.getRate();
...
$CHECKFUNC(...);
...
}
...
}
- pattern-not-inside: |
contract $C {
...
function $CHECKFUNC(...) {
...
$VAULT.manageUserBalance(...);
...
}
...
function $F(...) {
...
$VAR.getRate();
...
$CHECKFUNC(...);
...
}
...
}
- pattern-not-inside: |
contract $C {
...
function $CHECKFUNC(...) {
...
$VAULT.manageUserBalance(...);
...
}
...
function $F(...) {
...
$CHECKFUNC(...);
...
$VAR.getRate();
...
}
...
}
- focus-metavariable: $VAR
languages:
- solidity
severity: ERROR
Examples
balancer-readonly-reentrancy-getrate.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract BALBBA3USDOracle is IOracle, IOracleValidate {
function _get() internal view returns (uint256) {
uint256 usdcLinearPoolPrice = _getLinearPoolPrice(BAL_BB_A3_USDC);
uint256 usdtLinearPoolPrice = _getLinearPoolPrice(BAL_BB_A3_USDT);
uint256 daiLinearPoolPrice = _getLinearPoolPrice(BAL_BB_A3_DAI);
uint256 minValue = Math.min(
Math.min(usdcLinearPoolPrice, usdtLinearPoolPrice),
daiLinearPoolPrice
);
// ruleid: balancer-readonly-reentrancy-getrate
return (BAL_BB_A3_USD.getRate() * minValue) / 1e18;
}
function check() internal view returns (uint256) {
VaultReentrancyLib.ensureNotInVaultContext(IVault(BALANCER_VAULT));
// ok: balancer-readonly-reentrancy-getrate
return (BAL_BB_A3_USD.getRate() * minValue) / 1e18;
}
}
contract PoolRecoveryHelper is SingletonAuthentication {
function _updateTokenRateCache(
uint256 index,
IRateProvider provider,
uint256 duration
) internal virtual {
// ok: balancer-readonly-reentrancy-getrate
uint256 rate = provider.getRate();
bytes32 cache = _tokenRateCaches[index];
_tokenRateCaches[index] = cache.updateRateAndDuration(rate, duration);
emit TokenRateCacheUpdated(index, rate);
}
}
contract TestA {
function checkReentrancy() {
VaultReentrancyLib.ensureNotInVaultContext(IVault(BALANCER_VAULT));
}
function test() internal view returns (uint256) {
checkReentrancy();
// ok: balancer-readonly-reentrancy-getrate
return (BAL_BB_A3_USD.getRate() * minValue) / 1e18;
}
function test2() internal view returns (uint256) {
// ruleid: balancer-readonly-reentrancy-getrate
return (BAL_BB_A3_USD.getRate() * minValue) / 1e18;
}
}
contract TestB {
function checkReentrancy() {
vault.manageUserBalance(new IVault.UserBalanceOp[](0));
}
function test() internal view returns (uint256) {
checkReentrancy();
// ok: balancer-readonly-reentrancy-getrate
return (BAL_BB_A3_USD.getRate() * minValue) / 1e18;
}
function test2() internal view returns (uint256) {
vault.manageUserBalance(new IVault.UserBalanceOp[](0));
// ok: balancer-readonly-reentrancy-getrate
return (BAL_BB_A3_USD.getRate() * minValue) / 1e18;
}
}
Short Link: https://sg.run/g9e5