[G-01] State variables only set in the constructor should be declared immutable
Impact
Avoids a Gusset (20000 gas)
Findings:
2023-07-escrow-main/src/Escrow.sol::26 => State private s_state;
[G-02] Amounts should be checked for 0 before calling a transfer
Impact
Checking non-zero transfer values can avoid an expensive external call and save gas.
While this is done in some places, it’s not consistently done in the solution.
Findings:
2023-07-escrow-main/src/Escrow.sol::98 => i_tokenContract.safeTransfer(i_seller, i_tokenContract.balanceOf(address(this)));
2023-07-escrow-main/src/Escrow.sol::120 => i_tokenContract.safeTransfer(i_buyer, buyerAward);
2023-07-escrow-main/src/Escrow.sol::123 => i_tokenContract.safeTransfer(i_arbiter, i_arbiterFee);
2023-07-escrow-main/src/Escrow.sol::127 => i_tokenContract.safeTransfer(i_seller, tokenBalance);
[G-03] abi.encode()
is less efficient than abi.encodePacked()
Findings:
2023-07-escrow-main/src/EscrowFactory.sol::77 => byteCode, abi.encode(price, tokenContract, buyer, seller, arbiter, arbiterFee)
[G-04] Setting the constructor to payable
Impact
You can cut out 10 opcodes in the creation-time EVM bytecode if you declare a constructor payable. Making the constructor payable eliminates the need for an initial check of msg.value == 0
and saves 13
gas on deployment with no security risks.
Findings:
2023-07-escrow-main\src\Escrow.sol#L32-L39:
constructor(
uint256 price,
IERC20 tokenContract,
address buyer,
address seller,
address arbiter,
uint256 arbiterFee
) {