Omniscia Gravita Protocol Audit
ERC20Permit Code Style Findings
ERC20Permit Code Style Findings
ERC-01C: Inefficient mapping
Lookups
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | ERC20Permit.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:
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
Type | Severity | Location |
---|---|---|
Code Style | ![]() | ERC20Permit.sol:L7, L50 |
Description:
The referenced file contains multiple top-level declarations that decrease the legibility of the codebase.
Example:
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 transaction13 * 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 the27 * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP28 * 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 s38 ) external;39
40 /**41 * @dev Returns the current ERC2612 nonce for `owner`. This value must be42 * included whenever a signature is generated for {permit}.43 *44 * Every successful call to {permit} increases ``owner``'s nonce by one. This45 * 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
Type | Severity | Location |
---|---|---|
Code Style | ![]() | ERC20Permit.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:
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)
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | ERC20Permit.sol:L59, L67 |
Description:
The linked variable is assigned to only once during the contract's constructor
.
Example:
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")), // Version74 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.