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

ERC20 Permit Component #1140

Merged
merged 29 commits into from
Oct 15, 2024
Merged

ERC20 Permit Component #1140

merged 29 commits into from
Oct 15, 2024

Conversation

immrsd
Copy link
Collaborator

@immrsd immrsd commented Sep 10, 2024

Implements ERC20Permit extension

PR Checklist

  • Tests
  • Documentation in a separate PR
  • Added entry to CHANGELOG.md
  • Tried the feature on a public network

Copy link
Member

@ericnordelo ericnordelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Alejandro, the implementation is looking good, but I think we should refactor this into an extra embeddable implementation in the ERC20Component, instead of an extra component, since this would reduce the boilerplate in the final contract, and a component without storage members and events can be just an extra module.

CHANGELOG.md Outdated Show resolved Hide resolved
packages/presets/src/erc20_permit.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/extensions.cairo Outdated Show resolved Hide resolved
Copy link
Collaborator

@andrew-fleming andrew-fleming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, sir! I do agree with Eric with having ERC20Permit as an embeddable impl inside of ERC20Component. This should be a little easier to integrate into a contract. Aside from this, I left a few comments :)

packages/presets/src/erc20_permit.cairo Outdated Show resolved Hide resolved
packages/token/src/tests/mocks/erc20_permit_mocks.cairo Outdated Show resolved Hide resolved
packages/token/src/tests/erc20/test_erc20_permit.cairo Outdated Show resolved Hide resolved
packages/token/src/tests/erc20/test_erc20_permit.cairo Outdated Show resolved Hide resolved
Copy link

codecov bot commented Sep 27, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 91.76%. Comparing base (f7b7a7b) to head (a144d66).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1140      +/-   ##
==========================================
+ Coverage   91.53%   91.76%   +0.22%     
==========================================
  Files          46       48       +2     
  Lines        1182     1202      +20     
==========================================
+ Hits         1082     1103      +21     
+ Misses        100       99       -1     
Files with missing lines Coverage Δ
packages/testing/src/constants.cairo 100.00% <ø> (ø)
packages/token/src/erc20/erc20.cairo 96.55% <100.00%> (+0.77%) ⬆️
...kages/token/src/erc20/extensions/erc20_votes.cairo 95.91% <ø> (+1.80%) ⬆️
packages/token/src/erc20/snip12_utils/permit.cairo 100.00% <100.00%> (ø)
packages/token/src/erc20/snip12_utils/votes.cairo 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f7b7a7b...a144d66. Read the comment docs.

Copy link
Collaborator

@andrew-fleming andrew-fleming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job on the improvements! This looks almost ready to me. I left a small suggestion and a question

packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/extensions/erc20_permit.cairo Outdated Show resolved Hide resolved
Copy link
Member

@ericnordelo ericnordelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job with the refactor @immrsd! Left some comments.

packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/extensions/erc20_permit.cairo Outdated Show resolved Hide resolved
packages/token/src/erc20/interface.cairo Outdated Show resolved Hide resolved
@@ -107,3 +121,43 @@ pub trait ERC20VotesABI<TState> {
ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
) -> bool;
}

#[starknet::interface]
pub trait ERC20PermitABI<TState> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to add an extra ABI trait, but include the new implementations in the ERC20ABI trait, even if the user can choose not to use some implementations, the ABI should contain the full ABI of the component.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ERC20Mixin actually implements ERC20ABI. If we include permit fns into ERC20ABI, we'll have to require ERC20Permit to be implemented for ERC20Mixin to become available. I don't think we should do that and that ERC20Permit is the feature that should be expected to be ON by default

image

This way it makes total sense to have an additional interface named ERC20PermitABI, so it can be used for the cases when the trait is included and implemented

Copy link
Member

@ericnordelo ericnordelo Oct 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ERC20Mixin (and other mixins) implement the ABI of the component by coincidence, but not by definition. Mixin and ABIs are different things, even when they sometimes match.

A Mixin is a set of implementations that are commonly used together (as mentioned here) whose objective is to avoid verbosity. A component ABI trait, on the other hand, is intended as a single dispatcher for the component full interface, even if it doesn't have to be implemented all-together, as explained in this recently added note:

Screenshot 2024-10-07 at 14 04 24

We didn't follow this principle in Ownable and OwnableTwoStep because the same function (transfer ownership) with the same interface has different implementations that can be problematic if they are used thinking the other one is in place, so we favoured clarity over the rule. In this case, the permit implementation doesn't have a problematic intersection and can be added to the ABI as intended.

In this case, we can use #[generate_trait] for the mixin instead of implementing from the ABI trait, and we should add permit to the existing ABI.

Note that adding a different ABI per feature would create a lot of repetition in the interface file if the component grows bigger in features.

TLDR: Mixin shouldn't be necessarily pegged to component ABIs, since they are not defined as the same thing.

cc @andrew-fleming that may correct me if I recall something the wrong way from when we worked on this definitions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds accurate to me. Looking at the docs now, I do think we can improve our definition of ABI traits. We mention that they're useful for preset contracts; however, this isn't necessarily true anymore. We have a preset interfaces dir now and the ABI doesn't include the interface for upgrades. Further clarity and purpose would be helpful IMO

TLDR: Mixin shouldn't be necessarily pegged to component ABIs, since they are not defined as the same thing.

Maybe it's worth using #[generate_trait] for all the mixins to establish a better differentiation

Copy link
Collaborator Author

@immrsd immrsd Oct 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[generate_trait] won't help here since the embeddable trait has to implement a starknet interface. I decoupled mixin impl from ABI and added a IERC20Mixin interface

packages/token/src/tests/erc20/test_erc20_permit.cairo Outdated Show resolved Hide resolved
Copy link
Collaborator

@andrew-fleming andrew-fleming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with Eric's review, namely:

  1. Span (+ into) > Array
  2. ComponentState testing pattern > Dispatchers
    • If you feel strongly about favoring dispatchers for testing, let's discuss outside of the PR

packages/token/src/erc20/erc20.cairo Outdated Show resolved Hide resolved
@immrsd immrsd requested a review from andrew-fleming October 14, 2024 19:34
Copy link
Member

@ericnordelo ericnordelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good @immrsd ! I left a small suggestion, but besides that I think it is ready to go.

@ggonzalez94 this will generate some conflicts with the Votes PR.

fn test_invalid_sig_bad_deadline() {
let data = TEST_DATA();
let (owner, spender, amount, deadline) = (data.owner, data.spender, data.amount, data.deadline);
let mut state = setup(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an example of a test that doesn't use the DualCaseAccountMock, should we decouple the setup_account logic from the setup one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular test case doesn't require the account mock to be deployed. At the same time, I don't think we should decouple it, since this way we'll lose consistency over the test cases and we'll have to introduce an additional setup function that will be used in this only place

packages/utils/src/cryptography/snip12.cairo Outdated Show resolved Hide resolved
@immrsd immrsd merged commit 1cf9987 into OpenZeppelin:main Oct 15, 2024
8 checks passed
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

Successfully merging this pull request may close these issues.

3 participants