Reach out for an audit or to learn more about Macro
or Message on Telegram

TreasureDAO A-6

Security Audit

July 15th, 2024

Version 1.0.0

Presented by 0xMacro

Table of Contents

Introduction

This document includes the results of the security audit for Treasure DAO's smart contract code as found in the section titled ‘Source Code’. The security audit was performed by the Macro security team from June 20, 2024 to July 2, 2024.

The purpose of this audit is to review the source code of certain Treasure DAO Solidity contracts, and provide feedback on the design, architecture, and quality of the source code with an emphasis on validating the correctness and security of the software in its entirety.

Disclaimer: While Macro’s review is comprehensive and has surfaced some changes that should be made to the source code, this audit should not solely be relied upon for security, as no single audit is guaranteed to catch all possible bugs.

Overall Assessment

The following is an aggregation of issues found by the Macro Audit team:

Severity Count Acknowledged Won't Do Addressed
Low 1 1 - -
Code Quality 3 3 - -
Informational 1 1 - -
Gas Optimization 2 2 - -

Treasure DAO was quick to respond to these issues.

Specification

Our understanding of the specification was based on the following sources:

Source Code

The following source code was reviewed during the audit:

Specifically, we audited the following contract within this repository:

Contract SHA256
src/Rewards/StakingContractMainnet.sol

7cbc8ea8a1e5edeff14bcd0c73a87fc919234afd9d3b3290aa77d4eb0f0383d8

src/Rewards/libraries/FullMath.sol

2a5de8f6fdc3582740d383f67b27f547281590e9bb04d84da3e4c56a352a964c

src/Rewards/libraries/PackedUint144.sol

3d8d74835f2946f609b3aa929994c1aeab60f3ed2da275a7e24ec96ec5e872d2

src/Router/IMagicSwapV2Router.sol

2ffe8fc7f03054e609cb2620fe627fcbd0468fc11b2a70a7a04757cd1351bc53

src/Router/MagicSwapV2Router.sol

e1720511ad0a848ac5f8f39106dc665f0f363d7d2dcd2fee0847259208fef905

src/UniswapV2/core/UniswapV2ERC20.sol

b1af37edd188e5f6d6fdd30c5c6b77061e8fa10c0bd8529041943d294f462896

src/UniswapV2/core/UniswapV2Factory.sol

f0718339653d3192e43a6c923545f4af93e93422b171fbcd2609b6f8c8e3fbf8

src/UniswapV2/core/UniswapV2Pair.sol

7da07770196c1741e9074d7a898dbea9edd2a656b91929b70bae8585a7fc22f6

src/UniswapV2/core/interfaces/IUniswapV2Callee.sol

206e8cbbad806327cf9698144910a0eba142b7c177b080e34ef8260a49cddd4c

src/UniswapV2/core/interfaces/IUniswapV2ERC20.sol

1ffef2a9d2d1c94d2ecb76941abdf7d99ca4fd254668e9f7363bbf74b4ca0b81

src/UniswapV2/core/interfaces/IUniswapV2Factory.sol

6ca36b936fcbd706407620b0462555e05d0e9d163abdb7bc079a8e48d9a343ff

src/UniswapV2/core/interfaces/IUniswapV2Pair.sol

35c9ca4f12241cc79d5bbd203658665c706bdb70f301a951c9c7cc3d4e917f56

src/UniswapV2/core/libraries/Oracle.sol

a407aa6429d6f1e23d4e0551a052b5bd63cae6887724d1d425f54d42928b7b1c

src/UniswapV2/core/libraries/SafeMath.sol

f4896274d9eec04f4d5bfc90df2cb127fa11b58dea85125f88e5d99b5ff69e5d

src/UniswapV2/core/libraries/UQ112x112.sol

21c520df313335273cd20721812975a0d3a2684027710fbf09fcaff5d4db6e56

src/UniswapV2/core/libraries/UniswapV2Math.sol

41848de7a9cf0e2d9e29284cb36044749936d85580892b0d1d606f378a2737c8

src/UniswapV2/libraries/Babylonian.sol

661466a5adb3390a624207654fdb8f5357e5d186179ee0f05a8f122000b4b69f

src/UniswapV2/libraries/BitMath.sol

efd189eea67401b741d9845a5a55ff59e03f2f6f523c089e1758f37a636926fa

src/UniswapV2/libraries/FullMath.sol

819ae9982bc0a7b3d9c362bc0f0b119aad243feac805e58ebcb1203123230842

src/UniswapV2/libraries/TransferHelper.sol

