Open code423n4 opened 2 years ago
Lock-in Fee with Order Creation
Duplicate: Admin can change fee at any time for existing orders: https://github.com/code-423n4/2022-06-putty-findings/issues/422
Malicious Token Risk
Duplicate: Setting malicious or invalid erc721Assets, erc20Assets or floorTokens prevents the option from being exercised: https://github.com/code-423n4/2022-06-putty-findings/issues/50
high quality report
Question for "Slightly incorrect EIP-712 Definition".
Is incorrect (if slightly), as the EIP-712 compliant implementation would have the parenthesis on a separate line. While the closing parenthesis would be with the last entry
What do you mean by this? From the quoted spec it looks like the closing parentheses should be on the same line? (which is how it is currently). So I don't see what the issue is here.
Executive Summary
Code is well written, fully documented and coverage is high
The codebase could benefit with a few small refactoring to further simplify and to save extra gas
Use
treasury
for receiving fundsMost of the times a DAO ends up separating the
owner
, the Multisig with execution power, from thetreasury
the multisig to handle fees and funds.The contract is currently using
owner
to handle settings as well as receive funds, it may be preferable to separate that by addingtreasury
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L500-L501
Simplify Value Comparison - Saves some bytecode and makes logic leaner
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L495-L496
Can be refactored with
As in both case they were both true or both false
Consequence of Smart Comparison Above - Saves 20 to 80 gas (avg is 60)
Because of the gas save above we can refactor the entire block to an if / else
Can be refactored to
Lock-in Fee with Order Creation
TL;DR: Fee could change mid order, it's also more gas efficient to store them in the order struct
Fee for orders are calculated at time of
withdraw
, however the order taker may have accepted the order at a time in which thefee
was different, this can create a difference in their PnL.Because order validation is done on creation and only the hash is stored onChain, it may be desirable to add a
order.fee
to the order struct, and then use that fee instead of the one from storage.https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L498-L501
This will also save 2.1k in by avoiding one SLOAD during
withdraw
Exercise - order.isLong can fail earlier
Can move
require(order.isLong, "Can only exercise long positions");
to the first line to make it fail fasterThis would be consistent with how
withdraw
is writtenSlightly incorrect EIP-712 Definition
Quoting the standard for a Struct
It follows that the definition provided:
Is incorrect (if slightly), as the EIP-712 compliant implementation would have the parenthesis on a separate line. While the closing parenthesis would be with the last entry
ERC-712 Compliant
I've tested on 0.8.13 and because of
encodePacked
there will be no difference in the produced typeMalicious Token Risk
Am adding this because from my experience other wardens will submit such findings, and I don't want to lose points, although I don't believe there's any real risk beside the need to inform end-users that any token can be used with the Smart Contract.
Because of the open ended nature, any malicious token (revert on transfer, wrong accounting, deceiving name), could be used, and it's up to the caller (maker / taker) to verify all the addresses.
I think the finding should be at most Non-Critical (Informational)
Avoid Magic_Values
These values would be easier to maintain, understand and parse through if they were constants, ideally in ALL_CAPS
30
1000
Public Visibility for External Functions
Most of these functions are not called by the contract, yet they have
public
visibility, there is no additional cost to this, however you'd always want to mark functions meant to be called from outside asexternal
acceptCounterOffer
batchFillOrder
withdraw
exercise