PoolTogether contest - ladboy233's results

A no-loss prize-savings protocol.

General Information

Platform: Code4rena

Start Date: 01/12/2022

Pot Size: $26,900 USDC

Total HM: 3

Participants: 19

Period: 4 days

Judge: GalloDaSballo

Id: 188

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 3/19

Findings: 2

Award: $1,921.21

QA:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: AkshaySrivastav

Also found by: csanuragjain, hihen, ladboy233

Labels

bug
2 (Med Risk)
satisfactory
duplicate-166

Awards

1309.6144 USDC - $1,309.61

External Links

Lines of code

https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-arbitrum/EthereumToArbitrumRelayer.sol#L159 https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-optimism/EthereumToOptimismRelayer.sol#L64 https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-polygon/EthereumToPolygonRelayer.sol#L60

Vulnerability details

Impact

Cross-chain request does not have expiration time

Proof of Concept

In the current implementation, a caller in source chain can perform a relayer call to starts a cross-chain request.

But it is not clearly when the executor will be executing the cross-chain.

Some blockchain transaction can be very time senstiive (trading, etc...)

For example, a user wants to perform a cross-chain from ethereum to polygon,

In the polygon destination chain, the user wants to borrow 1000 USDC using 2 ETH in a lending market.

at the time when user performs a request, 1 ETH = 1300 USD.

but the executor is very busy and does not execute the cross-chain request until two days later, at this time, the ETH price drops to 500 USD per ETH or below 500 USD. the borrow request is executed but the user's position is liquidated.

Tools Used

Manual Review

We recommend the project adding a expiration time when creating the cross-chain request on the relayer side, and on execution side, check if the cross-chain is expired, if expired, do not perform the request.

#0 - c4-judge

2022-12-11T21:39:05Z

GalloDaSballo marked the issue as duplicate of #166

#1 - GalloDaSballo

2022-12-11T21:39:20Z

Markign as Dup of 166 as it's effectively the same case (tx doesn't expire if failed / not executed)

#2 - c4-judge

2022-12-26T23:44:14Z

GalloDaSballo marked the issue as satisfactory

Findings Information

🌟 Selected for report: 0xSmartContract

Also found by: cryptonue, gzeon, ladboy233

Labels

bug
grade-a
QA (Quality Assurance)
edited-by-warden
Q-02

Awards

611.5965 USDC - $611.60

External Links

[L-01] nonce should be marked as public instead of internal.

Line Of Code:

https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-optimism/EthereumToOptimismRelayer.sol#L29

https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-polygon/EthereumToPolygonRelayer.sol#L23

https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-arbitrum/EthereumToArbitrumRelayer.sol#L40

Vulnerability Detail and recommended fix

in the current implementation, the nonce is set to internal, and the user is only able to know the nonce by querying the blockchain transaction and read the emitted event log or use the return value from relayCall, which is very inconvenient to keep track of the nonce.

/// @notice Nonce to uniquely idenfity each batch of calls.
uint256 internal nonce;

We recommend the codebase change the access control for nonce from internal to public.

[L-02] unsafe downcasting of the gas limit from uint256 to uint32 in OptimismRelayer.sol

Line Of Code:

https://github.com/pooltogether/ERC5164/blob/5647bd84f2a6d1a37f41394874d567e45a97bf48/src/ethereum-optimism/EthereumToOptimismRelayer.sol#L72

Vulnerability Detail and recommended fix

The gas limit is unsafely downcasted from uint256 to uint32 in OptimismRelayer.sol

crossDomainMessenger.sendMessage(
  address(executor),
  abi.encodeWithSignature(
	"executeCalls(uint256,address,(address,bytes)[])",
	_nonce,
	msg.sender,
	_calls
  ),
  uint32(_gasLimit)
);

the gas limit can be truncated if the gas limit that is larger than uint32 is set.

We recommend the project use openzepplin unsafe case to make sure the gas limit is not trancunated sliently.

#0 - GalloDaSballo

2022-12-14T20:14:48Z

[L-01] nonce should be marked as public instead of internal.

R

[L-02] unsafe downcasting of the gas limit from uint256 to uint32 in OptimismRelayer.sol

Invalid per discussion with sponsot

1R

#1 - c4-judge

2022-12-26T23:14:09Z

GalloDaSballo marked the issue as grade-a

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