6

I am using libraries to reduce the cost of deployment of a contract of which there may be many instances (using a factory contract). When I mark a library function as internal, the code seems to get inlined into the calling contract, which for me defeats the purpose of using a library. My question is, is it safe to mark library functions that modify the calling contract's state as public, even though they are only intended to be called from within the contract?

According to solidity docs:

Library functions can only be called directly (i.e. without the use of DELEGATECALL) if they do not modify the state (i.e. if they are view or pure functions), because libraries are assumed to be stateless.

1 Answer 1

1

Yes, it's safe. The fragment you're citing refers to calling library functions using an ordinary external CALL instead of the typical DELEGATECALL. At the EVM level there's no difference between a contract and a library. Each is just a piece of bytecode at a particular address and has its own, isolated storage space. When a contract DELEGATECALLs a library, it gives it access to its storage space, which covers the original space of the library and makes that space inaccessible. If the contract CALLed it instead, the library would have access to its own storage space and any changes made there would be "lost" to the contract. They'd still be preserved in storage, just not the storage belonging to the contract.

This is only a problem if you actually let the library read/write is own storage space. DELEGATECALL prevents that so it's always safe in that sense. It's also save to CALL a pure function as such functions cannot access storage at all.

view functions on the other hand might be affected if they accept storage arguments and try to read them. That's because a storage argument is just a reference to some place in contract's storage and in case of a CALL the library does not have access to that storage. The call is still "safe" though in the sense that there won't be any lost state modifications.

So, to summarize, it would only be unsafe if your intention was to have the contract use CALL to call these functions. You don't have to worry about that happening if you only use the high-level call syntax (i.e. L.foo(x, y, z)). You'd have to use the low-level address.call() function or inline assembly to get into this problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.