Decent - ZdravkoHr's results

Decent enables one-click transactions using any token across chains.

General Information

Platform: Code4rena

Start Date: 19/01/2024

Pot Size: $36,500 USDC

Total HM: 9

Participants: 113

Period: 3 days

Judge: 0xsomeone

Id: 322

League: ETH

Decent

Findings Distribution

Researcher Performance

Rank: 37/113

Findings: 4

Award: $122.24

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DcntEth.sol#L20-L22

Vulnerability details

Impact

DcntEth.setRouter is used to change the router address. The router is a privileged role that can mint and burn DcntEth tokens. setRouter can be called by anyone, meaning that a malicious user can create his own router which behaves the same as the original one, but with 1 change - he will add a function that allows him to mint/burn wherever they want. This can be unnoticed for a long time. The user will then have control over the whole protcol.

Proof of Concept

    function testAnyoneCanChangeRouter() public {
        vm.prank(address(0xb0b));
        dcntEth.setRouter(address(weth));
        assertEq(dcntEth.router(), address(weth));
    }

Tools Used

Foundry

Add the onlyOwner modifier to DcntEth.setRouter()

-    function setRouter(address _router) public {
+    function setRouter(address _router) public onlyOwner {
        router = _router;
    }

Assessed type

Access Control

#0 - c4-pre-sort

2024-01-25T03:30:14Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-25T03:30:33Z

raymondfam marked the issue as duplicate of #14

#2 - c4-judge

2024-02-03T13:10:03Z

alex-ppg marked the issue as satisfactory

Findings Information

Awards

78.6887 USDC - $78.69

Labels

bug
3 (High Risk)
partial-75
sufficient quality report
upgraded by judge
duplicate-436

External Links

Lines of code

https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentBridgeExecutor.sol#L35-L38 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentBridgeExecutor.sol#L62-L64

Vulnerability details

Impact

Smart contracts that interact with the protocol may not receive their refund in case a transaction fails on the destination chain. This is because refunds are sent to the from address of the source chain. Smart contacts are not guaranteed to have the same address on different chains. This means that any funds sent to from address that is not controlled by the protocol interacting with Decent will probably be lost.

Proof of Concept

There are two (Gnosis) Safes controlled by a protocol on two different chains. Since they are smart contracts, their addresses can be different. The protocol wants to use Decent for cross-chain execution. For some reason, their transaction fails on the destination chain.

DecentBridgeExecutor will send the funds to the from address

    function _executeEth(
        address from,
        address target,
        uint256 amount,
        bytes memory callPayload
    ) private {
        weth.withdraw(amount);
        (bool success, ) = target.call{value: amount}(callPayload);
        if (!success) {
            // here
            payable(from).transfer(amount);
        }
    }

This from will be different from the address of the smart contract on the currentChain. Funds will be send to the wrong address and will be lost.

Tools Used

Add a new parameter address destinationRefund that can be specified on the source chain. Then use it instead of from.

 if (!success) {
-            payable(from).transfer(amount);
+            payable(destinationRefund).transfer(amount);
 }

Assessed type

Other

#0 - c4-pre-sort

2024-01-25T05:17:21Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-25T05:17:30Z

raymondfam marked the issue as duplicate of #27

#2 - c4-judge

2024-02-02T17:21:32Z

alex-ppg marked the issue as partial-75

#3 - c4-judge

2024-02-04T23:04:04Z

alex-ppg changed the severity to 3 (High Risk)

Findings Information

Awards

43.4302 USDC - $43.43

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
duplicate-262

External Links

Lines of code

https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L171

Vulnerability details

Impact

Any refunds from LayerZero will be sent to DecentBridgeAdapter, not to the initiator of the action. The adapter does not have any way to send this funds to the correct recipient, so they will be left in the contract, available for further use by other users.

Proof of Concept

  1. User X wants to use DecentBridgeAdapter to execute a cross-chain action.
  2. He calls UTB.bridgeAndExecute().
  3. UTB.bridgeAndExecute calls UTB.callBridge(), which makes an internal call to DecentBridgeAdapter.bridge() and sends native tokens for gas.
            IBridgeAdapter(bridgeAdapters[instructions.bridgeId]).bridge{
                value: bridgeFee + (native ? amt2Bridge : 0)
            }(...);
  1. DecentBridgeAdapter.bridge() calls DecentEthRouter.bridgeWithPayload() and forwards the native value.
        router.bridgeWithPayload{value: msg.value}(
            lzIdLookup[dstChainId],
            destinationBridgeAdapter[dstChainId],
            swapParams.amountIn,
            false,
            dstGas,
            bridgePayload
        );
  1. DecentEthRouter.bridgeWithPayload calls the internal function _bridgeWithPayload().

  2. It then constructs call parameters for layer zero and sets the refund address to msg.sender. If we look at step 4, it's clear that msg.sender is DecentBridgeAdapter. The funds will be sent to it and not to the initiator of the action, resulting in loss for the sender and profit for the next user that uses the protocol.

        ICommonOFT.LzCallParams memory callParams = ICommonOFT.LzCallParams({
            refundAddress: payable(msg.sender),
            zroPaymentAddress: address(0x0),
            adapterParams: adapterParams
        });

Tools Used

Manual Review

Instead of msg.sender, use a parameter specified by the initiator of the action.

Assessed type

Other

#0 - c4-pre-sort

2024-01-25T02:12:55Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-25T02:13:02Z

raymondfam marked the issue as duplicate of #27

#2 - c4-judge

2024-02-02T16:57:11Z

alex-ppg marked the issue as not a duplicate

#3 - c4-judge

2024-02-02T16:58:17Z

alex-ppg marked the issue as duplicate of #262

#4 - c4-judge

2024-02-02T17:01:16Z

alex-ppg marked the issue as satisfactory

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