Blur Exchange contest - ajtra's results

An NFT exchange.

General Information

Platform: Code4rena

Start Date: 11/11/2022

Pot Size: $36,500 USDC

Total HM: 5

Participants: 62

Period: 3 days

Judge: berndartmueller

Id: 181

League: ETH

Blur Exchange

Findings Distribution

Researcher Performance

Rank: 43/62

Findings: 2

Award: $55.62

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

33.4034 USDC - $33.40

Labels

bug
2 (Med Risk)
downgraded by judge
partial-50
edited-by-warden
duplicate-90

External Links

Lines of code

https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L216

Vulnerability details

Impact

_returnDust doesn't check that the call has been sucesfully. For example, if the buyer is a contract could fail during the reception but due to _returnDust doesn't check the return value to revert the transaction in case of failure the tokens could be missed.

Tools Used

Manual reviewed

Check the return value callStatus

#0 - trust1995

2022-11-14T22:07:22Z

Dup of #185

#1 - c4-judge

2022-11-16T11:57:32Z

berndartmueller marked the issue as duplicate of #90

#2 - c4-judge

2022-11-16T11:58:19Z

berndartmueller marked the issue as partial-50

#3 - c4-judge

2022-12-06T14:17:26Z

berndartmueller changed the severity to 2 (Med Risk)

Awards

22.2155 USDC - $22.22

Labels

bug
G (Gas Optimization)
grade-b
G-20

External Links

Index

  1. Require / Revert strings longer than 32 bytes cost extra gas
  2. I = I + (-) X is cheaper in gas cost than I += (-=) X
  3. Use unchecked in for/while loops when it's not possible to overflow
  4. Modifiers that are used just once waste gas
  5. Use unchecked in operation that can not be overflow/underflow
  6. Remove variables that are used once
  7. Public functions not used inside the contract should be external

Details

1. Require / Revert strings longer than 32 bytes cost extra gas

Description

Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas

Lines in the code

Exchange.sol#L49 Exchange.sol#L295 Exchange.sol#L604 Pool.sol#L63

2. I = I + (-) X is cheaper in gas cost than I += (-=) X

Description

In the following example (optimizer = 10000) it's possible to demostrate that I = I + X cost less gas than I += X in state variable.

contract Test_Optimization {
    uint256 a = 1;
    function Add () external returns (uint256) {
        a = a + 1;
        return a;
    }
}

contract Test_Without_Optimization {
    uint256 a = 1;
    function Add () external returns (uint256) {
        a += 1;
        return a;
    }
}
  • Test_Optimization cost is 26324 gas
  • Test_Without_Optimization cost is 26440 gas

With this optimization it's possible to save 116 gas

Lines in the code

Exchange.sol#L316 Exchange.sol#L574 Exchange.sol#L601 Pool.sol#L36 Pool.sol#L46 Pool.sol#L73 Pool.sol#L74

3. Use unchecked in for/while loops when it's not possible to overflow

Description

Use unchecked { i++; } or unchecked{ ++i; } when it's not possible to overflow to save gas.

Lines in the code

Exchange.sol#L177 Exchange.sol#L184 Exchange.sol#L307 Exchange.sol#L598

4. Modifiers that are used just once waste gas

Description

It's possible to save gas (due to JUMP operation) removing the modifier that are used just once in the code and inlined the code.

Lines in the code

Exchange.sol#L48-L51

5. Use unchecked in operation that can not be overflow/underflow

Description

Operations that could not be overflow/underflow due to an if or require could be unchecked to save gas.

Lines in the code

Exchange.sol#L574 Exchange.sol#L607 Pool.sol#L46 Pool.sol#L73

6. Remove variables that are used once

Description

Local variables that are used once could be removed.

-	uint256 receiveAmount = price - totalFee;
-	return (receiveAmount);
+	return (price - totalFee);

Exchange.sol#L607-L608

-	bool success = IPool(POOL).transferFrom(from, to, amount);
-	require(success, "Pool transfer failed");
+	require(IPool(POOL).transferFrom(from, to, amount), "Pool transfer failed");

Exchange.sol#L635-L636

7. Public functions not used inside the contract should be external

Description

Public functions needs to write all of the arguments to memory is that public functions may be called internally, which is an entirely different process than external calls. Internal calls are executed via jumps in the code and when the compiler generates the code for an internal function is expected to have its arguments located in memory.

For external functions, the compiler doesn't need to allow internal calls, and so it allows arguments to be read directly from calldata, saving the copying step.

Lines in the code

Pool.sol#L44 Pool.sol#L58 Pool.sol#L79 Pool.sol#L83

#0 - c4-judge

2022-11-17T14:06:26Z

berndartmueller marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter