stake.link

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

Inconsistency in transfering SDL lock from primary to secondary

Summary

When transferRing RESDL from mainnet to Arbitrum for example, SDL erc20 tokens are not subtracted from controller's effective balance as in the opposite flow - when transferring from Arbitrum to mainnet

Vulnerability Details

The flow is the following.

  1. End user calls transferRESDL on RESDLTokenBridge deployed on Arbitrum for example

  2. The bridge calls SDLCCIPControllerSecondary.handleOutGoingRESDL with _sender being msg.sender

  3. The secondary controller then calls handleOutgoingRESDL on the secondary pool with _sdlReceiver being the secondary controller

function handleOutgoingRESDL(
uint64,
address _sender,
uint256 _tokenId
) external override onlyBridge returns (address, ISDLPool.RESDLToken memory) {
return (primaryChainDestination, ISDLPoolSecondary(sdlPool).handleOutgoingRESDL(_sender, _tokenId, address(this))); @audit //address(this) meaning the address of the secondary controller
}
  1. The handleOutgoingRESDL on the secondary pool calculates lock.amount + lock.boostAmount and subtracts them from effectiveBalances[_sender] and totalEffectiveBalance.

  2. Then SDL tokens are transferred to the secondary controller

  3. Then the RESDLTokenBridge deployed on mainnet is invoked with ccipReceive from the primary controller

  4. handleIncomingRESDL is called on the primary controller

  5. The primary controller transfers the RESDLToken.amount to the primary pool and subtracts the amount + boost from the Arbitrum sdl supply

  6. handleIncomingRESDL on primary pool then increments effectiveBalances[_receiver] with amount + boost and this same amount gets subtracted from the secondary controller.

Now lets reverse this scenario meaning we are transferring from mainnet to Arbitrum so:

  1. transferRESDL on RESDLTokenBridge deployed on mainnet is called

  2. The bridge calls SDLCCIPControllerPrimary.handleOutGoingRESDL with _sender being msg.sender

  3. The primary controller then calls handleOutgoingRESDL on the primary pool with _sdlReceiver being the primary controller

  4. The handleOutgoingRESDL on the primary pool calculates lock.amount + lock.boostAmount and subtracts them from effectiveBalances[_sender] and adds them to the effectiveBalances[ccipController] (the primary controller)

  5. Then SDL tokens are transferred to the primary controller

  6. Then the RESDLTokenBridge deployed on Arbitrum is invoked with ccipReceive from the secondary controller

  7. handleIncomingRESDL is called on the secondary controller

  8. The secondary controller transfers the RESDLToken.amount to the secondary pool and adds amount + boost to effectiveBalances[_receiver] and to totalEffectiveBalance += totalAmount

  9. But here is the difference, the tokens are not subtracted from the effective balance of the controller, so they exist in the same time in the effective balance of the controller and in the effective balance of the _receiver

Impact

This inconsistency could lead to discrepancies in effective balance calculations, affecting reward distributions, staking calculations, or other functionalities dependent on the accurate accounting of effective balances.

Tools Used

Manual Review

Recommendations

In the scenario where RESDL lock is transferred from mainnet to a secondary chain, when the secondary controller transfers the lock.amount to the secondary pool subtract the amount + boost from the effective balance of the controller.

Updates

Lead Judging Commences

0kage Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
0kage Lead Judge
over 1 year ago
0kage Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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