Shell Protocol - bin2chen's results

Shell Protocol is DeFi made simple. Enjoy powerful one-click transactions, unbeatably capital-efficient AMMs, and a modular developer experience.

General Information

Platform: Code4rena

Start Date: 27/11/2023

Pot Size: $36,500 USDC

Total HM: 0

Participants: 22

Period: 8 days

Judge: 0xA5DF

Id: 308

League: ETH

Shell Protocol

Findings Distribution

Researcher Performance

Rank: 6/22

Findings: 1

Award: $814.56

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: peanuts

Also found by: 0xmystery, EV_om, IllIllI, Udsen, bin2chen, lsaudit, oakcobalt

Labels

bug
grade-b
QA (Quality Assurance)
sufficient quality report
Q-08

Awards

814.5609 USDC - $814.56

External Links

Findings Summary

LabelDescription
L-01primitiveOutputAmount() dust outputAmount residue in Curve2PoolAdapter
L-02_erc721Unwrap() Anyone can borrow NFT for free for voting/NFT verification
L-03Use isApprovedForAll permission to restrict forwardedDoInteraction(), posing a significant financial risk to users
L-04approveToken() If the token is USDT, it may not be executable

[L-01] primitiveOutputAmount() dust outputAmount residue in Curve2PoolAdapter

In Curve2PoolAdapter.primitiveOutputAmount() When outputToken's decimals > 18, it will be converted to 18, and the truncated dust will remain in the contract forever, never to be taken out. If accumulated over time, it may lock up a considerable amount of residual token in the contract. It is suggested to add a method for administrators to take away these dust.

    function primitiveOutputAmount(
        uint256 inputToken,
        uint256 outputToken,
        uint256 inputAmount,
        bytes32 minimumOutputAmount
    )
        internal
        override
        returns (uint256 outputAmount)
    {
...
@>      outputAmount = _convertDecimals(decimals[outputToken], NORMALIZED_DECIMALS, rawOutputAmount);

        if (uint256(minimumOutputAmount) > outputAmount) revert SLIPPAGE_LIMIT_EXCEEDED();

        if (action == ComputeType.Swap) {
            emit Swap(inputToken, inputAmount, outputAmount, minimumOutputAmount, primitive, true);
        } else if (action == ComputeType.Deposit) {
            emit Deposit(inputToken, inputAmount, outputAmount, minimumOutputAmount, primitive, true);
        } else {
            emit Withdraw(outputToken, inputAmount, outputAmount, minimumOutputAmount, primitive, true);
        }
    }

[L-02]_erc721Unwrap() Anyone can borrow NFT for free for voting/NFT verification and other applications that require NFT identity

Some NFTs will be used for identity verification. Currently, anyone can borrow NFT (through ERC721Unwarp and then ERC721warp) and perform identity verification, etc., in the custom onERC1155Received(). It is suggested to verify the real ownership of NFT when Unwarp.

    function _erc721Unwrap(address tokenAddress, uint256 tokenId, address userAddress, uint256 oceanId) private {

+       require(balanceOf(userAddress,oceanId)==1 ,"Not Your NFT");
        IERC721(tokenAddress).safeTransferFrom(address(this), userAddress, tokenId);
        emit Erc721Unwrap(tokenAddress, tokenId, userAddress, oceanId);
    }

[L-03] Use isApprovedForAll permission to restrict forwardedDoInteraction(), posing a significant financial risk to users

Currently, authorized users (isApprovedForAll()==true) can operate other users' Ocean:ERC1155 through forwardedDoInteraction(). But this user can also transfer the token that this user has not yet transferred into Ocean:ERC1155 through ERC20Wrap. This is a very dangerous permission, far greater than just operating Ocean:ERC1155 itself.

For example: Currently, Alice has 1000 BTC, and owns 1 Ocean:ERC1155, this Ocean:ERC1155 corresponds to 1 BTC.

  1. Alice executes Ocean:ERC1155.setApprovalForAll(bob), mistakenly thinking that bob can only operate Ocean:ERC1155, which is worth 1 btc.
  2. But bob can transfer the 1000 BTC in alice's wallet into Ocean:ERC1155 through forwardedDoInteraction()->ERC20Wrap.
  3. bob then transfers away 1001 Ocean:ERC1155.

The price bob can operate is far greater than 1 btc.

It is suggested to add other permissions, do not use ERC1155's isApprovedForAll(). For example, add a new permission: ApprovedOcean, and note the risk in the document, this can operate any funds in the user's wallet.

[L-04]_approveToken() If the token is USDT, it may not be executable

Currently, Curve2PoolAdapter._approveToken is executed using IERC20Metadata.approve(). But similar to USDT, the approve() method definition does not return. This leads to the use of IERC20Metadata.approve() will always revert.

It is recommended to use oz's safeApprove().

#0 - c4-pre-sort

2023-12-10T20:18:23Z

raymondfam marked the issue as sufficient quality report

#1 - 0xA5DF

2023-12-16T11:48:57Z

3L, 1R

LabelDescriptionSeverity
L-01primitiveOutputAmount() dust outputAmount residue in Curve2PoolAdapterL
L-02_erc721Unwrap() Anyone can borrow NFT for free for voting/NFT verificationL
L-03Use isApprovedForAll permission to restrict forwardedDoInteraction(), posing a significant financial risk to usersL
L-04approveToken() If the token is USDT, it may not be executableR

#2 - c4-judge

2023-12-17T12:12:54Z

0xA5DF marked the issue as grade-c

#3 - c4-judge

2023-12-18T09:10:14Z

0xA5DF marked the issue as grade-a

#4 - c4-judge

2023-12-21T17:24:30Z

0xA5DF 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