During an outgoing update from Secondary pool to the primary pool, no other update can take place until the primary pool returns the mintStartIndex
. If the transaction on the primary chain reverts, the secondary pool will be set in a deadlock situation.
Actions on the secondary pool such as staking, locking, withdrawing, or initiating a withdrawal do not take effect immediately, they get queued and sent periodically to the primary pool to keep accounting consistent between primary and secondary pools. Chainlink bots call performUpkeep on SDLPoolCCIPControllerSecondary
to initiate updates from secondary to primary chain.
One crucial thing happens in the handleOutgoingUpdate is that updateInProgress
flag is set to 1
whenever a new update is sent to primary chain, and no more updates can be sent until the current in-progress update is resolved:
On the primary chain, the SDLPoolCCIPControllerPrimary
receives the message and verifies that the sender, then calls handleIncomingUpdates
in the SDLPoolPrimary, which calculates the mintStartIndex
. This index is then sent back to the secondary chain by the SDLPoolCCIPControllerPrimary
in another cross-chain transaction.
The secondary pool is expecting an update from the primary pool to know the _mintStartIndex
via handleIncomingUpdate in which updateInProgress
is set 0
, finalizing the update in progress:
The issue is if the callback transaction that sends mintStartIndex
from primary to secondary chain reverts for whatever reason (not enough LINK token to pay for the gas, etc), this will lead to not triggering the function handleIncomingUpdate
on the Secondary pool, thus not finalizing the update in-progress, making the SDLPoolSecondary
in a dead lock situation where no further updates can be sent. There is no recovery mechanism to send back updates from the primary pool to the secondary pool if such situation happens as sending updates from the primary pool to the secondary pool is ONLY made when an update from the secondary pool comes.
Consider the following example:
There are several queued updates on SDLPoolSecondary
Chainlink Bots initiate updates from the Secondary pool to the primary pool by calling performUpKeep
handleOutgoingUpdate
is triggered on SDLPoolSecondary
and updateInProgress
flag is set to 1
updates are sent from the secondary pool to the primary pool via cross-chain communication using CCIP.
SDLPoolCCIPControllerPrimary
receives the incoming update, _ccipReceive
is triggered:
It calculates the mintStartIndex
and sends back an update to the secondary pool via a cross-chain communication using CCIP by invoking _ccipSendUpdate
The last transaction reverts for whatever reason (not enough LINK token to pay for gas, etc.)
SDLPoolSecondary
is still waiting for an update from the primary pool (which is reverted). Thus, handleIncomingUpdate
will never be triggered, keeping the updateInProgress
flag to 1
forever
There is no mechanism in SDLPoolPrimary/SDLPoolCCIPControllerPrimary
to re-send the updates to the secondary pool
The SDLPoolSecondary
is now in a deadlock situation as no further updates can be handled.
This issue will put the SDLPoolSecondary
pool in a deadlock situation putting users' actions in limbo.
Manual Review
Consider implementing a recovery mechanism that will re-send updates from the primary pool to the secondary pool if needed.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.