PoolTogether contest - csanuragjain'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: 10/19

Findings: 1

Award: $1,309.61

🌟 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#L101

Vulnerability details

Impact

It seems there is no expiry or cancelling facility for processing relay calls. This could become a problem where an old failed transaction could be run at any point of time in future without any deadline

Proof of Concept

  1. User relays Calls C1 using relayCalls function
function relayCalls(CallLib.Call[] calldata _calls, uint256 _gasLimit) external payable returns (uint256) { ... nonce++; uint256 _nonce = nonce; relayed[_getTxHash(_nonce, _calls, msg.sender, _gasLimit)] = true; ... }
  1. Now User process this transaction using processCalls function
function processCalls( uint256 _nonce, CallLib.Call[] calldata _calls, address _sender, uint256 _gasLimit, uint256 _maxSubmissionCost, uint256 _gasPriceBid ) external payable returns (uint256) { require(relayed[_getTxHash(_nonce, _calls, _sender, _gasLimit)], "Relayer/calls-not-relayed"); bytes memory _data = abi.encodeWithSignature( "executeCalls(uint256,address,(address,bytes)[])", _nonce, _sender, _calls ); ... }
  1. Assume that executeCalls fails in which case transaction will revert
function executeCalls( uint256 _nonce, address _sender, Call[] memory _calls, bool _executedNonce ) internal { if (_executedNonce) { revert CallsAlreadyExecuted(_nonce); } ... (bool _success, bytes memory _returnData) = _call.target.call( abi.encodePacked(_call.data, _nonce, _sender) ); if (!_success) { revert CallFailure(_callIndex, _returnData); } } }
  1. User understands that current condition does not allow the transaction to complete as of now (say contract is locked). But now User has no way to cancel this relay transaction. This means anyone can execute this transaction in future even if it is not required

Allow only X amount of duration post relayCalls and if call is not processed during that time then it expires Or Add a new function which allows to reset relay calls ie relayed[_getTxHash(_nonce, _calls, msg.sender, _gasLimit)]

#0 - GalloDaSballo

2022-12-11T17:04:06Z

Interesting idea, esp given other findings, would like to hear Sponsor's opinion

#1 - GalloDaSballo

2022-12-11T20:29:57Z

This finding pertains to expiring relay calls, but mentions failing as well. I think it's acceptable to mark as dup of 166

#2 - c4-judge

2022-12-11T20:30:11Z

GalloDaSballo marked the issue as duplicate of #166

#3 - c4-judge

2022-12-26T23:39:39Z

GalloDaSballo 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