96ce38945adb19c77800ae72db0c9dc3e4b3f31b94671258d0ba28096cbfbf8a

src/UniswapV2/periphery/UniswapV2Router02.sol

f234f4953d8c5c592ba9c7948fdc5df0e5384547b9b4f1bc963bfb1edfa28a08

src/UniswapV2/periphery/interfaces/IERC20.sol

a63503906469cad7fbf111d930e705c0a744775df43557d2ff4d4d2a541a4177

src/UniswapV2/periphery/interfaces/IUniswapV2Router01.sol

155f2539137e65a41c5ebebc27514339a2c6c39fce72d32cba4dfd36a7134377

src/UniswapV2/periphery/interfaces/IWETH.sol

e8044b905d57a0d9a3c38af15bd85ecd0a03c9d1cd0f8db64619ae45fd6ce489

src/UniswapV2/periphery/libraries/OracleLibrary.sol

0eb43ff4ca68e3834a702bbaf15ff4119957466466bc52d6261cb5dcffaae0b0

src/UniswapV2/periphery/libraries/UniswapV2Library.sol

da4c0c475ee37f0a1bb9633b2c3d9f44985853fccdc6a025edae33f3cee7bfb6

src/Vault/INftVault.sol

8be4c058d3c828a367e5493804b432b7952916283a90cc816a8d78563973a809

src/Vault/INftVaultFactory.sol

5e1111a1abd38a85cf870b66da66807e90c0ad35d7726a34a1443243e74b0b81

src/Vault/NftVault.sol

12135c3fa19f4be1e9c19d3ad934df04dd91470b7b34443368bf73a2211ac94e

src/Vault/NftVaultFactory.sol

d5616c18262aeb58710f8e3c75ef437f1f4ff65ac5682dd4512208f752fb50b7

Note: This document contains an audit solely of the Solidity contracts listed above. Specifically, the audit pertains only to the contracts themselves, and does not pertain to any other programs or scripts, including deployment scripts.

Issue Descriptions and Recommendations

Click on an issue to jump to it, or scroll down to see them all.

Security Level Reference

We quantify issues in three parts:

  1. The high/medium/low/spec-breaking impact of the issue:
    • How bad things can get (for a vulnerability)
    • The significance of an improvement (for a code quality issue)
    • The amount of gas saved (for a gas optimization)
  2. The high/medium/low likelihood of the issue:
    • How likely is the issue to occur (for a vulnerability)
  3. The overall critical/high/medium/low severity of the issue.

This third part – the severity level – is a summary of how much consideration the client should give to fixing the issue. We assign severity according to the table of guidelines below:

Severity Description
(C-x)
Critical

We recommend the client must fix the issue, no matter what, because not fixing would mean significant funds/assets WILL be lost.

(H-x)
High

We recommend the client must address the issue, no matter what, because not fixing would be very bad, or some funds/assets will be lost, or the code’s behavior is against the provided spec.

(M-x)
Medium

We recommend the client to seriously consider fixing the issue, as the implications of not fixing the issue are severe enough to impact the project significantly, albiet not in an existential manner.

(L-x)
Low

The risk is small, unlikely, or may not relevant to the project in a meaningful way.

Whether or not the project wants to develop a fix is up to the goals and needs of the project.

(Q-x)
Code Quality

The issue identified does not pose any obvious risk, but fixing could improve overall code quality, on-chain composability, developer ergonomics, or even certain aspects of protocol design.

(I-x)
Informational

Warnings and things to keep in mind when operating the protocol. No immediate action required.

(G-x)
Gas Optimizations

The presented optimization suggestion would save an amount of gas significant enough, in our opinion, to be worth the development cost of implementing it.

Issue Details

L-1

Incorrect data emitted in IncentiveUpdated event

Topic
Events
Status
Acknowledged
Impact
Low
Likelihood
Low

In the StakingContractMainnet:updateIncentive() function, the IncentiveUpdated() event is emitted at the end of the execution in the following way.

emit IncentiveUpdated(incentiveId, changeAmount, incentive.lastRewardTime, incentive.endTime);

However, the changeAmount argument does not, in all cases, represent the actual amount with which the incentive was updated. In the scenario where the change amount is less than 0, and its absolute value is greater than the remaining reward, the actual change amount would equal the value of rewardRemaining.

    } else if (changeAmount < 0) {
      uint112 transferOut = uint112(-changeAmount);
>>    if (transferOut > incentive.rewardRemaining) transferOut = incentive.rewardRemaining;
      unchecked { incentive.rewardRemaining -= transferOut; }
      ERC20(incentive.rewardToken).safeTransfer(msg.sender, transferOut);
    }

