Decent - ZanyBonzy'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: 91/113

Findings: 1

Award: $0.12

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

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

Vulnerability details

Impact

Arbitrary minting and burning of DcntEth tokens, which may later be used to redeem ETH/WETH from the router.

Proof of Concept

In the DcntEth contract, tokens can be minted/burned either by the owner or the router.

function mint(address _to, uint256 _amount) public onlyRouter { _mint(_to, _amount); } function burn(address _from, uint256 _amount) public onlyRouter { _burn(_from, _amount); } function mintByOwner(address _to, uint256 _amount) public onlyOwner { _mint(_to, _amount); } function burnByOwner(address _from, uint256 _amount) public onlyOwner { _burn(_from, _amount); }

To mint tokens through the router, the router needs to be set.

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

The function to the set the router however, is public and unprotected, making it accessible to anyone. This causes that any user, a malicious user can set any address as the router address and mint/burn DcntEth at will.

The malicious user can also use this to redeem ETH and WETH from the DecentEthRouter contract thereby stealing funds from the protocol.

function redeemEth( uint256 amount ) public onlyIfWeHaveEnoughReserves(amount) { dcntEth.transferFrom(msg.sender, address(this), amount); weth.withdraw(amount); payable(msg.sender).transfer(amount); } /// @inheritdoc IDecentEthRouter function redeemWeth( uint256 amount ) public onlyIfWeHaveEnoughReserves(amount) { dcntEth.transferFrom(msg.sender, address(this), amount); weth.transfer(msg.sender, amount); }

Tools Used

Manual code review

Add an onlyOwner modifier to the setRouter function

Assessed type

Access Control

#0 - c4-pre-sort

2024-01-24T22:46:24Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-24T22:46:35Z

raymondfam marked the issue as duplicate of #14

#2 - c4-judge

2024-02-03T13:13:44Z

alex-ppg marked the issue as satisfactory

Lines of code

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

Vulnerability details

Impact

A malicious user can change router address or set it to address 0, hampering the DecentEthRouter's ability to add or remove ETH/WETH liquidity.

Proof of Concept

Bridge liquidity can be added to or removed from DecentEthRouter by calling the addLiquidityEth, addLiquidityWeth, removeLiquidityEth and removeLiquidityWeth functions.

function addLiquidityEth() public payable onlyEthChain userDepositing(msg.value) { weth.deposit{value: msg.value}(); dcntEth.mint(address(this), msg.value); //@note } /// @inheritdoc IDecentEthRouter function removeLiquidityEth( uint256 amount ) public onlyEthChain userIsWithdrawing(amount) { dcntEth.burn(address(this), amount); //@note weth.withdraw(amount); payable(msg.sender).transfer(amount); }

Doing this requires that DcntEth tokens are minted or burned before ETH/WETH is sent to or retrieved from the user, which is executed in the DcntEth contract by calling the mint/burn functions.

function mint(address _to, uint256 _amount) public onlyRouter { _mint(_to, _amount); } function burn(address _from, uint256 _amount) public onlyRouter { _burn(_from, _amount); }

The mint/burn functions are inteded to be called by only the router, in this case the DecentEthRouter and is expected to be set by calling the setRouter function.

/** * @param _router the decentEthRouter associated with this eth */ function setRouter(address _router) public { router = _router; }

As can be seen from the above, the function is public and unprotected meaning anyone can call the function. Note also that the function is executed in one step and features no zero address checks.

A malicious user can call the the function, passing in a zero address, or any arbitrary address, causing that all calls to mint or burn tokens from the DecentEthRouter fails, and thus liquidity cannot be added or removed from the bridge.

Tools Used

Manual code review

Add an onlyOwner modifier to the setRouter function

Assessed type

Access Control

#0 - c4-pre-sort

2024-01-24T22:52:36Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-24T22:52:43Z

raymondfam marked the issue as duplicate of #14

#2 - alex-ppg

2024-02-03T13:14:47Z

The submission fails to identify the correct impact or exploitation vector and instead mentions an attack vector that would not be of high risk.

#3 - c4-judge

2024-02-03T13:14:59Z

alex-ppg marked the issue as partial-50

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