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
Rank: 48/113
Findings: 2
Award: $43.52
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: NPCsCorp
Also found by: 0x11singh99, 0xAadi, 0xBugSlayer, 0xE1, 0xPluto, 0xSimeon, 0xSmartContract, 0xabhay, 0xdice91, 0xprinc, Aamir, Aymen0909, CDSecurity, DadeKuma, DarkTower, EV_om, Eeyore, GeekyLumberjack, GhK3Ndf, Giorgio, Greed, Inference, JanuaryPersimmon2024, Kaysoft, Krace, Matue, MrPotatoMagic, NentoR, Nikki, PUSH0, Soliditors, Tendency, Tigerfrake, Timeless, Timenov, ZanyBonzy, ZdravkoHr, abiih, adeolu, al88nsk, azanux, bareli, boredpukar, cu5t0mpeo, d4r3d3v1l, darksnow, deth, dutra, ether_sky, haxatron, ke1caM, kodyvim, m4ttm, mgf15, mrudenko, nmirchev8, nobody2018, nuthan2x, peanuts, piyushshukla, ravikiranweb3, rouhsamad, seraviz, simplor, slylandro_star, stealth, th13vn, vnavascues, wangxx2026, zaevlad
0.0879 USDC - $0.09
Malicious user can manipulate a router address.
DcntEth contract is used for setting up router address that controls minting and burning DcntEth tokens. This functions is not protected and can be called by any user:
function setRouter(address _router) public { router = _router; }
So malicious user can set his router and mint as much tokens as he need to harm the protocol.
Manual review
Protec the func with onlyOwner
modifier
Invalid Validation
#0 - c4-pre-sort
2024-01-24T05:31:24Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-01-24T05:31:29Z
raymondfam marked the issue as duplicate of #14
#2 - alex-ppg
2024-02-03T13:24:58Z
An improper severity level has been specified.
#3 - c4-judge
2024-02-03T13:25:02Z
alex-ppg marked the issue as partial-75
#4 - c4-judge
2024-02-04T23:07:50Z
alex-ppg changed the severity to 3 (High Risk)
43.4302 USDC - $43.43
https://github.com/code-423n4/2024-01-decent/blob/main/src/bridge_adapters/DecentBridgeAdapter.sol#L117 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L171 https://github.com/code-423n4/2024-01-decent/blob/main/src/UTB.sol#L289
Some Ether can stuck in the contract as there is no option to withdraw it.
When user wants to use token transfer to another chain he uses bridgeAndExecute
in the UTB contract, that forwards a call to a bridge()
in the adapter contract, such as DecentBridgeAdapter.
function bridge( uint256 amt2Bridge, SwapInstructions memory postBridge, uint256 dstChainId, address target, address paymentOperator, bytes memory payload, bytes calldata additionalArgs, address payable refund ) public payable onlyUtb returns (bytes memory bridgePayload) { ... router.bridgeWithPayload{value: msg.value}( lzIdLookup[dstChainId], destinationBridgeAdapter[dstChainId], swapParams.amountIn, false, dstGas, bridgePayload ); }
Later it pass data to the Router contract to bridgeWithPayload()
:
function _bridgeWithPayload( uint8 msgType, uint16 _dstChainId, address _toAddress, uint _amount, uint64 _dstGasForCall, bytes memory additionalPayload, bool deliverEth ) internal { ( bytes32 destinationBridge, bytes memory adapterParams, bytes memory payload ) = _getCallParams( msgType, _toAddress, _dstChainId, _dstGasForCall, deliverEth, additionalPayload ); ICommonOFT.LzCallParams memory callParams = ICommonOFT.LzCallParams({ @> refundAddress: payable(msg.sender), // DecentBridgeAdapter zroPaymentAddress: address(0x0), adapterParams: adapterParams }); uint gasValue; if (gasCurrencyIsEth) { weth.deposit{value: _amount}(); gasValue = msg.value - _amount; } else { weth.transferFrom(msg.sender, address(this), _amount); gasValue = msg.value; } dcntEth.sendAndCall{value: gasValue}( address(this), // from address that has dcntEth (so DecentRouter) _dstChainId, destinationBridge, // toAddress _amount, // amount payload, //payload (will have recipients address) _dstGasForCall, // dstGasForCall callParams // refundAddress, zroPaymentAddress, adapterParams ); }
Here we have refundAddress: payable(msg.sender)
, that assumed that Adaper (it is a msg.sender) can accept refunds for a call in native token.
In case of refunds there can be a situation where Adapter collet refunds that admin will not be able to withdraw.
Manual review
Provide a functions to withdraw refund ethers from the Adapter.
ETH-Transfer
#0 - c4-pre-sort
2024-01-24T05:55:45Z
raymondfam marked the issue as insufficient quality report
#1 - c4-pre-sort
2024-01-24T05:55:52Z
raymondfam marked the issue as duplicate of #27
#2 - c4-judge
2024-02-02T16:57:13Z
alex-ppg marked the issue as not a duplicate
#3 - c4-judge
2024-02-02T16:58:44Z
alex-ppg marked the issue as duplicate of #262
#4 - c4-judge
2024-02-02T17:03:21Z
alex-ppg marked the issue as satisfactory