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

Idea: Play better with non-Sylvia contracts #377

Open
ethanfrey opened this issue May 9, 2024 · 2 comments
Open

Idea: Play better with non-Sylvia contracts #377

ethanfrey opened this issue May 9, 2024 · 2 comments

Comments

@ethanfrey
Copy link
Member

ethanfrey commented May 9, 2024

While Sylvia and non-Sylvia contracts can call each other without a problem (they have the same message shapes), it isn't always the most convenient. This is actually an essential use case for adoptioon of sylvia. Now that the API has stabilized, I think the biggest barrier to adoption is the fact that most teams have existing CosmWasm codebases, and they should get access to similar coding efficiency boosts adopting Sylvia in such an existing multi-repo as adopting it in a greenfield application. I mentioned this to DAO DAO, and I think the biggest resistance is the difficulty of integration and lack of any examples of someone doing this successfully.

There are some concrete hurdles besides learning a new framework. I will just highlight a few, happy for more in the comments (or this could break out to a meta-issue to track individual issues). Here are some examples:


Issue 1: If a non-sylvia contract wishes to call a sylvia contract, the ExecuteMsg struct gets kind of complicated:

let msg = cw20_base::contract::ContractExecMsg::Minting(cw20_minting::sv::Cw20MintingExecMsg::Mint {
        recipient: mock.sender.to_string(),
        amount: 150_000u128.into(),
});

The From implementation in #376 may make this a bit easier, and you do need cargo doc to even find the proper types to call. I don't have a great answer for a better API, but it should be nice and easy to construct such an item. Maybe providing such constructors on the message like you do on remote, so the following would work:

let msg = cw20_base::contract::ContractExecMsg::mint(mock.sender.to_string(), 150_000u128.into());

Issue 2: If a Sylvia contract wishes to call a non-Sylvia contract, it can't use the typed helpers like Remote.

I guess the straight-forward solution would be to hand-construct a Sylvia interface that matches the types on the existing contract, but that is a bit of work (especially for those new to Sylvia) and it will not update when the contract changes, which destroys one of the great type-safety guarantees from Sylvia.

My proposal would be to create a new macro designed for non-Sylvia contracts. They could do something like the following, and it would generate a Sylvia interface/trait that could be used to call it. Sure, just one trait for the whole contract, but that already provides a large performance boost:

#[cw_serde]   
#[sylvia::export_trait]
pub enum ExecMsg {
  // ... standard CosmWasm format
}

Issue 3: Multi-test helpers are lacking for Sylvia calling non-sylvia contracts.

This is similar to issue 2 but for the testing environment, not inside the contracts. Again, I think we are somewhat limited in what can be provided, but adding something like the #[sylvia::export_trait] macro could theoretically provide us with some usable stubs to test the two contracts together.


There are probably many other issues, and my suggestion is that when there is time and desire to get real adoption, someone on the Sylvia team tries to add a Sylvia contract to an existing multirepo of a real-world CosmWasm app and see how hard it is to port one of those contracts to Sylvia - what breaks in the calling contracts, what is needed to write clean sylvia code in the updated contract. And then define a number of concrete improvements. That, and document the process.

Pinging @hashedone and @jawoznia to think about how this fits with your roadmap. (I personally have no need for this currently, but I think it would be a big boon to Sylvia adoption)

@hashedone
Copy link
Collaborator

Issue 1: addressed with both #376 and #130, prioritizing them.


Issue 2 is "having Sylvia without having Sylvia" which is not a way to go. Sylvia uses many things from many contexts to generate its entities, and we cannot generate, for eg. remotes, without having a contract type or interface trait.

If we have an existing contract and we want to deliver sylvia-like helpers for it, it can be done today with defining a dummy interface:

#[interface]
trait MyNonSylviaContract {
  #[sv::exec]
  fn my_exec_msg(...) -> ...;
}

This approach makes it difficult to develop the future Sylvia utilities roadmap. For example - the Remote type would, in the future, contain both query and exec utilities (with mentioned #130) - so it would not be able to generate it from a single message.
Also, non-Sylvia contracts can be accessed from Sylvia contracts easily - all Sylvia messages return Response, it can have submsgs and query messages can be constructed.
Obviously, it would be possible to provide some simplified versions of interfaces, but it adds maintenance complexity that would not be needed if contracts were simply migrated to Sylvia.


Issue 3 I completely don't understand. Sylvia provides utilities for using contracts using Sylvia, but the sylvia::cw_multi_test::App still implements Executor and exposes all the methods from the cw_multi_test::App - non-sylvia contracts can be used the same way as they were before, in the same tests cases as Sylvia contracts, and they can interoperate.

@ethanfrey
Copy link
Member Author

I think these questions would be more obvious if the maintainers of Sylvia were also applying this to a larger real-world repository.

I have found some issues in the multi-test code while upgrading mesh-security, which seem to be limitations of the sylvia implementation around mixing contracts with CustomMsg and without CustomMsg. At the very least, there are no examples to come from.

The general idea here is that the core sylvia team tries this out and either realizes there is a simple enough approach already (which they then use and have an example that serve as documentation for others following the route), or they realize the parts that are a fair bit of mental overhead and which could be improved in Sylvia.

My ideas above were just my guesses on what would be hard, which is why they are not concrete issues. But I think the point that the core team should demo a path (and provide tooling / examples for it) before assuming any outside team will follow that path is the core point here.

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

No branches or pull requests

2 participants