-
Notifications
You must be signed in to change notification settings - Fork 24
FLIP 338: Flow Actions: Composable Standards for Protocols #339
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
base: main
Are you sure you want to change the base?
Conversation
|
This is very interesting approach; looks a bit like my FLIX alternative ( composeability part ) but also I think lines are harder here. To be honest I would love to see DefiActions as a subset of Actions framework, I believe it would be more meaningful. I just read super fast, mostly code parts, I will try to dive deeper next week. ( torturing myself with linux DE this weekend ) |
|
Thanks for the initial feedback @bluesign! I don't remember seeing your FLIX alternative @bluesign, but I'm interested in hearing more about it.
What do you mean "as a subset of Actions framework"? Is that your FLIX alternative or are you speaking to a broader potential standard? |
| 3. **Swapper**: Exchanges one token type for another (e.g. targetted DEX trades, multi-protocol aggregated swaps) | ||
| 4. **PriceOracle**: Provides price data for assets (e.g. external price feeds, DEX prices, price caching) | ||
| 5. **Flasher**: Provides flash loans with atomic repayment (e.g. arbitrage, liquidations) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We ran into a usecase which didn't fit into the above model: Adding liquidity to a pool. It's basically a swap between two token types and LP tokens.
We solved for now by implementing "zap" instead: adding liquidity with one token type (it does an extra swap to the second token to have both tokens)
|
@sisyphusSmiling I was talking general. i think this is great idea to standardize things like lego blocks. But I think it is also important to build on something generic. Like now we have DefiActions; later we can have NFTActions, TopshotActions, etc ( something like MetadataViews ). As we did in metadataViews, it would be nice to define base Action, and build on it. Not sure if interface is the best way to go here. |
|
@bluesign while ideating there were mentions of expanding the underlying concept of DeFi Actions to other use cases - DAO Actions, Gaming Actions, NFT Actions, etc. And the existence of DeFiActions certainly doesn't prevent additional types of actions from existing. In fact, it's a hope that the mental model of an "action" as a composable, tightly scoped component with single responsibility enhances composable architectures. Though I have difficulty thinking of a way to create an ecosystem of composable parts for specific use cases (DeFi, governance, NFTs, etc) without common interfaces given we lack generics in Cadence. Did you have any ideas on that front? Also, the FLIP has been updated to place DeFi Actions under the broader umbrella of "actions" as a concept and way of thinking about composable contract development. |
| **Single Asset Type** | ||
| - Current [Sink](#sink-interface) and [Source](#source-interface) interfaces only support single Vault operations, which may not accommodate multi-asset actions such as liquidity provision or removal that require handling multiple Vaults simultaneously. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a blocker we ran into building a Source on top of Increment Fi Staking. Because all rewards must be withdrawn at the same time, and a source can only provide a single token type, it was unclear in the current single asset model how the source should handle excess output tokens that do not match the requested type.
I've thought a bit more about this, and have came up with the following:
Intuitively, it feels that this can just be part of the implementation, and that this should simply be passed as an initialization parameter. e.g. something like:
access(all) struct SomeSourceThatOverflows: Source {
init (
overflow: { Type: Sink }
)
// ...
}Where all possible tokens types correspond to a respecive handler (Sink) for any excess tokens encountered.
Thoughts @sisyphusSmiling ?
|
I think this is a good idea. I could see many options on how to visualize what a tx is doing in flowscan based on this. I agree with @bluesign on the generic part. It would be so good to have an action to:
I have an endless amount if boilerplate thar is repeated in find repos. |
This is great idea, but I think the main issue I have here is Action and Interface used as interchangeable here. I feel action should be more generic to be honest. It is not possible to predict everything, and things can go ugly fast. Interfaces are lacking a lot to cover Actions, then you will have a lot of boilerplate. ( other structs interfaces implementing said interface etc ) |
|
Did a little overview of this and I have a suggestion. Can we create a super interface Actions that has some of the structs? Right now many things is in DEFI actions this means that if we want to create other types of actions that is hard conceptually. |
|
@bjartek sorry, not sure I follow. Correct me if I'm wrong - I think you're asking if all actions regardless of purpose can share a common interface. Tbh I'm not sure what that could be given the variety of use cases. The idea of an "action" is more philosophical than anything - a building block that accomplishes some task with a tight scope of responsibility and graceful failure so that any given action can be interchanged as blocks in larger, more complex workflows. Fundamentally, any given "action" may do very different things from each other - a price oracle fetches a price while a swapper swaps tokens and a sink accepts deposits. However, when interacting with two of the same connectors, you don't have to concern yourself with the underlying implementation. Without some degree of assurance that every different "action" connector will share at least some functionality, I'm not sure how a super interface comes into play. This is complicated by the amount of abstraction that can be packaged under a single connector. One That's to say that even the initialization patterns between the same action could be very different. However, importantly using them can be simplified - I have tokens to deposit, I stick them in a Do you have a shared super interface in mind? |
|
@sisyphusSmiling I think what @bjartek says is pretty similar to what I was saying. Basically Action should just provide "introspection" on some superior interface. Rest is ( where defined here as action ) is actually optional. ( Even wrong without a superior interface ) This usually leads to assignable input/output connectors and generic execute method. More like an invocation pattern. So in the end you can understand and execute action over a single basic interface. This is a basic requirement in my opinion. |
|
We are currently brainstorming how to visualize and enhance actions in flowscan. We can analyze the source of a tx and find all vars that are DefiActions. But what about when there are other actions? Marketplace actions, nft actions etc? How would you make a Source for a single NFT with a given ID of a given type? (In find we call this a ViewPointer, or the AuthPointer where you can withdraw it) The defining sink source et all structs live in DefiAcfions not in Action. I see now that a Sink is very specific to an FT, so maybe some structs that live in Actions that are supertypes of all types of Sinks/Sources? Also how can i in code know more metadata about an action? Views could work or something. Does that help make this clearer @sisyphusSmiling |
|
Another question this a bit more detail focused To me this is the wrong level of abstraction. Why do i have to know about this path and the swap config stuff in here? I know there are increment fi swaps that can have complex paths, but has anybody ever used them. And if that is the case this could be a MultiPathSwapper. IMHO this code should be |
This FLIP is tracked by: #338