# IMarket.execute.selector, _checkSender bypass allows to execute arbitrary operations

Magnetar's _checkSender decodes calldata length as owner address, letting attacker forge calldata to execute arbitrary market operations and steal approved tokens.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: GalloDaSballo
- Disclosed: 2024-05-23
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2024-02-tapioca-findings/issues/77
- Library page: https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AH-08
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** Magnetar.sol _processMarketOperation / IMarket.execute
**Root cause:** The owner check decodes _actionCalldata[4:36] as an address, but for a dynamic calldata argument those bytes are the array length, not the owner; the length can be chosen to equal msg.sender.
**Steps:**
1. Call Magnetar._processMarketOperation with _actionCalldata whose selector is IMarket.execute.selector
2. Craft calldata so bytes 4:36 (the modules array length) equal an address you control or a low system address like Optimism Portal
3. Ensure msg.sender matches that decoded length value
4. Pass arbitrary modules/calls to execute market operations with victim allowances
**How found:** Code reading of _processMarketOperation: noticed abi.decode(_actionCalldata[4:36], (address)) on a dynamic calldata argument actually reads the array length, not the owner param.
**Exploitation:** Attacker mines or selects a low address matching the forged calldata length (or uses a system contract like Optimism Portal), bypasses _checkSender, and has Magnetar execute market operations transferring tokens approved to Magnetar.
**Escalation:** Using low system addresses (Optimism Portal) makes the attack cost-free; Arbitrum has no block gas limit aiding mining.
**Insight:** When a contract decodes a fixed calldata offset as an address for an authorization check, verify whether that offset is actually a dynamic-type length field; forge the length to match msg.sender.
