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: use openzeppelin's eip712 and change authorization name #453

Closed
wants to merge 8 commits into from

Conversation

pakim249CAL
Copy link
Contributor

@pakim249CAL pakim249CAL commented Feb 1, 2023

Pull Request

Issue(s) fixed

This pull request:

To preemptively answer some questions that may arise:

The reason that EIP712Upgradeable is not used is because this version stores some useless storage variables, namely the hashes of the name and version.

EIP712 should function identically despite it being the non-upgradeable variant. There are no storage variables in this contract, and the domain separator is built entirely through immutable logic. It uses address(this), thus satisfying the property that the domain separator is built using the proxy contract's address as context.

I've also removed much of the signature logic in favor of using the ECDSA library's system of checks.

The reason that I renamed the authorization typehash is because I believe the standard is for each function that utilizes EIP712 to have its own unique typehash. Thus the previous naming makes little sense if we ever introduce a new function that utilizes EIP712.

@pakim249CAL pakim249CAL linked an issue Feb 1, 2023 that may be closed by this pull request
src/libraries/Constants.sol Outdated Show resolved Hide resolved
src/MorphoStorage.sol Outdated Show resolved Hide resolved
Rubilmax
Rubilmax previously approved these changes Feb 2, 2023
constructor(address addressesProvider, uint8 eModeCategoryId)
EIP712(
Constants.EIP712_NAME,
string(abi.encodePacked(Constants.EIP712_VERSION, ".", Strings.toString(eModeCategoryId)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
string(abi.encodePacked(Constants.EIP712_VERSION, ".", Strings.toString(eModeCategoryId)))
string.concat(Constants.EIP712_VERSION, ".", Strings.toString(eModeCategoryId))

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this string represent the version argument of the instance ? Why do we need to add the E-mode id?

Copy link
Contributor

Choose a reason for hiding this comment

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

  1. Yes
  2. I don't think there's a need, but it's weird to share the same id between 2 instances of Morpho

#453 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it's strictly required because the address of the proxy is used as part of the domain separator. But I believe it is good practice to maintain distinct identities to each contract. We could instead put this in an arbitrary salt, but I don't think this is necessary. It should suffice to have different versions for each e-mode category.

if (signature.v != 27 && signature.v != 28) revert Errors.InvalidValueV();
bytes32 structHash =
keccak256(abi.encode(Constants.APPROVE_MANAGER_TYPEHASH, delegator, manager, isAllowed, nonce, deadline));
bytes32 digest = _hashTypedDataV4(structHash);
Copy link
Contributor

Choose a reason for hiding this comment

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

why did you remove the checks on v and s ?

Copy link
Contributor

@Rubilmax Rubilmax Feb 2, 2023

Choose a reason for hiding this comment

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

These checks are performed in OZ's ECDSA tryRecover

constructor(address addressesProvider, uint8 eModeCategoryId)
EIP712(
Constants.EIP712_NAME,
string(abi.encodePacked(Constants.EIP712_VERSION, ".", Strings.toString(eModeCategoryId)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this string represent the version argument of the instance ? Why do we need to add the E-mode id?


uint256 internal constant MAX_VALID_ECDSA_S = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; // The highest valid value for s in an ECDSA signature pair (0 < s < secp256k1n ÷ 2 + 1)
bytes32 internal constant APPROVE_MANAGER_TYPEHASH =
keccak256("ApproveManager(address delegator,address manager,bool isAllowed,uint256 nonce,uint256 deadline)"); // The EIP-712 typehash for approveManagerBySig Authorization.
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not understand why change approve manager typehash from EIP712 Authorization typehash

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is for clarity, because this type hash is only used upon manager approval

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct. AFAIK it is standard practice for each function which has a signature method to be the same as the method to be called. My goal here is consistency, not much opinion on the naming.

@@ -46,7 +47,7 @@ abstract contract MorphoStorage is Initializable, Ownable2StepUpgradeable, EIP71
/// @param addressesProvider The address of the pool addresses provider.
/// @param eModeCategoryId The e-mode category of the deployed Morpho. 0 for the general mode.
constructor(address addressesProvider, uint8 eModeCategoryId)
EIP712(Constants.EIP712_NAME, Constants.EIP712_VERSION)
EIP712(Constants.EIP712_NAME, string.concat(Constants.EIP712_VERSION, ".", Strings.toString(eModeCategoryId)))
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the bytecode of adding this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

clearly too much. investigating.

@pakim249CAL
Copy link
Contributor Author

Too much bytecode, so I'm ruling out OZ's implementation for now. Closing.

@pakim249CAL pakim249CAL closed this Feb 2, 2023
@Rubilmax
Copy link
Contributor

Rubilmax commented Feb 3, 2023

Reopening because I don't understand the conclusion: I just compiled the contracts and it seems we're loosing ~1kb because of OZ's implementation. Do you have the same number? If yes, why do you consider this "too much bytecode"?
Please note there's still a 2kb margin after this change (3kb before)

Pushing this because we've just made the error of trying to rewrite OZ's standard and it led us to introduce a bug. Perhaps we should really consider base our work on standards, even if it costs bytecode.

@Rubilmax Rubilmax reopened this Feb 3, 2023
@Rubilmax Rubilmax marked this pull request as draft February 3, 2023 08:25
@pakim249CAL pakim249CAL mentioned this pull request Feb 3, 2023
@Rubilmax Rubilmax closed this Feb 6, 2023
@MerlinEgalite MerlinEgalite deleted the fix/domain-separator branch May 3, 2023 12:51
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.

Reconsider EIP712 implementation
4 participants