Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Race condition in the Solana Wormhole gateway program #767

Open
lukasz-zimnoch opened this issue Jan 12, 2024 · 1 comment
Open

Race condition in the Solana Wormhole gateway program #767

lukasz-zimnoch opened this issue Jan 12, 2024 · 1 comment
Labels
⛓️ solidity Solidity contracts

Comments

@lukasz-zimnoch
Copy link
Member

lukasz-zimnoch commented Jan 12, 2024

Issue discovered by Karl and Kevin from the Wormhole team:

Sending tbtc can hit a race condition due to the way the Wormhole message account is derived. To bypass transaction simulation, see this failed transaction.

The core_message account's derivation depends on the wormhole gateway's emitter sequence account data. Every time wormhole publishes a message, it upticks this sequence. But because the sequence is used to derive this pubkey, there can be two folks trying to invoke the send_tbtc instruction, and only one of those guys will succeed.

For example, if Kevin and I both want to send tbtc, we both fetch the emitter sequence account to fetch the latest sequence number to drive the message PDA address. We both see 2 as the value. When we both send our transactions, either Kevin's transaction or my transaction may land first. If Kevin's lands first, mine will fail because the program during runtime will be trying to derive the message account using the value 3 instead of 2

What this means is there can be only one send_tbtc instruction per slot (unless someone can anticipate that his transaction lands after someone else's in the same slot, using sequence + 1 for his derivation... but that is unlikely)

There should be a new instruction that executes almost exactly the same way as send_tbtc (maybe call it send_tbtc_v2?) but the message account either uses a keypair generated off-chain or uses a PDA determined by another account called something like Payer Sequence, which uses a sequence number per transaction payer.
The latter way is safe to use because the payer is always tied to the transaction (lamports are sent from the payer to pay for the wormhole message fee, allocate accounts etc). So using web3, we can fetch this sequence reliably to derive the message PDA address

Using this type of account would solve the issue in a new instruction: link

The core message would then be derived this way: link

@lukasz-zimnoch lukasz-zimnoch added the ⛓️ solidity Solidity contracts label Jan 12, 2024
@erdogan
Copy link
Collaborator

erdogan commented Jan 12, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⛓️ solidity Solidity contracts
Projects
None yet
Development

No branches or pull requests

2 participants