Steadefi

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

Missing access control logic check for the `deposit` function

Summary

Contract allows anyone to deposit assets into the contract without any access restrictions. Access control is not properly implemented, potentially enabling unauthorized users to interact with the contract's deposit functionality.

Vulnerability Details

The vulnerable function is deposit, which allows users to deposit assets into the contract without checking their permissions. The lack of access control makes the contract susceptible to unauthorized deposits.

function deposit(
GMXTypes.Store storage self,
GMXTypes.DepositParams memory dp,
bool isNative
) external {
// Sweep any tokenA/B in vault to the temporary trove for future compouding and to prevent
// it from being considered as part of depositor's assets
if (self.tokenA.balanceOf(address(this)) > 0) {
self.tokenA.safeTransfer(self.trove, self.tokenA.balanceOf(address(this)));
}
if (self.tokenB.balanceOf(address(this)) > 0) {
self.tokenB.safeTransfer(self.trove, self.tokenB.balanceOf(address(this)));
}
self.refundee = payable(msg.sender);
GMXTypes.HealthParams memory _hp;
_hp.equityBefore = GMXReader.equityValue(self);
_hp.lpAmtBefore = GMXReader.lpAmt(self);
_hp.debtRatioBefore = GMXReader.debtRatio(self);
_hp.deltaBefore = GMXReader.delta(self);
// Transfer assets from user to vault
if (isNative) {
GMXChecks.beforeNativeDepositChecks(self, dp);
self.WNT.deposit{ value: dp.amt }();
} else {
IERC20(dp.token).safeTransferFrom(msg.sender, address(this), dp.amt);
}
GMXTypes.DepositCache memory _dc;
_dc.user = payable(msg.sender);
if (dp.token == address(self.lpToken)) {
// If LP token deposited
_dc.depositValue = self.gmxOracle.getLpTokenValue(
address(self.lpToken),
address(self.tokenA),
address(self.tokenA),
address(self.tokenB),
false,
false
)
* dp.amt
/ SAFE_MULTIPLIER;
} else {
// If tokenA or tokenB deposited
_dc.depositValue = GMXReader.convertToUsdValue(
self,
address(dp.token),
dp.amt
);
}
_dc.depositParams = dp;
_dc.healthParams = _hp;
self.depositCache = _dc;
GMXChecks.beforeDepositChecks(self, _dc.depositValue);
self.status = GMXTypes.Status.Deposit;
self.vault.mintFee();
// Borrow assets and create deposit in GMX
(
uint256 _borrowTokenAAmt,
uint256 _borrowTokenBAmt
) = GMXManager.calcBorrow(self, _dc.depositValue);
_dc.borrowParams.borrowTokenAAmt = _borrowTokenAAmt;
_dc.borrowParams.borrowTokenBAmt = _borrowTokenBAmt;
GMXManager.borrow(self, _borrowTokenAAmt, _borrowTokenBAmt);
GMXTypes.AddLiquidityParams memory _alp;
_alp.tokenAAmt = self.tokenA.balanceOf(address(this));
_alp.tokenBAmt = self.tokenB.balanceOf(address(this));
_alp.minMarketTokenAmt = GMXManager.calcMinMarketSlippageAmt(
self,
_dc.depositValue,
dp.slippage
);
_alp.executionFee = dp.executionFee;
_dc.depositKey = GMXManager.addLiquidity(
self,
_alp
);
self.depositCache = _dc;
emit DepositCreated(
_dc.user,
_dc.depositParams.token,
_dc.depositParams.amt
);
}

Impact

Unauthorized users can deposit assets, potentially causing unexpected interactions or disruptions in the system. This lack of control could lead to unintended deposits, potentially affecting the contract's state and stability.

Tools Used

Manual

Recommendations

Implement proper access control by using modifiers to ensure that only authorized users can call the deposit function. Below is an example of how to add an onlyController modifier to restrict access to authorized controllers:

modifier onlyController() {
require(msg.sender == self.controller, "Unauthorized access");
_;
}
function deposit(
GMXTypes.Store storage self,
GMXTypes.DepositParams memory dp,
bool isNative
) external onlyController {
// Function logic with proper access control
require(self.controller != address(0), "Controller address is not set"); // Ensure the controller address is set
// Additional checks and logic can be added here
// Sweep any tokenA/B in vault to the temporary trove for future compounding
if (self.tokenA.balanceOf(address(this)) > 0) {
self.tokenA.safeTransfer(self.trove, self.tokenA.balanceOf(address(this)));
}
if (self.tokenB.balanceOf(address(this)) > 0) {
self.tokenB.safeTransfer(self.trove, self.tokenB.balanceOf(address(this)));
}
self.refundee = payable(msg.sender);
GMXTypes.HealthParams memory _hp;
_hp.equityBefore = GMXReader.equityValue(self);
_hp.lpAmtBefore = GMXReader.lpAmt(self);
_hp.debtRatioBefore = GMXReader.debtRatio(self);
_hp.deltaBefore = GMXReader.delta(self);
// Transfer assets from the user to the vault
if (isNative) {
GMXChecks.beforeNativeDepositChecks(self, dp);
self.WNT.deposit{ value: dp.amt }();
} else {
IERC20(dp.token).safeTransferFrom(msg.sender, address(this), dp.amt);
}
GMXTypes.DepositCache memory _dc;
_dc.user = payable(msg.sender);
if (dp.token == address(self.lpToken)) {
// If LP token is deposited
_dc.depositValue = self.gmxOracle.getLpTokenValue(
address(self.lpToken),
address(self.tokenA),
address(self.tokenA),
address(self.tokenB),
false,
false
) * dp.amt / SAFE_MULTIPLIER;
} else {
// If tokenA or tokenB is deposited
_dc.depositValue = GMXReader.convertToUsdValue(self, address(dp.token), dp.amt);
}
_dc.depositParams = dp;
_dc.healthParams = _hp;
self.depositCache = _dc;
GMXChecks.beforeDepositChecks(self, _dc.depositValue);
self.status = GMXTypes.Status.Deposit;
self.vault.mintFee();
// Borrow assets and create a deposit in GMX
(uint256 _borrowTokenAAmt, uint256 _borrowTokenBAmt) = GMXManager.calcBorrow(self, _dc.depositValue);
_dc.borrowParams.borrowTokenAAmt = _borrowTokenAAmt;
_dc.borrowParams.borrowTokenBAmt = _borrowTokenBAmt;
GMXManager.borrow(self, _borrowTokenAAmt, _borrowTokenBAmt);
GMXTypes.AddLiquidityParams memory _alp;
_alp.tokenAAmt = self.tokenA.balanceOf(address(this));
_alp.tokenBAmt = self.tokenB.balanceOf(address(this));
_alp.minMarketTokenAmt = GMXManager.calcMinMarketSlippageAmt(self, _dc.depositValue, dp.slippage);
_alp.executionFee = dp.executionFee;
_dc.depositKey = GMXManager.addLiquidity(self, _alp);
self.depositCache = _dc;
emit DepositCreated(_dc.user, _dc.depositParams.token, _dc.depositParams.amt);
}
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.