Skip to content

Gabe's review #56

Open
Open
@grod220

Description

@grod220

Testing 🧪

  • Here’s a peek at your code coverage. I’d encourage you to run them as well (I use CLion’s coverage abilities) and find the holes. For example: Entry point queries could use some tests.
    • Screenshot 2023-08-08 at 3 19 11 PM
  • I think the nature of this application really requires something that can test contract-to-contract functionality. Perhaps that’s why there isn’t coverage for lots of messages? Some things to consider:
    • I have used cw-multi-test extensively and it has worked work well. However, it may require you to mock out some contracts or chain modules to be able to complete full contract→contract→chain module requests.
    • For Osmosis, we’ve also used Test-Tube which is the most accurate to the chain (but does not have good debugging).
  • If there is only two cases tested (a happy and bad), I’d say testcase is not necessary.
    • In general, would you say testcase is helpful? Personally, I have used it sparingly. For this repo, I find it makes it quite difficult to reason about these cases. And given it’s in a macro, the IDE kinda treats it as plain text and hard to read.
  • I think you should be asserting here the changed state of the bank balances of the contracts and the user.

Frontend scripts 🐍

Your deploy scripts are not type safe and are written in Python. I think you should convert this to Typescript (the sooner the better). Few things:

  • You want to tightly couple your contract messages with your deploy scripts. At the moment, these are entirely separate. This means the contracts can break the deploy scripts and you wouldn’t know.
  • The frontend team already needs to write Typescript and convert these Rust messages to Typescript types. Your deploy scripts could partially serve as a blueprint for them. Further, you should be using ts-codegen to generate the types the frontend needs to use. Doing so, will tightly couple their types with the contracts. So much safer!
  • Add yarn build checks and ts-codegen generation to your CI/CD so it ensures your contracts never unexpectedly break frontend types.
  • Consider adding simple user flows to your deploy scripts that can run in testnet
  • Your deploy scripts should also automatically generate these files from the result of their running
  • Good examples here. If you are interested in all of this I could walk you through how this works too.

Chain Abstraction ⛓️

  • Your thoughts are definitely valid here. This is a great time to start abstracting things out. We ran into this exact issue and found this pattern to be effective. You define a base struct that takes generics which implement general functions. It’s quite hard to fully explain and is much easier to straight copy this model from Mars.

Random observations ☕️

  • I see you are using a Makefile, but we’ve been quite happy using cargo make. Here’s our Makefile.toml.
  • Your build cache looks to be using an old version. The new way should look like: --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \
  • Some of your deps are out of date. I encourage you to run cargo upgrade (in cargo-edit package) and run it often.
  • You should add a cargo fmt check to your ci/cd pipeline to ensure folks are formatting their code.
  • Your github workflow only runs on PR. I’d recommend to add main as well. You always want to know if your main builds after a merge. There is a situation where someone merges an old PR that had passed all CI/CD checks, but breaks main. It’s good to be aware of that after merge and not the next time someone creates a new PR.
  • Instead of a path dependency, make this skip = { workspace = true } and add the dependency to the top level workspace Cargo.toml like so: skip = { version = "2.0.0", path = "./packages/skip" }. That way, it makes it easier for contracts to inherit.
  • The instantiate function has a lot of validation logic inside. I’d encourage you to abstract this. There is a pattern you could use of having messages that take unchecked versions and have a unchecked_swap_venue.checked() method called in instantiate. That struct can also have other logic on it (e.g. how to assemble swap messages).
  • You probably want a set here. Larry created a good crate for that purpose.
  • Why is it called a Venue and not a Dex?
  • Consider adding code comments for documentation on your execute messages. Not sure what an Affiliate is.
  • If fee_swap is only for IBC transfers, you should place it within the action variant instead of making it an option.
  • How can you determine the refund amount at this stage? Isn’t it just an estimate? Don’t you need to issue the swap first, see how much is left over, and then issue the refund? For this, you’d need to have a callback message with the current balance and check the balance after the action has taken place. Or perhaps I’m not understanding this precisely right.
  • This file is getting a bit long. Could be a candidate for splitting up functions into separate files. This is also a personal preference. I tend to err on splitting up code earlier rather than later.
  • If you don’t set the contract version, you won’t be able to upgrade the contract.
  • You should have an owner role that is allowed to update the config and state of the contract. Else, those values become immutable. I wrote this one and it’s in use with all Mars contracts. Examples: initialize / update / use in execute
  • Doing it this way means you can only ever have one reply message. Would encourage you to do a match and throw an error vs panic with unreachable!().

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions