stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: medium
Invalid

SDLPoolPrimary.sol::Parralel data structure

Summary

Parralel data structure was present in https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/sdlPool/base/SDLPool.sol which was later used in https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/sdlPool/SDLPoolPrimary.sol contract's withdraw(), handleOutgoingRESDL(), handleIncomingRESDL() & _storeNewLock(). We can simply remove 2 mappings and modify another mapping to get expected results.

Vulnerability Details

As you can see, a struct was present here: https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/sdlPool/base/SDLPool.sol#L18. Later two mapping was written here: https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/base/SDLPool.sol#L36C1-L36C1 and here: https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/base/SDLPool.sol#L38

The struct looks like:

struct Lock {
uint256 amount;
uint256 boostAmount;
uint64 startTime;
uint64 duration;
uint64 expiry;
}

and mappings are:

mapping(uint256 => Lock) internal locks;

and

mapping(address => uint256) internal balances;

The locks mapping is set lockId to Lock struct. But this is redundant, we can simply add a variant named lockId in the struct.
Same for balances mapping, this mapping sets how many locks a user has, this balances also can be be added as a variant in struct.
So struct should look like:

struct Lock {
uint256 lockId,
uint256 balances,
uint256 amount;
uint256 boostAmount;
uint64 startTime;
uint64 duration;
uint64 expiry;
}

Now we simply have to replace another mapping: mapping(uint256 => address) internal lockOwners; with mapping(address => Lock) internal ownerToLock or with any better name. Now we can update the Lock struct using the owner's address as key.

Impact

Data Consistency: Maintaining data consistency across parallel data structures can be challenging. If one data structure is updated and another is not, it can lead to inconsistencies in the state of the contract.

Gas Costs: Each additional data structure increases the gas cost for transactions. This is because each operation (read, write, update) on a data structure consumes a certain amount of gas. Therefore, the more data structures you have, the more gas you will consume.

Tools Used

Manual analysis

Recommendations

Use this struct structure:

struct Lock {
uint256 lockId,
uint256 balances,
uint256 amount;
uint256 boostAmount;
uint64 startTime;
uint64 duration;
uint64 expiry;
}

and remove these 2 mappings :

mapping(uint256 => Lock) internal locks;
mapping(address => uint256) internal balances;

and replace the mapping(uint256 => address) internal lockOwners; with mapping(address => Lock) internal ownerToLock
and update contracts according to it.

Updates

Lead Judging Commences

0kage Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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