Steadefi

Steadefi
DeFiHardhatFoundryOracle
35,000 USDC
View results
Submission Details
Severity: medium
Invalid

Missing access control checks in the getAmountsOut function

Summary

The GMXOracle contract lacks proper access control, allowing any address to interact with its functions without authorization. This vulnerability can potentially lead to unauthorized and malicious operations.

Vulnerability Details

The GMXOracle contract does not implement access control mechanisms, making all functions publicly accessible. As a result, any address, including potential attackers, can call these functions without proper authorization.

The missing access control vulnerability can be found in the getAmountsOut function within the GMXOracle contract. Below is the vulnerable function:

/**
* @notice Get amountsOut of either the long or short token based on the amountsIn
* of either long or short token in the market
* @param marketToken LP token address
* @param indexToken Index token address
* @param longToken Long token address
* @param shortToken Short token address
* @param tokenIn TokenIn address
* @param amountIn Amount of tokenIn, expressed in tokenIn's decimals
* @return amountsOut Amount of tokenOut within LP (market) to be received, expressed in tokenOut's decimals
*/
function getAmountsOut(
address marketToken,
address indexToken,
address longToken,
address shortToken,
address tokenIn,
uint256 amountIn
) public view returns (uint256) {
ISyntheticReader.MarketProps memory _market;
_market.marketToken = marketToken;
_market.indexToken = indexToken;
_market.longToken = longToken;
_market.shortToken = shortToken;
ISyntheticReader.PriceProps memory _indexTokenPrice;
_indexTokenPrice.min = _getTokenPriceMinMaxFormatted(indexToken);
_indexTokenPrice.max = _getTokenPriceMinMaxFormatted(indexToken);
ISyntheticReader.PriceProps memory _longTokenPrice;
_longTokenPrice.min = _getTokenPriceMinMaxFormatted(longToken);
_longTokenPrice.max = _getTokenPriceMinMaxFormatted(longToken);
ISyntheticReader.PriceProps memory _shortTokenPrice;
_shortTokenPrice.min = _getTokenPriceMinMaxFormatted(shortToken);
_shortTokenPrice.max = _getTokenPriceMinMaxFormatted(shortToken);
ISyntheticReader.MarketPrices memory _prices;
_prices.indexTokenPrice = _indexTokenPrice;
_prices.longTokenPrice = _longTokenPrice;
_prices.shortTokenPrice = _shortTokenPrice;
address _uiFeeReceiver = address(0);
(uint256 _amountsOut,,) = syntheticReader.getSwapAmountOut(
dataStore,
_market,
_prices,
tokenIn,
amountIn,
_uiFeeReceiver
);
return _amountsOut;
}

The getAmountsOut function, being publicly accessible, is vulnerable to misuse by unauthorized users who can call this function with arbitrary parameters, potentially affecting the contract's behavior. This function should have proper access control to restrict its usage to authorized addresses.

Impact

An attacker can exploit the absence of access control to call functions intended only for authorized users. In the following example, the attacker calls the getAmountsOut function with a malicious value:

In this scenario, the attacker can execute the getAmountsOut function with arbitrary parameters, potentially affecting the contract's behavior.

It allows unauthorized users to interact with the contract's functions without restriction. This can lead to various potential malicious activities, including manipulating token prices, creating inaccurate market data, or affecting the contract's intended behavior.

Tools Used

Manual

Recommendations

Access control mechanisms should be implemented to restrict the usage of critical functions to authorized addresses. You can use OpenZeppelin's Access Control smart contracts to manage roles and permissions within your contract. Below is an example of how you can apply access control using OpenZeppelin's Access Control library:

  • Import the AccessControl contract from OpenZeppelin:

import "@openzeppelin/contracts/access/AccessControl.sol";
  • Inherit the AccessControl contract in your GMXOracle contract:

contract GMXOracle is AccessControl {
// Define roles and grant access to specific functions
bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");
constructor() {
_setupRole(ORACLE_ROLE, msg.sender); // Assign the ORACLE_ROLE to the contract deployer
}
// Ensure that only addresses with the ORACLE_ROLE can access certain functions
modifier onlyOracle() {
require(hasRole(ORACLE_ROLE, msg.sender), "Not authorized");
_;
}
// Sample function with access control
function someFunction() public onlyOracle {
// Function logic for authorized users
}
}
Updates

Lead Judging Commences

hans Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.