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

feat request: adding support for mocking libraries #50

Open
ashhanai opened this issue Aug 18, 2021 · 8 comments
Open

feat request: adding support for mocking libraries #50

ashhanai opened this issue Aug 18, 2021 · 8 comments

Comments

@ashhanai
Copy link

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
Copy link
Member

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
Copy link
Author

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
Copy link
Member

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
Copy link
Contributor

smartcontracts commented Aug 18, 2021

@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
Copy link
Member

This is still not solved, but at least right now you can deploy a mock that uses a library, check out the tests of #68

@Remscar
Copy link

Remscar commented Oct 7, 2021

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
Copy link

hickscorp commented May 13, 2022

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:

  • Any function marked internal or a private in the library? Then this function will get inlined by the compiler, and put directly in the caller. Therefore - mocking cannot work. This can be particularly misleading - and I know lots of people discover this at their own expense, when they "think" their logic is deployed neat and tidy separately, and in the end discover that just a few functions are actually deployed in their library and all others are inlined, bloating their contracts.
  • Even if your function is explicitly marked public, there's a huge caveat here. If your public or even external library function uses an argument passed as storage and / or of type struct, then you'll also get that inlined.

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

@wei3erHase wei3erHase changed the title Mock library feat request: adding support for mocking libraries Jun 17, 2022
@0xmichalis
Copy link

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

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

6 participants