[CAP-67] Classic Ops emit Transfer/Mint/Burn/Clawback events #1553
Replies: 36 comments 395 replies
-
Define "emit"? I don't think this is even logistically possible from Core's perspective. Since smart contracts operate in their own land of execution and thus emit events into metadata via host functions, how would classic operations replicate this? Are you suggesting they inject Don't get me wrong, this sounds really nice, but I just can't see how it's possible. |
Beta Was this translation helpful? Give feedback.
-
While this seems easy enough to support for simple payments, I wonder what should we do for things like path payments, DEX trades, claimable balances etc. In Soroban world these would contain a number of transfer events, as well as maybe some other events. I don't think that's feasible for classic, as we wouldn't want to have an operation to emit a lot of events (these won't have a fee, unlike in Soroban case). I wonder if a subset of operations that move balances is sufficient to support. Basically, it would be nice to identify the requirements/use cases that we can support with certain 'classic' events. |
Beta Was this translation helpful? Give feedback.
-
Just wanted to big ➕ this! There have been a handful of conversations lately (internal + external) that have assumed or implied that we will be rebuilding or recreating the unified data models that we built out in Horizon, but now in RPC. Repeating this behavior would only recreate a lot of the issues we saw with Horizon, and allow RPC to become the defacto backend/monolith for any and all applications that want on-chain data. So yes, I'd wholeheartedly agree that the right layer to solve this at feels like the source-of-truth of the events data (ie. Core).
I think this is the right bit to start with as there's generally a lot of interest around a unified understanding of "what is a payment" or "what moves value" (lots of interest/talk around an open-source payment indexer, for example). |
Beta Was this translation helpful? Give feedback.
-
I'm a big fan of this proposal. I want to point out that there are two layers in this unification effort -- the source of the data and the format of the data. Providing a stream for all stellar asset transactions at the protocol level via events, as opposed to at the application level (like Horizon's /payments endpoint), makes sources of this data interchangeable. Clients can use RPC, a txmeta lake (produced by galaxie), captive core, or some other source of txmeta. However, I think it is equally important that we unify the format of the data provided. We could add events for all stellar asset transfers, providing a unified the stream for this data, but if the format of these events vary, clients will inevitably support a subset of these formats. We have this same problem right now with Horizon's Unfortunately I think we've already introduced multiple data formats in cases where a single format could have sufficed. For example, So lets take path payments for example. I would advocate that the event(s) emitted as a result of a path payment operation use the I'd like to see events in this format emitted for the following classic operations:
Now there are some classic operations where using the same format may not be the best path because there is not an obvious
In these cases, we may need to use a different format. The good news is that most applications won't need to care about these events because they don't use claimable balances or native AMMs. Finally, I think we should also consider emitting events for transaction fees. These are a kind XLM transfer, and anyone using events to update balances won't be able to maintain an accurate XLM balance without this event. |
Beta Was this translation helpful? Give feedback.
-
I've written up a document taking the list that @JakeUrban posted at #1553 (comment) and documenting what I think each of the events would need to be emitted to align the events with the events that the Stellar Asset Contract already emits today. https://docs.google.com/document/d/1511nhYdUiaGAJ-CT7TzVeAdBaTm4HLBgEFndfjno4jc Please leave comments about specifics directly on the document ☝🏻, or more general broad comments here 👇🏻. cc @JakeUrban appreciate your 👀 again. cc @sisuresh @dmkozh @anupsdf @MonsieurNicolas Cross-posted to Discord: https://discord.com/channels/897514728459468821/1285736582426394760/1300244089102532718 |
Beta Was this translation helpful? Give feedback.
-
@jopmiddelkamp I'd be curious on your take from Beans' perspective. Or if you'd continue using a third-party indexer, maybe you can ask your indexer to take a look at this? @earrietadev what is xBull's solution for indexing value transfers? Would this be helpful? I know from Freighter and Vibrant's perspective, this would be quite helpful because it would make our implementation much simpler. Today Vibrant listens for classic payments and path payments using RPC's Its a similar situation for Freighter. |
Beta Was this translation helpful? Give feedback.
-
Hi folks, conversation seems to have slowed in this proposal, suggesting some consensus exists, with the discussions on balances having identified a new problem we should think about and potentially solve independently. One of the most critical decisions with this proposal is where we solve the problem. The proposal as it is has the problem being solved in Stellar-Core. Alternatives that were considered:
Does anyone have alternative views on this? For folks who think this is being solved in the right place, please leave a positive emoji of some kind. |
Beta Was this translation helpful? Give feedback.
-
Reviving this thread - It sounds like there's support for adding the events described in this doc to stellar-core. We still need to figure out exactly what's required. Do the unified events need to be emitted retroactively? Also, the soroban events vector in tx meta can currently be verified because it's hashed into the ledger, so these classic events (which won't be hashed into the ledger), will need to either be a different field in meta, or put into the diagnostic events vector. Related to this, we need to make a change to make sure the events are semantically correct for transfers involving the issuer in the SAC - discussion. This will result in different logic to consume the events between protocol versions (a transfer call from an issuer will emit a |
Beta Was this translation helpful? Give feedback.
-
Here's the initial CAP - https://github.com/stellar/stellar-protocol/blob/master/core/cap-0067.md. There are some notable points that'll probably change -
|
Beta Was this translation helpful? Give feedback.
-
I noticed the following line in the proposed CAP-67 for this discussion after #1617:
(Also noted by @sisuresh in (1), above.) This seems prohibitive to downstream ingesters, unless the events themselves are expanded to make it completely unnecessary to inspect the operation itself (which would require more details in each classic event's Could we make |
Beta Was this translation helpful? Give feedback.
-
So I had a thought I want to throw out there. If the whole purpose of this event stream is for people downstream to track balances, couldn't the event itself just include the current balance for
Preemptive potential reasons why this might be a bad idea:
|
Beta Was this translation helpful? Give feedback.
-
@dmkozh ' suggestion of converging all event types down to a single On its own, map may be considered tedious for ingestion apps as it requires manual out-of-band comprehension of key/value docs and then translating that into application ingestion code(usually with hard-coded key names). Could the event data be defined in IDL terms, such as similar XDR Ext arm pattern, i.e. |
Beta Was this translation helpful? Give feedback.
-
I've been thinking about how to deal with old protocol bugs related to the native asset. More specifically, when it was possible to mint/burn the native asset in specific scenarios due to a cached account. From stellar-cores perspective, we'd ideally be able to go off of meta and emit an event that has a 1-to-1 mapping with a LedgerEntryChange like a Instead, we can use logic similar to the ConservationOfLumens invariant to identify when the asset has been minted/burned, tie that diff to a specific account, and emit the correct event. The bug should've only been hit in very specific scenarios, so it shouldn't be that difficult to special case this. |
Beta Was this translation helpful? Give feedback.
-
There is one thing that seems to have escaped our attention when discussing this: memos and muxed accounts. It's arguably not necessary for the high level purpose of 'just tracking the balances', but I think we generally want the events to be more self-sufficient and compatible with Soroban. But for Soroban the 'classic' ways of handling memos by parsing both the transaction and the meta is rather annoying. The annoyance will be much worse for Soroban, if we ever want it to support multiplexing. So I think we might need to try specifying something useful for the classic memos/muxed accounts and then hopefully make it also possible in Soroban. I don't have any concrete proposal yet; looking for some ideas/opinions first. |
Beta Was this translation helpful? Give feedback.
-
RE: https://docs.google.com/document/d/1511nhYdUiaGAJ-CT7TzVeAdBaTm4HLBgEFndfjno4jc/edit?disco=AAABbyoARVA
What's the status of how events will be published for path payments that result in multiple assets exchanging between accounts? @sisuresh Are we confident that the the above statements from CAP-67 about what transfer events that path payments will emit are how it will be implemented? Early on in those discussions @MonsieurNicolas suggested that events might get generated for net movement. I think everyone else involved in the discussion (@tomerweller @Shaptic @tamirms @leighmcculloch) seemed to prefer the pattern that's described in CAP-67, that is also consistent with how Horizon presents the trades. Just want to confirm this is closed out, or something that's still under consideration. |
Beta Was this translation helpful? Give feedback.
-
As has been discussed during the protocol meeting, here is a rough sketch for how the muxed address support could look like: stellar/soroban-examples#363. I've briefly described the pieces of the sketch in the doc. Some concerns that I recall have been raised regarding this approach during the meeting:
|
Beta Was this translation helpful? Give feedback.
-
For comparison with the spike @dmkozh posted (#1553 (comment)) I've posted an example of what it would look like to implement @MonsieurNicolas's idea (#1553 (reply in thread)) (not too different to also what was posted at #1534), which I'm pondering on because of its simplicity, and how easy it can be isolated, and because of its very low future maintenance burden: Trade-offs with this approach:
|
Beta Was this translation helpful? Give feedback.
-
I think we should answer the question:
We've been discussing different approaches, where we introduce new first-class types (#1553 (comment), #1553 (reply in thread)), and other approaches that require less effort/maintenance (#1553 (comment)). All spikes have been extensions to SEP-41, rather than a modification of SEP-41. If we're targeting a small number of contracts using memos, an extension makes sense. But if we expect a lot of tokens to add mux capabilities, then I think we should consider changing SEP-41 instead. To add it to SEP-41, then @dmkozh's original proposal to bring The new interface would still be backwards compatible if the SDK auto-upgraded |
Beta Was this translation helpful? Give feedback.
-
Assuming we do #1553 (reply in thread), then we need to define how the event will render for all memo types. 1. Break apart consistently
2. M where-ever possible
3. A new M-strkey that can store all types of memos
4. Embed in ScAddress but no new strkey
|
Beta Was this translation helpful? Give feedback.
-
In the protocol meeting today we discussed a bit what would happen with transfer events that had a mix of muxed accounts and transaction memos. Are we leaning towards doing the following?
|
Beta Was this translation helpful? Give feedback.
-
I hate to necro a topic but a lot has changed since we last discussed it so I wanted to get a temp check on it. How do we feel about
In a similar vein, I can see an argument made for Prior discussion (not "required reading" but included for completeness): |
Beta Was this translation helpful? Give feedback.
-
Should we add a new ContractEventType calling it
|
Beta Was this translation helpful? Give feedback.
-
I've probably missed the discussion regarding the |
Beta Was this translation helpful? Give feedback.
-
While working on the prototype for the
instead. This way there is no ambiguity built into the data structure. FWIW this seems consistent with the strkey library representation as well. Any objections? |
Beta Was this translation helpful? Give feedback.
-
I see change #1686 occurring adding the following statement:
Does this only affect past operations? or also new operations that execute in P23? Are these events from within a single operation only? or can this reordering span operations in a single transaction? @sisuresh Can you share a list of all the operations the reordering can happen within and some examples? |
Beta Was this translation helpful? Give feedback.
-
I see that there's a change for CAP-63 that says that refunds of fees will occur later outside of individual transaction applies: And that there's a related change in CAP-67 that says that fee refunds will not have their own event, rather a single fee event per transaction will be emitted that is the net result of the initial amount debited minus the refund: I think these changes will create a subtle inconsistency in the balance of an account when viewed from different perspectives. When viewed from the perspective of a contract that executes during the ledger, they will see the balance of the account as the account balance minus the full fee. When viewed from the perspective of an off-chain system ingesting events, they will see the balance of the account as the account balance minus the net fee. Contracts will see the account balance in a state that off-chain systems will never see it in. I'm not convinced this problem will be material, or that it's worth having a separate refund event to exactly represent the changes in value. It'd be nice if the transition was also hidden from contracts, but I don't think that's possible. |
Beta Was this translation helpful? Give feedback.
-
@jayz22 pointed out this early success case in PaymentOp where we return early if you're paying yourself. Should we emit an event this specific case? I don't think it's necessary, but wanted to make this known because the TTP probably emits an event in this scenario. A path payment that sends and receives the same amount of XLM would emit an event, so I could see the argument for consistency, but I'm not a fan of doing additional work to emit an event that has no value. @karthikiyer56 @leighmcculloch If we decide not to add the event, then we should update the CAP to mention that an operation might not emit an event if no movement of value occurs. |
Beta Was this translation helpful? Give feedback.
-
Currently for Soroban transactions, the diagnostics vector contains all events (diagnostics, events from failed invocations, and events for successful invocations). This was done because the diagnostics might be interleaved with non-diagnostic events, and having all of them in a single vector would let you consume all events in order. For classic transactions, the current implementation does not duplicate operation events into the diagnostics vector, and will only exist in the non-diagnostic operation level vector. We don't emit diagnostics for classic operations, so there's no interleaving. Is this an issue? I believe there might be some consumers that solely go off of the diagnostics vector with the expectation that it will contain all events. |
Beta Was this translation helpful? Give feedback.
-
-- Thread about Muxed Info for Mint and Burn events --- Reading through this section in CAP-67, the impression i get is that the What about when eventType = mint or burn? Consider the case of a simple payment Op - where Same question for mint. And what if txMemo is set, instead of the destination being a MuxedAccount in the case of the mint? In all of these cases, IMO, the appropriate muxed (either |
Beta Was this translation helpful? Give feedback.
-
@sisuresh I can't find in CAP-67 a clear description of when the fees are deducted and credited to the fee paying account, and therefore when the fee events should be interpreted to have had an effect on the balance. I know somewhere in the threads above it was mentioned that:
Is that correct? If that's not captured in CAP-67 can it be? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
What
I propose we unify transfer events on the network in smart contract events, by exploring emitting transfer contract events, like those defined by SEP-41, CAP-46-6, and those potentially defined by #1534, for classic transfers (payments, path payments, etc).
Why
To create a singe unified data stream of all movements of assets / tokens on Stellar.
Today there is no single way to consume transfer events on the network. Transfers are divided by the classic vs smart contract divide, and then also on a separate dimension by stellar assets and custom tokens.
The RPC is the way developers are intended to stream and ingest live events occurring on Stellar. The RPC exposes smart contract events. However any application using the RPC and wanting to ingest transfers must implement complex logic merging the results of streaming smart contract events and transactions containing payments, path payments, offers, so on.
The shortest paths to a payments implementation today is to go back to Horizon's /effects endpoints, or Horizon's /payments endpoint, however the migration path we're wanting to create is in the opposite direction from Horizon to the RPC. There should be a way for developers to ingest all transfers from RPC, otherwise the path for migrating from Horizon to RPC is not realistic.
We could explore ways to add payment information to RPC, such as a similar Horizon-like /effects endpoint or /payments endpoint, however I think that is solving the problem at the wrong layer and repeating mistakes of the past. We've made that mistake before with Horizon, by solving all indexing problems at the Horizon layer which encouraged folks to build on Horizon rather than innovate on new and or better data sources.
RPC's API is designed to provide a raw view into the network and live / current network data. It exposes raw transaction XDR, and raw events. RPC doesn't contain "business logic" or even "indexer logic" for understanding network data. This is critical because if you build on RPC, you're building on the same data that's also available from Galexie, other CDP tooling, or raw meta. You have access to the same data, so applications can select between them without being disadvantaged, and without artificial / convenience forcing functions causing folks to interact with one when another would be more appropriate.
What's critical is that network data be a good foundation to build on. In many ways it is, but for understanding transfers between accounts it is unfortunately not. Soroban transfers have resolved this problem for transfers originating on Soroban through Soroban events, and if classic adopted the same events network data would tell a great coherent story about transfers.
If we solve the problem at the network layer, then events on Stellar can support a unified view into the movement of value on the network.
How
All transfers / payments on Stellar classic are the result of interactions with Stellar Assets. All Stellar Assets have a reserved contract address and a reserved installation of the built-in Stellar Asset Contract. For example, on mainnet (pubnet) the
native
asset has contract addressCAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA
. Stellar classic operations can emit Soroban events using the asset's reserved contract address, even if the reserved contract address hasn't been deployed to yet for that contract. All classic transfers of value are mappable to Soroban events, because the Soroban Stellar Asset Contract was modelled on the Stellar asset classic behaviours.A proposed mapping exists at: https://docs.google.com/document/d/1511nhYdUiaGAJ-CT7TzVeAdBaTm4HLBgEFndfjno4jc
And is being discussed here: #1553 (comment)
Links
Discussion on Discord: https://discord.com/channels/897514728459468821/1285736582426394760
Beta Was this translation helpful? Give feedback.
All reactions