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 DELEGATECALL
s 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 CALL
ed 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.