Skip to content

Stellar integration#4858

Open
Oghma wants to merge 4 commits into
wormhole-foundation:ext-integration/stellarfrom
NethermindEth:stellar
Open

Stellar integration#4858
Oghma wants to merge 4 commits into
wormhole-foundation:ext-integration/stellarfrom
NethermindEth:stellar

Conversation

@Oghma

@Oghma Oghma commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Stellar/Soroban support to Wormhole: a complete Soroban implementation of
the Wormhole Core contract, supporting client libraries, and a guardian node
watcher for the Stellar chain.

What's included

Soroban contracts (stellar/)

  • Wormhole Core contract (contracts/wormhole-contract) — message posting,
    guardian set management, message fee handling, and the full governance action
    set (guardian set upgrade, contract upgrade, set message fee, transfer fees),
    plus VAA parsing/verification and __constructor initialization.
    Soroban client library (contracts/wormhole-soroban-client) — shared
    types, errors, constants, and a BytesReader for VAA decoding. This is the
    library users import to interact with the Wormhole smart contract.

Guardian node watcher (node/)

  • New Stellar watcher (node/pkg/watchers/stellar/) with unit tests.
  • Wired into guardiand via node/cmd/guardiand/node.go.

Tooling & tests

  • Integration tests against a local Stellar network (stellar/integration-tests,
    contracts/wormhole-contract/src/tests) covering initialize/query,
    post message, message fee, transfer fees, guardian set upgrade, and contract
    upgrade flows.
  • Deployment scripts and mainnet/testnet config (stellar/scripts).
  • Local development via Tilt (Tiltfile, stellar/stellar.yaml).
  • Architecture and usage docs (stellar/ARCHITECTURE.md, stellar/README.md).

Notes

  • node/go.mod / go.sum updated for the Stellar SDK dependencies.

@socket-security

socket-security Bot commented Jun 12, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: golang github.com/aws/aws-sdk-go-v2/service/sts is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?golang/github.com/ethereum/go-ethereum@v1.10.21golang/github.com/aws/aws-sdk-go-v2/config@v1.29.17golang/github.com/stellar/go@v0.0.0-20251104133942-0bd7280d08e8golang/github.com/aws/aws-sdk-go-v2/service/sts@v1.34.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/aws/aws-sdk-go-v2/service/sts@v1.34.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: golang go.etcd.io/etcd/api/v3 is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?golang/github.com/go-kit/kit@v0.12.0golang/github.com/grafana/dskit@v0.0.0-20230201083518-528d8a7d52f2golang/go.etcd.io/etcd/api/v3@v3.5.9

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/go.etcd.io/etcd/api/v3@v3.5.9. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@johnsaigle

Copy link
Copy Markdown
Contributor

Hi @Oghma, I'd recommend squashing the commits above in order to have an easier time with CI going forward. As of now, the GitHub front-end won't allow us to run CI against this PR due to conflicts. As time goes on, this is likely to reoccur as this large PR is issued against origin/main which is updated many times per week. It'll likely be easier to continue through CI loops with a smaller set of targeted commits.

Screenshot 2026-06-17 at 3 55 10 PM

@Oghma

Oghma commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Hi @johnsaigle. I squashed in a single commit and rebased it on top of main

Adds the Stellar core Wormhole contract (Soroban), the Stellar watcher in
the guardian node, and the Tilt/devnet wiring for local Stellar testing.

Squashes the full Stellar integration work into a single commit.

Co-authored-by: Goutham <dkgoutham1806@gmail.com>
Co-authored-by: Marko Cupic <71461781+cupicmarko@users.noreply.github.com>
Co-authored-by: Stavros Vlachakis <89769224+svlachakis@users.noreply.github.com>
Signed-off-by: Matteo Lisotto <matteo.lisotto@gmail.com>
}

// parseMessageFromXDR parses the XDR-encoded Soroban event value into a MessagePublication.
func parseMessageFromXDR(data []byte, logger *zap.Logger) *common.MessagePublication {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it makes sense to have this as a method on the watcher rather than a free-floating function. This would allow you to use w.chainId for emitter chain below rather than using Unset which will always be invalid.

Timestamp: time.Time{},
Nonce: nonce,
Sequence: sequence,
ConsistencyLevel: uint8(consistencyLevel),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The uint32 value is truncated to uint8 without checking for overflow. Could you add a check somewhere that returns an error if the consistency level is > MaxUint8?

var sequence uint64
var emitterAddress []byte
var payload []byte
var consistencyLevel uint32

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
var consistencyLevel uint32
var consistencyLevel uint8

Better to use the correct type here and ensure that the JSON value fits inside of it

copy(emitter[:], emitterAddress)
}

return &common.MessagePublication{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe t would be better to return only the parsed values here instead of a partially-constructed MessagePublication?

IMO it's difficult to audit whether this struct is being created correctly when its fields are getting set in different places. I'm not sure passing around a semantically invalid Message Publication struct is the right way to go. (Empty values for TxID, Timestamp, and EmitterChain aren't valid)

mp.EmitterChain = w.chainID
mp.IsReobservation = true

logger.Info("reobserved stellar message",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you change this to use the ZapFields method instead? It allows us to get a common format when logging MessagePublicatons

func (msg *MessagePublication) ZapFields(fields ...zap.Field) []zap.Field {

{EmitterChainID: vaa.ChainIDMonad, DailyLimit: 500_000, BigTransactionSize: 50_000},
{EmitterChainID: vaa.ChainIDMegaETH, DailyLimit: 10_000, BigTransactionSize: 10_000},
{EmitterChainID: vaa.ChainIDZeroGravity, DailyLimit: 10_000, BigTransactionSize: 10_000},
{EmitterChainID: vaa.ChainIDZeroGravity, DailyLimit: 50_000, BigTransactionSize: 10_000},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks like a mistake, maybe a rebase issue? Same with the mainnet tokens changes. I don't believe this PR should modify the governor package.

// the raw account ID as their emitter (the 20-byte account left-padded with 12 zero bytes), so
// prepending this non-zero prefix makes it impossible to forge a generated message by sending a
// payment to the core account. The 20-byte account ID remains recoverable in the last 20 bytes.
var generatedEmitterPrefix = [4]byte{'X', 'R', 'P', 'L'}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It also looks like this is included from #4865 by mitake

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.

5 participants