Skip to content

feat(hermes-server): add option to allow reading the guardian set from ethereum#3399

Open
keyvankhademi wants to merge 8 commits intomainfrom
hermes-eth
Open

feat(hermes-server): add option to allow reading the guardian set from ethereum#3399
keyvankhademi wants to merge 8 commits intomainfrom
hermes-eth

Conversation

@keyvankhademi
Copy link
Contributor

Summary

This PR adds new config parameters to allow choosing pythnet or ethereum as a source for fetching the guardian set.

Rationale

After migrating from pythnet, it will shutdown and will no longer be usable for fetching the guardian set.

How has this been tested?

  • Current tests cover my changes
  • Added new tests
  • Manually tested the code

Manually tested the fetched guardian set to be identical to pythnet's.

@vercel
Copy link

vercel bot commented Jan 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
api-reference Ready Ready Preview, Comment Jan 20, 2026 10:42pm
component-library Ready Ready Preview, Comment Jan 20, 2026 10:42pm
developer-hub Ready Ready Preview, Comment Jan 20, 2026 10:42pm
entropy-explorer Ready Ready Preview, Comment Jan 20, 2026 10:42pm
insights Ready Ready Preview, Comment Jan 20, 2026 10:42pm
proposals Ready Ready Preview, Comment Jan 20, 2026 10:42pm
pyth-app Error Error Jan 20, 2026 10:42pm
staking Ready Ready Preview, Comment Jan 20, 2026 10:42pm

Request Review

Copy link
Collaborator

@ali-behjati ali-behjati left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have two concerns here, first is to whether we need to keep Pythnet or not? (i think we can get rid of it).

Second is around the ETH contract we stick to here. the reason is that the WH main ETH is the trigger for the guardian transition and we are polling it every 60s and this means we can incur one minute of downtime when it happens. We might need to change it to another ETH contract [likely our custom one deployed in ETH or some other network].

p.s: In the future when we implement proper governance in Lazer, Lazer should become the source though.

}

/// Makes an eth_call to a contract and returns the raw bytes
async fn eth_call(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm surprised that alloy doesn't have a function for this :?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alloy has eth_call but I couldn't install full alloy because of a dependency issue with pinned solana sdk versions. Pavel is looking to see if there is a workaround.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"Ethereum RPC address is required when guardian set source is 'ethereum'. \
Set --wormhole-ethereum-rpc-addr or WORMHOLE_ETHEREUM_RPC_ADDR."
)
})?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errr i don't like doing validation like this here. isn't there any other way [like how does an enum work on clippy?]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N/A anymore

Copy link
Collaborator

@ali-behjati ali-behjati left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Copy link
Contributor

@Riateche Riateche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some minor suggestions.

pub async fn fetch_guardian_sets_from_ethereum(
ethereum_rpc_url: &str,
wormhole_contract_addr: &str,
) -> Result<(u32, GuardianSet, Option<(u32, GuardianSet)>)> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear what's u32. Maybe replace the tuple with a struct with two fields?

Comment on lines +127 to +132
// Update current guardian set
Wormhole::update_guardian_set(&*state, current_index, current_set).await;

Wormhole::update_guardian_set(&*state, bridge.guardian_set_index - 1, previous).await;
// Update previous guardian set if available
if let Some((prev_index, prev_set)) = previous {
Wormhole::update_guardian_set(&*state, prev_index, prev_set).await;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be a single atomic update of both current and previous sets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants