defi-wonderland / smock

The Solidity mocking library
MIT License
321 stars 39 forks source link

feat request: adding support for mocking libraries #50

Open ashhanai opened 2 years ago

ashhanai commented 2 years ago

Make it possible to mock libraries in contracts.

Example: I am using my own library Lib with struct Lib.Str in my contract Con. using Lib for Lib.Str;

My Lib has few methods which works with Lib.Str: function foo(Lib.Str memory _str, uint256 _amount) external

I am calling this functions in my contract like this: str.foo(10);

I would really use mocking this library and be able to see, if my contract (which is using this library) called function foo, how many times and so on.

0xGorilla commented 2 years ago

Hey @ashhanai , it's great to see that people are actually using Smock v2!

Your proposal sounds super interesting, could you please provide a test that would illustrate better the use case?

ashhanai commented 2 years ago

Hi @0xGorilla, sure.

Use case

Create a token abstraction and pack ERC20, ERC721 & ERC1155 into one struct Token. Implement library, that uses Token struct and defines functions for transfer and approve transfers of underlying ERC20 / 721 / 1155 tokens. Use this token to eliminate unnecessary type check every time transfer / approval should occur.

Test

My contract is transferring tokens via this abstraction and I want to test, that it calls the right function of the library (library is tester separately, so just the call check is enough).

The issue here is that my contract is linking the library and using it like this: using TokenAbstract for Token; so even though the function is defined like this function transfer(Token memory _token, address _receiver, uint256 _amount) the transfer call is made e.g. like this token.transfer(receiver, 10).

I hope I made the use case more understandable.

0xGorilla commented 2 years ago

I meant forking this repo and creating a real test (that would fail), from there I will grab the test and try to make it pass.

Is that possible? From there it will be easier to develop a solution

smartcontracts commented 2 years ago

@0xGorilla this is related to our plan to add mocking for libraries in general, which requires that deeper rewrite we discussed. It's definitely a huge value add but will take some effort.

0xGorilla commented 2 years ago

This is still not solved, but at least right now you can deploy a mock that uses a library, check out the tests of https://github.com/defi-wonderland/smock/pull/68

Remscar commented 2 years ago

I've been using smock a whole lot lately and have been also working with the Ethereum Diamonds (https://eips.ethereum.org/EIPS/eip-2535). Diamonds use a lot of libraries and being able to mock a library would make unit testing Diamond Facet's 1000x easier.

hickscorp commented 2 years ago

First of all, I'm completely mind blown by what smock does. Being in the Solidity ecosystem since it started, and for having had to test stuff manually with solidity mocks keeping tracks of args, smock absolutely rocks.

Now - mocking libraries - this is a really tricky topic. Solidity libraries are weird beasts... I'd like to give a bit of feedback here, from my experience with smock just now.

  1. I tried to smock.fake a library. Things just crash.
  2. I then tried to smock.mock a library factory. Things got better.
  3. All in all, I wasn't able to get the mock to return the number of times it was called (getCall(0) is just undefined).

Now regarding 2 - during this step, I discovered a few things: You might think that you're using a library while you're in fact not. Basically, if your library has either one of:

To finish - I might have forgotten a few things here - I would really like that smock adds support for libraries.

0xmichalis commented 5 months ago

Came across this issue today, it'd be great to have support for this! We have the exact same use case as @ashhanai