Skip to content

Move contract logic to libraries #4800

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

Open
Amxx opened this issue Dec 19, 2023 · 6 comments
Open

Move contract logic to libraries #4800

Amxx opened this issue Dec 19, 2023 · 6 comments
Labels

Comments

@Amxx
Copy link
Collaborator

Amxx commented Dec 19, 2023

In #4799, @k06a proposes to move the contract logic to libraries. Using Object orienter programming, the library would include a struct, and operations to interact with it. Presumably this would help for the transition between normal and upgradeable contract, as the logic would remain (mostly) the same and only the data location (and construction?) would need to me modified.

My concern is that this could negativelly affect customisability and overridability of the contracts. For example, if ERC20.transfer relies on a ERC20Lib.transfer "internal" function, how would ERC20Votes (or other) be able to override that internal function ?

@Amxx Amxx added the idea label Dec 19, 2023
@k06a
Copy link
Contributor

k06a commented Dec 19, 2023

Libraries and their structures can not be inherited and ovveriden, but composition can be used. It is implicit, but still very powerful and I think compiler can inline all those lib calls.

Example:

library ERC20VotesLib {
    using ERC20Lib for ERC20Lib.Storage;
    using VotesLib for VotesLib.Storage;

    struct Storage {
        ERC20Lib.Storage erc20;
        VotesLib.Storage votes;
    }
    
    function balanceOf(Storage storage $, address account) internal view returns(uint256) {
        return $.erc20.balanceOf(account);
    }
}

@k06a
Copy link
Contributor

k06a commented Dec 19, 2023

Having libs for most of the functionalities would allow next gen of utility to the library. ERC20Lib library logic could be used multiple times inside one contract, for example to track shares and balances separately.

@Amxx
Copy link
Collaborator Author

Amxx commented Dec 19, 2023

My concern in ERC20 + Votes is not really in the storages, but in the operation.

Whenever tokens are transfered, minted, or burnt, the Votes module must track that. Today, this is done by overriding the _update() function in ERC20Votes, to plug the Votes module logic.

If we cannot override _update() then that means that you'd have to override the public transfer and transferFrom function to include that logic. If you use ERC1363, you'd also not to include that logic in all variants of transferAndCall().
And if a dev ever calls ERC20Lib.mint, the vote update will not be automatic, so they'll also have to call the vote update function. This feels like a lot of attention goes into the composition ... and a lot can go wrong. I'm not sure it makes things simplers or safer.

@k06a
Copy link
Contributor

k06a commented Dec 19, 2023

I see that composition currently allows only static hierarchies. We can’t have agile method to compose: ERC20, Votes and Delegates for example. The thing which can help with dynamic composition of structures is Solidity Generics, which I hope to see in 0.9.0 (didn’t checked their roadmap, but saw this on some slides).

@k06a
Copy link
Contributor

k06a commented Dec 19, 2023

BTW in OOP composition is usually considered as much more agile pattern than inheritance: https://en.wikipedia.org/wiki/Composition_over_inheritance

@Amxx
Copy link
Collaborator Author

Amxx commented Dec 19, 2023

Don't expect solidity to ship generic any time soon.

https://www.youtube.com/watch?v=jX5VJ4wcJXM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants