Open code423n4 opened 2 years ago
LOW‑1 | Missing Checks for Address(0x0) | 18 L
LOW‑2 | Use Safetransfer Instead Of Transfer | 3 TODO - M-01
LOW‑3 | Vulnerable To Cross-chain Replay Attacks Due To Static DOMAIN_SEPARATOR | 1 L
LOW‑4 | Contracts are not using their OZ Upgradeable counterparts | 9 R
LOW‑5 | Critical Changes Should Use Two-step Procedure | 4 NC
LOW‑6 | Low Level Calls With Solidity Version 0.8.14 Can Result In Optimiser Bug | 2 Disputed, these are fine
LOW‑7 | Missing parameter validation | Already as part of L-1
LOW‑8 | Usage of payable.transfer can lead to loss of funds | 1 L
LOW‑9 | Upgrade OpenZeppelin Contract Dependency | 2 R
LOW‑10 | ecrecover may return empty address | 1 R
LOW‑11 | transferOwnership Should Be Two Step See L-5
NC‑1 | Event Is Missing Indexed Fields | 2 Disputed as 50% incorrect
NC‑2 | Public Functions Not Called By The Contract Should Be Declared External Instead | 1 R
NC‑3 | Constants Should Be Defined Rather Than Using Magic Numbers | 1 Disagre for instance given
NC‑4 | require() / revert() Statements Should Have Descriptive Reason Strings | 4 NC
NC‑5 | Implementation contract may not be initialized | 1 R
NC‑6 | Large multiples of ten should use scientific notation | 1 Disputed for that instance
NC‑7 | Use of Block.Timestamp | 1 Disagree with unfounded take
NC‑8 | Non-usage of specific imports | 7 NC
NC‑9 | Expressions for constant values such as a call to keccak256(), should use immutable rather than constant | 5 Nope https://github.com/GalloDaSballo/Braindead-Gas-Savings NC‑10 | Lines are too long | 1 NC
NC‑11 | Use bytes.concat() | 4 Disagree
NC‑12 | Use of ecrecover is susceptible to signature malleability | 1 Already agreed above
NC‑13 | Stop using v != 27 && v != 28 or v == 27 || v == 28 | 1 Same
NC‑14 | Prevent accidentally burning tokens Disagree without explaining how the buyer or seller would be the 0 address
3L 5R 4NC
Summary
Low Risk Issues
payable.transfer
can lead to loss of fundsecrecover
may return empty addresstransferOwnership
Should Be Two StepTotal: 41 instances over 9 issues
Non-critical Issues
require()
/revert()
Statements Should Have Descriptive Reason Stringskeccak256()
, should useimmutable
rather thanconstant
bytes.concat()
ecrecover
is susceptible to signature malleabilityv != 27 && v != 28
orv == 27 \|\| v == 28
Total: 30 instances over 13 issues
Low Risk Issues
[LOW‑1] Missing Checks for Address(0x0)
Lack of zero-address validation on address parameters may lead to transaction reverts, waste gas, require resubmission of transactions and may even force contract redeployments in certain cases within the protocol.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L95
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L95
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L36
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L45
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L73
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L73
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L73
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L88
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L88
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L88
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L104
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L104
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L104
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L119
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L119
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L119
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/PolicyManager.sol#L25
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/PolicyManager.sol#L36
Recommended Mitigation Steps
Consider adding explicit zero-address validation on input parameters of address type.
[LOW‑2] Use Safetransfer Instead Of Transfer
It is good to add a
require()
statement that checks the return value of token transfers or to use something like OpenZeppelin’ssafeTransfer
/safeTransferFrom
unless one is sure the given token reverts in case of a failure. Failure to do so will cause silent failures of transfers and affect token accounting in contract.For example, Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. For example Tether (USDT)'s transfer() and transferFrom() functions do not return booleans as the specification requires, and instead have no return value. When these sorts of tokens are cast to IERC20, their function signatures do not match and therefore the calls made, revert.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L508
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L78
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L125
Recommended Mitigation Steps
Consider using
safeTransfer
/safeTransferFrom
orrequire()
consistently.[LOW‑3] Vulnerable To Cross-chain Replay Attacks Due To Static DOMAIN_SEPARATOR
The protocol calculates the chainid it should assign during its execution and permanently stores it in an immutable variable. Should Ethereum fork in the feature, the chainid will change however the one used by the permits will not enabling a user to use any new permits on both chains thus breaking the token on the forked chain permanently.
Please consult EIP1344 for more details: https://eips.ethereum.org/EIPS/eip-1344#rationale
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L106
Recommended Mitigation Steps
The mitigation action that should be applied is the calculation of the chainid dynamically on each permit invocation. As a gas optimization, the deployment pre-calculated hash for the permits can be stored to an immutable variable and a validation can occur on the permit function that ensure the current chainid is equal to the one of the cached hash and if not, to re-calculate it on the spot.
[LOW‑4] Contracts are not using their OZ Upgradeable counterparts
The non-upgradeable standard version of OpenZeppelin’s library are inherited / used by the contracts. It would be safer to use the upgradeable versions of the library contracts to avoid unexpected behaviour.
Proof of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L8
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L5
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L6
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L7
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L8
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/PolicyManager.sol#L4
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/PolicyManager.sol#L5
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/ERC1967Proxy.sol#L5
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/ERC1967Proxy.sol#L6
Recommended Mitigation Steps
Where applicable, use the contracts from @openzeppelin/contracts-upgradeable instead of @openzeppelin/contracts.
[LOW‑5] Critical Changes Should Use Two-step Procedure
The critical procedures should be two step process.
See similar findings in previous Code4rena contests for reference: https://code4rena.com/reports/2022-06-illuminate/#2-critical-changes-should-use-two-step-procedure
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L215
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L224
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L233
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L242
Recommended Mitigation Steps
Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.
[LOW‑6] Low Level Calls With Solidity Version 0.8.14 Can Result In Optimiser Bug
The project contracts in scope are using low level calls with solidity version before 0.8.14 which can result in optimizer bug. https://medium.com/certora/overly-optimistic-optimizer-certora-bug-disclosure-2101e3f7994d
Simliar findings in Code4rena contests for reference: https://code4rena.com/reports/2022-06-illuminate/#5-low-level-calls-with-solidity-version-0814-can-result-in-optimiser-bug
Proof Of Concept
POC can be found in the above medium reference url.
Functions that execute low level calls in contracts with solidity version under 0.8.14
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L548
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/MerkleVerifier.sol#L49
Recommended Mitigation Steps
Consider upgrading to at least solidity v0.8.15.
[LOW‑7] Missing parameter validation
Some parameters of constructors are not checked for invalid values.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/ERC1967Proxy.sol#L21
Recommended Mitigation Steps
Validate the parameters.
[LOW‑8] Usage of
payable.transfer
can lead to loss of fundsThe funds that are to be sent can be lost. The issues with
transfer()
are outlined here: https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L508
Recommended Mitigation Steps
Using low-level
call.value(amount)
with the corresponding result check or using the OpenZeppelinAddress.sendValue
is advised: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L60[LOW‑9] Upgrade OpenZeppelin Contract Dependency
An outdated OZ version is used (which has known vulnerabilities, see: https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories).
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/package.json#L63
https://github.com/code-423n4/2022-10-blur/tree/main/package.json#L64
Recommended Mitigation Steps
Update OpenZeppelin Contracts Usage in package.json
[LOW‑10]
ecrecover
may return empty addressThere is a common issue that
ecrecover
returns empty (0x0) address when the signature is invalid.function _recover
should check that before returning the result ofecrecover
.Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L408
Recommended Mitigation Steps
See the solution here: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/cryptography/ECDSA.sol#L68
[LOW‑11] TransferOwnership Should Be Two Step
BlurExchange.sol
is inherting theOwnableUpgradeable
contract which contains thetransferOwnership
function. Recommend considering implementing a two step process where the owner or admin nominates an account and the nominated account needs to call anacceptOwnership()
function for the transfer of ownership to fully succeed. This ensures the nominated EOA account is a valid and active account.Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L30
Recommended Mitigation Steps
Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.
Non Critical Issues
[NC‑1] Event Is Missing Indexed Fields
Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields).
Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L76
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L86
[NC‑2] Public Functions Not Called By The Contract Should Be Declared External Instead
Contracts are allowed to override their parents’ functions and change the visibility from external to public.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L181
[NC‑3] Constants Should Be Defined Rather Than Using Magic Numbers
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L59
[NC‑4]
require()
/revert()
Statements Should Have Descriptive Reason StringsProof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L134
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L183
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L452
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L513
[NC‑5] Implementation contract may not be initialized
OpenZeppelin recommends that the initializer modifier be applied to constructors. Per OZs Post implementation contract should be initialized to avoid potential griefs or exploits. https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680/5
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/ERC1967Proxy.sol#L21
[NC‑6] Large multiples of ten should use scientific notation
Use (e.g. 1e6) rather than decimal literals (e.g. 100000), for better code readability.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L59
[NC‑7] Use of Block.Timestamp
Block timestamps have historically been used for a variety of applications, such as entropy for random numbers (see the Entropy Illusion for further details), locking funds for periods of time, and various state-changing conditional statements that are time-dependent. Miners have the ability to adjust timestamps slightly, which can prove to be dangerous if block timestamps are used incorrectly in smart contracts. References: SWC ID: 116
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L283
Recommended Mitigation Steps
Block timestamps should not be used for entropy or generating random numbers—i.e., they should not be the deciding factor (either directly or through some derivation) for winning a game or changing an important state.
Time-sensitive logic is sometimes required; e.g., for unlocking contracts (time-locking), completing an ICO after a few weeks, or enforcing expiry dates. It is sometimes recommended to use block.number and an average block time to estimate times; with a 10 second block time, 1 week equates to approximately, 60480 blocks. Thus, specifying a block number at which to change a contract state can be more secure, as miners are unable to easily manipulate the block number.
[NC‑8] Non-usage of specific imports
The current form of relative path import is not recommended for use because it can unpredictably pollute the namespace. Instead, the Solidity docs recommend specifying imported symbols explicitly. https://docs.soliditylang.org/en/v0.8.15/layout-of-source-files.html#importing-other-source-files
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L10
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L11
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L12
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L13
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L14
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L15
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L16
Recommended Mitigation Steps
Use specific imports syntax per solidity docs recommendation.
[NC‑9] Expressions for constant values such as a call to
keccak256()
, should useimmutable
rather thanconstant
While it doesn't save any gas because the compiler knows that developers often make this mistake, it's still best to use the right tool for the task at hand. There is a difference between
constant
variables andimmutable
variables, and they should each be used in their appropriate contexts.constants
should be used for literal values written into the code, andimmutable
variables should be used for expressions, or values calculated in, or passed into the constructor.Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#L20
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#L23
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#L26
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#L29
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#L33
[NC‑10] Lines are too long
Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length Reference: https://docs.soliditylang.org/en/v0.8.10/style-guide.html#maximum-line-length
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/ERC1967Proxy.sol#L11
[NC‑11] Use
bytes.concat()
Solidity version 0.8.4 introduces
bytes.concat()
(vsabi.encodePacked(<bytes>,<bytes>)
)Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#L80
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#0
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#0
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/lib/EIP712.sol#0
[NC‑12] Use of
ecrecover
is susceptible to signature malleabilityThe built-in EVM precompile
ecrecover
is susceptible to signature malleability, which could lead to replay attacks. References: https://swcregistry.io/docs/SWC-117, https://swcregistry.io/docs/SWC-121, and https://medium.com/cryptronics/signature-replay-vulnerabilities-in-smart-contracts-3b6f7596df57. While this is not immediately exploitable, this may become a vulnerability if used elsewhere.Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L408
Recommended Mitigation Steps
Consider using OpenZeppelin’s ECDSA library (which prevents this malleability) instead of the built-in function.
[NC‑13] Stop using
v != 27 && v != 28
orv == 27 || v == 28
See this for reference
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L407
[NC‑14] Prevent accidentally burning tokens
Transferring tokens to the zero address is usually prohibited to accidentally avoid “burning” tokens by sending them to an unrecoverable zero address.
Proof Of Concept
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/BlurExchange.sol#L508
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L78
https://github.com/code-423n4/2022-10-blur/tree/main/contracts/ExecutionDelegate.sol#L125
Recommended Mitigation Steps
Consider adding a check to prevent accidentally burning tokens here