PoolTogether micro contest #1 - 0xRajeev's results

A protocol for no loss prize savings on Ethereum

General Information

Platform: Code4rena

Start Date: 29/07/2021

Pot Size: $20,000 USDC

Total HM: 8

Participants: 12

Period: 3 days

Judge: LSDan

Total Solo HM: 2

Id: 24

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 1/12

Findings: 6

Award: $4,899.69

🌟 Selected for report: 7

πŸš€ Solo Findings: 1

Findings Information

🌟 Selected for report: GalloDaSballo

Also found by: 0xRajeev, gpersoon

Labels

bug
duplicate
3 (High Risk)
SwappableYieldSource
sponsor disputed

Awards

838.3068 USDC - $838.31

External Links

Handle

0xRajeev

Vulnerability details

Impact

SwappableYieldSource.sol has a transferERC20() function callable only by the owner or asset manager to transfer out ERC20 tokens other than the yield source's tokens held by this contract. This is similar to the functions in ATokenYieldSource and IdleYieldSource.

In ATokenYieldSource and IdleYieldSource, the token exclusion check is made on aToken and idleToken respectively because they are specific to those yield contracts.

However, in this generic SwappableYieldSource contract which points to the chosen yield source, there is not one permanent yield source token. So the exclusion check has to be performed on the token of the current yield source. But the check implemented checks against the address of the yieldSource contract instead of its token. This will pass even for the yieldSource token and will allow owner or asset manager to transfer out at any time all the yieldSource tokens to any recipient address of choice i.e. rugging.

For e.g. if SwappableYieldSource yieldSource points to ATokenYieldSource, the check will allow aToken to be transferred out because it checks the ERC20 aToken address against ATokenYieldSource address which will pass and allow the transfer out.

Proof of Concept

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/SwappableYieldSource.sol#L324

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/SwappableYieldSource.sol#L317-L328

https://github.com/code-423n4/2021-06-pooltogether/blob/85f8d044e7e46b7a3c64465dcd5dffa9d70e4a3e/contracts/yield-source/ATokenYieldSource.sol#L225

https://github.com/code-423n4/2021-06-pooltogether/blob/85f8d044e7e46b7a3c64465dcd5dffa9d70e4a3e/contracts/yield-source/IdleYieldSource.sol#L142

Tools Used

Manual Analysis

Check against yield source token address instead of yield source address.

#0 - PierrickGT

2021-08-11T23:17:08Z

This exploit is not possible. The swappable yield source don't old any funds, this is the role of the yield source that either mint ERC20 token shares to the swappable yield source or keep track of the balance by using a mapping. That's why we only check that transferERC20 can't move ERC20 token shares that would represent the swappable yield source shares in the yield source.

#1 - 0xean

2021-08-24T16:35:18Z

I agree that there is a potential for a rug pull here, it would have to be in combination with #14 but the potential exists. I am marking as a duplicate as #14 as the issues are related and the check here does little to avoid tokens being transferred after the yieldSource has been changed.

#2 - PierrickGT

2021-08-30T15:33:44Z

Closing this issue that has been marked as a duplicate.

Findings Information

🌟 Selected for report: hickuphh3

Also found by: 0xRajeev

Labels

bug
duplicate
1 (Low Risk)
SwappableYieldSource

Awards

1397.178 USDC - $1,397.18

External Links

Handle

0xRajeev

Vulnerability details

Impact

Similar to the check in _setYieldSource(), it is safer to check in transferFunds() that the deposit token of the yield source being transferred from is the same as the current yield source.

An owner or assetManager can mistakenly initiate transfer from a yield source with a different depositToken, e.g. DAI, to the current one, e.g. mUSD.

Proof of Concept

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/SwappableYieldSource.sol#L296-L300

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/SwappableYieldSource.sol#L278-L289

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/SwappableYieldSource.sol#L256

Tools Used

Manual Analysis

Add the check similar to the one in L256 to transferFunds().

#0 - PierrickGT

2021-08-06T16:36:38Z

Findings Information

🌟 Selected for report: 0xRajeev

Labels

bug
2 (Med Risk)
SwappableYieldSource
sponsor acknowledged

Awards

931.452 USDC - $931.45

External Links

Handle

0xRajeev

Vulnerability details

Impact

The SwappableYieldSource allows owners and asset managers to set/swap/transfer yield sources/funds. As such, the contract ownership plays a critical role in the protocol.

