Omniscia Gravita Protocol Audit

ERC20Permit Code Style Findings

ERC20Permit Code Style Findings

ERC-01C: Inefficient mapping Lookups

TypeSeverityLocation
Gas OptimizationERC20Permit.sol:L96, L104

Description:

The linked statements perform key-based lookup operations on mapping declarations from storage multiple times for the same key redundantly.

Example:

contracts/Dependencies/ERC20Permit.sol
95bytes32 hashStruct = keccak256(
96 abi.encode(PERMIT_TYPEHASH, owner, spender, amount, _nonces[owner].current(), deadline)
97);
98
99bytes32 _hash = keccak256(abi.encodePacked(uint16(0x1901), DOMAIN_SEPARATOR, hashStruct));
100
101address signer = ecrecover(_hash, v, r, s);
102require(signer != address(0) && signer == owner, "ERC20Permit: Invalid signature");
103
104_nonces[owner].increment();

Recommendation:

As the lookups internally perform an expensive keccak256 operation, we advise the lookups to be cached wherever possible to a single local declaration that either holds the value of the mapping in case of primitive types or holds a storage pointer to the struct contained.

Alleviation:

All inefficient mapping lookups have been significantly optimized per our recommendation, rendering this exhibit fully alleviated.

ERC-02C: Multiple Top-Level Declarations

TypeSeverityLocation
Code StyleERC20Permit.sol:L7, L50

Description:

The referenced file contains multiple top-level declarations that decrease the legibility of the codebase.

Example:

contracts/Dependencies/ERC20Permit.sol
7interface IERC2612Permit {
8 /**
9 * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens,
10 * given `owner`'s signed approval.
11 *
12 * IMPORTANT: The same issues {IERC20-approve} has related to transaction
13 * ordering also apply here.
14 *
15 * Emits an {Approval} event.
16 *
17 * Requirements:
18 *
19 * - `owner` cannot be the zero address.
20 * - `spender` cannot be the zero address.
21 * - `deadline` must be a timestamp in the future.
22 * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
23 * over the EIP712-formatted function arguments.
24 * - the signature must use ``owner``'s current nonce (see {nonces}).
25 *
26 * For more information on the signature format, see the
27 * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
28 * section].
29 */
30 function permit(
31 address owner,
32 address spender,
33 uint256 amount,
34 uint256 deadline,
35 uint8 v,
36 bytes32 r,
37 bytes32 s
38 ) external;
39
40 /**
41 * @dev Returns the current ERC2612 nonce for `owner`. This value must be
42 * included whenever a signature is generated for {permit}.
43 *
44 * Every successful call to {permit} increases ``owner``'s nonce by one. This
45 * prevents a signature from being used multiple times.
46 */
47 function nonces(address owner) external view returns (uint256);
48}
49
50abstract contract ERC20Permit is ERC20, IERC2612Permit {

Recommendation:

We advise all highlighted top-level declarations to be split into their respective code files, avoiding unnecessary imports as well as increasing the legibility of the codebase.

Alleviation:

The IERC2612Permit interface declaration has been relocated to its dedicated file and is now imported by the codebase, optimizing the project's structure.

ERC-03C: Redundant Low-Level Assembly Blocks

TypeSeverityLocation
Code StyleERC20Permit.sol:L62-L65, L115-L119

Description:

The referenced assembly block within the contract's constructor yields the chainid of the execution context, however, the same value can be extracted without an assembly block by accessing block.chainid. Additionally, the ERC20Permit::chainId function is redundant as the value can be acquired via the same syntax in other contexts.

Example:

contracts/Dependencies/ERC20Permit.sol
62uint256 chainID;
63assembly {
64 chainID := chainid()
65}

Recommendation:

We advise the block.chainid syntax to be utilized, standardizing the codebase's style and rendering the ERC20Permit::chainId function redundant.

Alleviation:

The block.chainid variable is now utilized in the ERC20Permit::constructor as advised.

ERC-04C: Variable Mutability Specifier (Immutable)

TypeSeverityLocation
Gas OptimizationERC20Permit.sol:L59, L67

Description:

The linked variable is assigned to only once during the contract's constructor.

Example:

contracts/Dependencies/ERC20Permit.sol
59bytes32 public DOMAIN_SEPARATOR;
60
61constructor() {
62 uint256 chainID;
63 assembly {
64 chainID := chainid()
65 }
66
67 DOMAIN_SEPARATOR = keccak256(
68 abi.encode(
69 keccak256(
70 "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
71 ),
72 keccak256(bytes(name())),
73 keccak256(bytes("1")), // Version
74 chainID,
75 address(this)
76 )
77 );
78}

Recommendation:

We advise it to be set as immutable greatly optimizing its read-access gas cost.

Alleviation:

The DOMAIN_SEPARATOR variable has been set as immutable, greatly optimizing its read-access gas cost.