Remediations to consider

  • Update IncentiveUpdated() event emission to send the proper changeAmount value in all scenarios so that off-chain monitoring and tracking tools have the correct input data.
Q-1

Redundant validation checks can be replaced with internal function

Topic
Best practices
Status
Acknowledged
Quality Impact
Low

Consider replacing following check across the contract with call to new function _validIncentiveId().

if (incentiveId > incentiveCount || incentiveId <= 0) revert InvalidInput();

New function

function _validIncentiveId(uint256 incentiveId) internal returns(bool) {
    return incentiveId != 0 && incentiveId <= incentiveCount;
}

Update current checks with the following:

if(!_validIncentiveId(incentiveId)) revert InvalidInput();
Q-2

Unnecessary checks for uint not being less than 0

Topic
Best practices
Status
Acknowledged
Quality Impact
Low

Instances:

  • createIncentive() - reward amount cannot be less than 0 since it is uint112.

    if (rewardAmount <= 0) revert InvalidInput();
    
  • subscribeToIncentive(), accrueRewards(), claimRewards() - incentiveId cannot be less than 0 since it is uint256.

    if (incentiveId > incentiveCount || incentiveId <= 0) revert InvalidInput();
    
  • subscribeToIncentive() - referenced value cannot be less than 0 since it is uint112.

    if (userStakes[msg.sender][incentive.token].liquidity <= 0) revert NotStaked();
    
Q-3

Event may be emitted without any state updates

Topic
Best practices
Status
Acknowledged
Quality Impact
Low

In updateIncentive() - when changeAmount, newStartTime, and newEndTime are all zeros, IncentiveUpdate event will be emitted even though no changes have been performed.

Also, in stake() and unstake() when amount is 0, Stake() and Unstake() events may be emitted, without corresponding state updates.

Since events without state update may negatively impact off-chain tracking tools, consider updating implementation to not emit event unless at least one of the parameters has changed.

G-1

Multiple unnecessary casts

Topic
Best practices
Status
Acknowledged
Gas Savings
Low

In updateIncentive() - changeAmount is casted multiple times.

incentive.rewardRemaining += uint112(changeAmount);

ERC20(incentive.rewardToken).safeTransferFrom(msg.sender, address(this), uint112(changeAmount));

Consider assigning casted value to variable in memory and using it instead.

G-2

Unnecessary function calls

Topic
Best practices
Status
Acknowledged
Gas Savings
Low

In the StakingContractMainnet, replace _increment(i) calls with unchecked { ++i; } at the end of each loop for more efficient operation, or update contract to use Solidity version 0.8.22+ which has this optimization built in by default.

I-1

Fee-on-transfer and rebase tokens not supported

Topic
Protocol Design
Status
Acknowledged
Impact
Informational

Current StakingContractMainnet implementation, does not support fee-on-transfer tokens nor rebase tokens, as staking and reward tokens. Parties interacting with the contract are advised not to configure it with such tokens nor use incentives relying on such tokens.

Disclaimer

Macro makes no warranties, either express, implied, statutory, or otherwise, with respect to the services or deliverables provided in this report, and Macro specifically disclaims all implied warranties of merchantability, fitness for a particular purpose, noninfringement and those arising from a course of dealing, usage or trade with respect thereto, and all such warranties are hereby excluded to the fullest extent permitted by law.

Macro will not be liable for any lost profits, business, contracts, revenue, goodwill, production, anticipated savings, loss of data, or costs of procurement of substitute goods or services or for any claim or demand by any other party. In no event will Macro be liable for consequential, incidental, special, indirect, or exemplary damages arising out of this agreement or any work statement, however caused and (to the fullest extent permitted by law) under any theory of liability (including negligence), even if Macro has been advised of the possibility of such damages.

The scope of this report and review is limited to a review of only the code presented by the Treasure DAO team and only the source code Macro notes as being within the scope of Macro’s review within this report. This report does not include an audit of the deployment scripts used to deploy the Solidity contracts in the repository corresponding to this audit. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project. In this report you may through hypertext or other computer links, gain access to websites operated by persons other than Macro. Such hyperlinks are provided for your reference and convenience only, and are the exclusive responsibility of such websites’ owners. You agree that Macro is not responsible for the content or operation of such websites, and that Macro shall have no liability to your or any other person or entity for the use of third party websites. Macro assumes no responsibility for the use of third party software and shall have no liability whatsoever to any person or entity for the accuracy or completeness of any outcome generated by such software.