Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Invalid

The `InheritanceManager::contractInteractions` Function Overwrites Interaction Data, Leading to Loss of Critical Audit Trail

Summary

The contractInteractions function within the InheritanceManager contract is vulnerable to data overwrites in the interactions mapping. If the owner interacts with the same external contract multiple times using contractInteractions and sets _storeTarget to true, the previous interaction data will be overwritten. This leads to the potential loss of information about previous interactions, hindering the contract's ability to maintain a complete audit trail.


Vulnerability Details

https://github.com/CodeHawks-Contests/2025-03-inheritable-smart-contract-wallet/blob/main/src/InheritanceManager.sol#L120-L130

1. Overview

The contractInteractions function allows the owner to make arbitrary calls to external contracts. When the _storeTarget parameter is set to true, the function stores the return data from the external contract call in the interactions mapping, keyed by the target contract's address.

The issue lies in how the interactions mapping is updated. The code simply assigns the new data to the target's address, overwriting any previously stored data:

function contractInteractions(
address _target,
bytes calldata _payload,
uint256 _value,
bool _storeTarget
) external nonReentrant onlyOwner {
(bool success, bytes memory data) = _target.call{value: _value}(_payload);
require(success, "Interaction Failed");
if (_storeTarget) {
@> interactions[_target] = data; // @audit-issue Will override previous data
}
}

This logic has the following limitations:

  • No Appending Mechanism: New data overwrites existing data, making it impossible to append to or preserve previous interactions. Multiple interactions with the same contract cannot be distinguished or tracked.

  • No History Tracking: Beneficiaries can only access the most recent interaction with a specific external contract, losing all prior interaction history.


Impact

1. Loss of Audit Trail

  • Beneficiaries may need a complete history of the owner's interactions with external contracts to fully understand the state of the wallet. Overwriting data destroys this audit trail.

2. Difficulty in Reclaiming Funds

  • If the owner has deposited assets in multiple places on the same platform (e.g., multiple pools on Aave), beneficiaries might only be able to identify the most recent deposit. This makes it harder for them to locate and reclaim all assets upon inheritance.


Tools Used

  • Manual Code Review


Recommendations

Use a List or Array for Interactions

Instead of directly storing data in the interactions mapping, consider using a data structure that can hold multiple entries per target contract. For example:

Array of Structs

  • Use a struct to hold information about each interaction (e.g., timestamp, function called, data returned).

struct Interaction {
uint256 timestamp;
bytes data;
bytes4 selector; // Add function selector for better audit
bytes encodedPayload; // Add the calldata to recreate the call
}
mapping(address => Interaction[]) public interactions;
address[] public interactionTargets; // Keep track of interactions target
function contractInteractions(
address _target,
bytes calldata _payload,
uint256 _value,
bool _storeTarget
) external nonReentrant onlyOwner {
(bool success, bytes memory data) = _target.call{value: _value}(_payload);
require(success, "Interaction Failed");
if (_storeTarget) {
interactions[_target].push(Interaction(
block.timestamp,
data,
_payload.length >= 4 ? bytes4(_payload[0:4]) : bytes4(0),
_payload
)); // Store the timestamp with the data
if(interactions[_target].length == 0) {
interactionTargets.push(_target);
}
}
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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