Given that AssetManager is derived from Ownable, the ownership management of this contract defaults to Ownable’s transferOwnership() and renounceOwnership() methods which are not overridden here. Such critical address transfer/renouncing in one-step is very risky because it is irrecoverable from any mistakes.

Scenario: If an incorrect address, e.g. for which the private key is not known, is used accidentally then it prevents the use of all the onlyOwner() functions forever, which includes the changing of various critical addresses and parameters. This use of incorrect address may not even be immediately apparent given that these functions are probably not used immediately. When noticed, due to a failing onlyOwner() or onlyOwnerOrAssetManager() function call, it will force the redeployment of these contracts and require appropriate changes and notifications for switching from the old to new address. This will diminish trust in the protocol and incur a significant reputational damage.

Proof of Concept

See similar High Risk severity finding from Trail-of-Bits Audit of Hermez: https://github.com/trailofbits/publications/blob/master/reviews/hermez.pdf

See similar Medium Risk severity finding from Trail-of-Bits Audit of Uniswap V3: https://github.com/Uniswap/uniswap-v3-core/blob/main/audits/tob/audit.pdf

https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/081776bf5fae2122bfda8a86d5369496adfdf959/contracts/access/OwnableUpgradeable.sol#L59-L76

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/access/AssetManager.sol#L20-L61

Tools Used

Manual Analysis

Override the inherited methods to null functions and use separate functions for a two-step address change: 1) Approve a new address as a pendingOwner 2) A transaction from the pendingOwner address claims the pending ownership change. This mitigates risk because if an incorrect address is used in step (1) then it can be fixed by re-approving the correct address. Only after a correct address is used in step (1) can step (2) happen and complete the address/ownership change.

Also, consider adding a time-delay for such sensitive actions. And at a minimum, use a multisig owner address and not an EOA.

#0 - PierrickGT

2021-08-11T23:05:02Z

This isn't a security issue but an improper use of the initialize function. We do check for address zero so at least the risk of deploying the contract with address zero is excluded. Also, these contracts will be deployed by a multi sig owned by governance so the risk of a single human error is almost null.

#1 - 0xean

2021-08-24T16:41:58Z

Disagree with sponsor. A two step process would be a safer implementation. A multi-sig does not remove human error or the potential risk here. It may be an acceptable risk to the team, but still worth highlighting with the given severity.

#2 - PierrickGT

2021-08-30T23:38:14Z

We have studied this solution and decided to not implement it since it would make it a pretty tedious process to deploy a swappable yield source, especially through the use of our builder which would mean that a user would have to manually claimOwnership after deploying a pool. Plus, this contract will be owned by governance so it will be very difficult to transfer it to another owner or renounce ownership.

Findings Information

🌟 Selected for report: 0xRajeev

Also found by: cmichel, pauliax, shw

Labels

bug
2 (Med Risk)
mStableYieldSource
sponsor confirmed

Awards

169.7571 USDC - $169.76

External Links

Handle

0xRajeev

Vulnerability details

Impact

Unlike SwappableYieldSource which uses safeIncreaseAllowance to increase the allowance to uint256.max, mStableYieldSource uses OpenZeppelin’s safeApprove() which has been documented as 1) Deprecated because of approve-like race condition and 2) To be used only for initial setting of allowance (current allowance == 0) or resetting to 0 because it reverts otherwise.

The usage here is intended to allow increase of allowance when it falls low similar to the documented usage in SwappableYieldSource. Using it for that scenario will not work as expected because it will always revert if current allowance is != 0. The initial allowance is already set as uint256.max in constructor. And once it gets reduced, it can never be increased using this function unless it is invoked when allowance is reduced completely to 0.

Proof of Concept

https://github.com/pooltogether/pooltogether-mstable/blob/0bcbd363936fadf5830e9c48392415695896ddb5/contracts/yield-source/MStableYieldSource.sol#L60-L65

https://github.com/pooltogether/pooltogether-mstable/blob/0bcbd363936fadf5830e9c48392415695896ddb5/contracts/yield-source/MStableYieldSource.sol#L51

https://github.com/pooltogether/swappable-yield-source/blob/89cf66a3e3f8df24a082e1cd0a0e80d08953049c/contracts/SwappableYieldSource.sol#L135-L143

https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/081776bf5fae2122bfda8a86d5369496adfdf959/contracts/token/ERC20/utils/SafeERC20Upgradeable.sol#L37-L57

Tools Used

Manual Analysis

Use logic similar to SwappableYieldSource instead of using safeApprove().

#0 - PierrickGT

2021-08-13T21:34:02Z

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