Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QA Report #268

Open
code423n4 opened this issue May 14, 2022 · 3 comments
Open

QA Report #268

code423n4 opened this issue May 14, 2022 · 3 comments
Labels
bug Something isn't working QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax

Comments

@code423n4
Copy link
Contributor

QA Report

Table of Contents

summary

Few vulnerabilities were found examining the contracts. The main concerns are with the lack of checks in setters.

Events emitted early

PROBLEM

It is not recommended to emit events before the end of the computations, as the function might revert based on conditions ahead of the event emission

SEVERITY

Low

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol: 195 emit NewVault(vaultId, msg.sender, token);//emitted before tokens transferred to contract.
Cally.sol: 291 emit ExercisedOption(optionId, msg.sender);//emitted before tokens transferred to user.
Cally.sol: 337 emit Withdrawal(vaultId, msg.sender);//emitted before harvest() call and tokens transferred to user.
Cally.sol: 365 emit Harvested(msg.sender, amount);//emitted before ETH transferred to user.

TOOLS USED

Manual Analysis

MITIGATION

Place the event emission in the last position in the function.

Event should be emitted in setters

PROBLEM

Setters should emit an event so that Dapps can detect important changes to storage

SEVERITY

Low

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol:119: setFee(uint256 feeRate_)
Cally.sol:351: setVaultBeneficiary(uint256 vaultId, address beneficiary)

TOOLS USED

Manual Analysis

MITIGATION

Emit an event in all setters.

Function missing comments

PROBLEM

Some functions are missing comments.

SEVERITY

Non-Critical

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol:455: function tokenURI(uint256 tokenId)

CallyNft.sol

CallyNft.sol:51: function renderJSON()
CallySvg.sol:136: function renderSvg()
CallyNft.sol:236: function addressToString()

TOOLS USED

Manual Analysis

MITIGATION

Add comments to these functions

Related data should be grouped in struct

PROBLEM

When there are mappings that use the same key value, having separate fields is error prone, for instance in case of deletion or with future new fields.

SEVERITY

Non-Critical

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol:103: mapping(uint256 => Vault) private _vaults;
Cally.sol:108: mapping(uint256 => address) private _vaultBeneficiaries;

TOOLS USED

Manual Analysis

MITIGATION

Group the related data in a struct and use one mapping. For instance, for the Cally.sol mappings, the mitigation could be:

struct VaultInformation {
  Vault _vault;
  address beneficiary;
}

And it would be used as a state variable:

mapping(uint256 =>  VaultInformation) private vaultInformation;

nonReentrant modifier unused

PROBLEM

Some external functions calling the ERC20 methods safeTransfer or safeTransferFrom do not have the nonReentrant modifier and are hence unprotected to reentrancy (besides the gas limit on the methods). No funds are directly at loss but it is best practice to avoid reentrancy altogether.

SEVERITY

Low

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol:158: function createVault()
Cally.sol:258: function exercise()
Cally.sol:368: function harvest()

TOOLS USED

Manual Analysis

MITIGATION

Use the nonReentrant modifier on these functions.

High feeRate can break core protocol function

PROBLEM

There is no maximum input value on setFee() in Cally.sol. But if the owner sets it to a uint greater than 1e18, the users will not be able to call exercice() as the function will revert, breaking the protocol's functionality.

SEVERITY

Low

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol:284: fee = (msg.value * feeRate) / 1e18;

If feeRate is set so that ethBalance[getVaultBeneficiary(vaultId)] + msg.value < fee, and the following statement will revert

Cally.sol:289: ethBalance[getVaultBeneficiary(vaultId)] += msg.value - fee;

TOOLS USED

Manual Analysis

MITIGATION

Add a check in setFee to ensure the new fee rate is less than a maximum maxFeeRate. Its value depends on different factors, but considering it determines how much ETH a vault creator is receiving from a strike, it should be reasonably low (ie less than 0.5 * 1e18)

Unchecked inputs

PROBLEM

Setters should check the input value - ie make revert if it is the zero address. Here, if the vault beneficiary is set as the zero address, all the strike ETH associated with the vault will be locked.

SEVERITY

Low

PROOF OF CONCEPT

Instances include:

Cally.sol

Cally.sol:351: setVaultBeneficiary()

TOOLS USED

Manual Analysis

MITIGATION

Add a zero address check

@code423n4 code423n4 added bug Something isn't working QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax labels May 14, 2022
code423n4 added a commit that referenced this issue May 14, 2022
@outdoteth
Copy link
Collaborator

this can be bumped to medium severity:
High feeRate can break core protocol function; #48

@HardlyDifficult
Copy link
Collaborator

Merging with #271

@HardlyDifficult
Copy link
Collaborator

Moved High feeRate to #325

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
Projects
None yet
Development

No branches or pull requests

3 participants