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: 16/113
Findings: 3
Award: $435.67
🌟 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.1172 USDC - $0.12
https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DcntEth.sol#L20-L22 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DcntEth.sol#L8-L11 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L294-L299 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L285-L291 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DcntEth.sol#L24-L26
It is possible to steal the weth of DecentEthRouter contracts
Since setRouter can be accessed by anyone.
function setRouter(address _router) public { router = _router; }
By calling setRouter,the router can be modified to a contract controlled by a bad user, and then run mint to cast any number of tokens for the bad user. After the mint runs, the router is then switched back to the DecentEthRouter contract.
Then, through the redeemEth or redeemWeth methods, the weth of the DecentEthRouter contract can be extracted
Manual Review
Restrict access to the setRouter by adding the modifier onlyOwner
Access Control
#0 - c4-pre-sort
2024-01-24T04:10:22Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-01-24T04:10:28Z
raymondfam marked the issue as duplicate of #14
#2 - c4-judge
2024-02-03T13:26:15Z
alex-ppg marked the issue as satisfactory
🌟 Selected for report: Soliditors
Also found by: NentoR, Soliditors, gesha17, peanuts, wangxx2026, windhustler
392.1226 USDC - $392.12
https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/UTB.sol#L186-L188 https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/bridge_adapters/StargateBridgeAdapter.sol#L61-L67 https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/UTB.sol#L311-L319 https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/UTB.sol#L134-L162
Loss of users due to fixed cross-chain transaction costs
With StargateBridgeAdapter.getBridgedAmount we can see that the amountIn transferred to the target chain is fixed and reduced by 6/10,000. this part is used to pay the cross-chain fees. The problem is, if the cross-chain fee is less than 6/10000, the extra amount will be locked in the target chain and can't be transferred out.
https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/bridge_adapters/StargateBridgeAdapter.sol#L61-L67 function getBridgedAmount( uint256 amt2Bridge, address /*tokenIn*/, address /*tokenOut*/ ) external pure returns (uint256) { return (amt2Bridge * (1e4 - SG_FEE_BPS)) / 1e4; }
The process of cross-chain transaction through StargateBridgeAdapter is to make a pre-cross-chain transaction first. The amoutOut of the pre-cross-chain transaction is used as the amoutIn of the cross-chain transaction, and a certain amount of fee will be deducted through StargateBirdge. https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/UTB.sol#L181-L188
SwapParams memory newPostSwapParams = abi.decode( instructions.postBridge.swapPayload, (SwapParams) ); newPostSwapParams.amountIn = IBridgeAdapter( bridgeAdapters[instructions.bridgeId] --> ).getBridgedAmount(amountOut, tokenOut, newPostSwapParams.tokenIn); // Reduce by 6/10,000
The amoutOut after the deduction is used to control the slippage. https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/bridge_adapters/StargateBridgeAdapter.sol#L170-L180
router.swap{value: msg.value}( getDstChainId(additionalArgs), //lzBridgeData._dstChainId, // send to LayerZero chainId getSrcPoolId(additionalArgs), //lzBridgeData._srcPoolId, // source pool id getDstPoolId(additionalArgs), //lzBridgeData._dstPoolId, // dst pool id refund, // refund adddress. extra gas (if any) is returned to this address amt2Bridge, // quantity to swap ---> (amt2Bridge * (10000 - SG_FEE_BPS)) / 10000, // the min qty you would accept on the destination, fee is 6 bips getLzTxObj(additionalArgs), // additional gasLimit increase, airdrop, at address abi.encodePacked(getDestAdapter(dstChainId)), bridgePayload // bytes param, if you wish to send additional payload you can abi.encode() them here );
The amoutOut obtained by stargateBirdge will be greater than or equal to (amt2Bridge * (10000 - SG_FEE_BPS)) / 10000. equal to this is not a problem, but greater than this will result in excess assets not being handled appropriately.
The rate for stargateBirdge is variable. If stargateBirdge's rate is lowered, the lowered rate will not benefit the user, but will be locked in the contract
Manual Review
When receiving transactions sent from other chains via receiveFromBridge, consider the case where the amount sent is greater than postBridge.amountIn to avoid being locked in the contract.
Also the rate(SG_FEE_BPS) should be settable to accommodate stargateBirdge rate changes
Token-Transfer
#0 - c4-pre-sort
2024-01-24T15:59:42Z
raymondfam marked the issue as insufficient quality report
#1 - raymondfam
2024-01-24T16:00:29Z
"greater than this will result in excess assets" will be sent to the user then.
#2 - c4-pre-sort
2024-01-24T16:02:25Z
raymondfam marked the issue as duplicate of #245
#3 - c4-judge
2024-02-02T11:31:42Z
alex-ppg marked the issue as not a duplicate
#4 - c4-judge
2024-02-02T11:31:48Z
alex-ppg marked the issue as primary issue
#5 - alex-ppg
2024-02-02T11:35:03Z
The Warden highlights that the Stargate router system utilizes a fixed fee which is incorrect as the Stargate fee can change.
An increase of the fee will result in perpetually failing transactions, while a decrease of the fee will result in loss of funds as the StargateBridgeAdapter::sgReceive
function ignores its _amountLD
argument.
Based on the fact that the same issue can lead to a Denial-of-Service as well as a presumably small loss-of-funds albeit with a low likelihood, I consider it to be a valid medium-risk issue.
#6 - c4-judge
2024-02-02T11:35:23Z
alex-ppg marked the issue as selected for report
#7 - c4-judge
2024-02-02T11:35:26Z
alex-ppg marked the issue as satisfactory
#8 - alex-ppg
2024-02-02T11:45:15Z
To note, the Stargate fee imposed on swaps is different from the Layer Zero fee. Here's the documentation that details the fee may be higher than .06%
: https://stargateprotocol.gitbook.io/stargate/v/user-docs/stargate-features/transfer#transfer-fees-and-how-they-work
I believe the pool imbalance fee is known as the equilibrium fee in the developer documentation: https://stargateprotocol.gitbook.io/stargate/developers/eq-fee-projection
#9 - c4-judge
2024-02-02T14:42:26Z
alex-ppg marked issue #520 as primary and marked this issue as a duplicate of 520
43.4302 USDC - $43.43
https://github.com/code-423n4/2024-01-decent/blob/07ef78215e3d246d47a410651906287c6acec3ef/src/bridge_adapters/DecentBridgeAdapter.sol#L81-L125 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L171 https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L148-L194
Excess gas returned will be locked in the contract
In the process of initiating a request to another chain, through the DecentBridgeAdapter.bridge method, call router.bridgeWithPayload while assembling the call to the sendAndCall method, we see that the refundAddress uses msg.sender.
ICommonOFT.LzCallParams memory callParams = ICommonOFT.LzCallParams({ --> refundAddress: payable(msg.sender), // Refunds received by msg.sender will be locked. zroPaymentAddress: address(0x0), adapterParams: adapterParams });
Now, msg.sender is a DecentBridgeAdapter contract, and there is no method of extracting native tokens from the DecentBridgeAdapter contract. This contract is just a temporary token storage contract during the transaction process. After the excess gas is returned, it will be locked.
Manual Review
Add the refundAddress parameter to the bridgeWithPayload method to allow for refunds.
ETH-Transfer
#0 - c4-pre-sort
2024-01-24T07:40:35Z
raymondfam marked the issue as insufficient quality report
#1 - c4-pre-sort
2024-01-24T07:40:44Z
raymondfam marked the issue as duplicate of #27
#2 - raymondfam
2024-01-24T07:41:54Z
Same root cause as in #27, albeit with insufficient proof.
#3 - c4-judge
2024-02-02T16:57:13Z
alex-ppg marked the issue as not a duplicate
#4 - c4-judge
2024-02-02T16:58:41Z
alex-ppg marked the issue as duplicate of #262
#5 - c4-judge
2024-02-02T17:03:13Z
alex-ppg marked the issue as satisfactory