Platform: Code4rena
Start Date: 07/07/2022
Pot Size: $75,000 USDC
Total HM: 32
Participants: 141
Period: 7 days
Judge: HardlyDifficult
Total Solo HM: 4
Id: 144
League: ETH
Rank: 37/141
Findings: 3
Award: $334.61
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: xiaoming90
Also found by: 0x29A, 0xDjango, 0xalpharush, Critical, Treasure-Seeker, ayeslick, infosec_us_team
https://github.com/code-423n4/2022-07-fractional/blob/main/src/modules/protoforms/BaseVault.sol#L58 https://github.com/code-423n4/2022-07-fractional/blob/main/src/modules/protoforms/BaseVault.sol#L77 https://github.com/code-423n4/2022-07-fractional/blob/main/src/modules/protoforms/BaseVault.sol#L98
When a call is made to a given token within BaseVault the token contract sees BaseVaults` address not the callers' address. As a result, all of the checks pass, and the caller is able to drain the contract.
A caller can pass an address they control into the _to
parameter while passing in BaseVault's address to the _from
parameter and setting the _amounts
and _tokens
arrays equal to the types and amounts of tokens within BaseVault. Then the caller can transfer all of the tokens to themselves.
Set the _from
parameter to msg.sender
Set the _to
parameter to address(this)
#0 - mehtaculous
2022-07-18T15:19:34Z
Duplicate of #468
🌟 Selected for report: byterocket
Also found by: 0x1f8b, 242, ACai, BradMoon, Chom, Lambda, PwnedNoMore, Twpony, __141345__, ayeslick, berndartmueller, cccz, giovannidisiena, infosec_us_team, minhtrng, nine9, oyc_109, reassor, slywaters, sseefried, tofunmi, unforgiven
4.9607 USDC - $4.96
https://github.com/code-423n4/2022-07-fractional/blob/main/src/Vault.sol#L76 https://github.com/code-423n4/2022-07-fractional/blob/main/src/Vault.sol#L87 https://github.com/code-423n4/2022-07-fractional/blob/main/src/Vault.sol#L94 https://github.com/code-423n4/2022-07-fractional/blob/main/src/Vault.sol#L102
When DELEGATECALL is called the targets' code is executed within Vault's storage/context. The targets' code is not limited to the functions within the Vault which means the targets' code may manipulate the Vault's storage. State variables owner, merkleRoot, nonce, and the methods mapping can be changed. MIN_GAS_RESERVE is a constant so it cannot be changed after the contract is deployed. The only variable that is checked to make sure it wasn't changed is the owner variable. This leaves the rest susceptible to manipulation where the values can be changed without proper permission.
The target contract could also call selfdestruct()
which would destroy the vault.
For example the install
function restricts access to its execution by checking to make sure msg.sender is the owner of the contract. This works under normal circumstances. However when a DELEGATECALL is executed the targets' contract has complete access to the context/storage of the Vault contract and, the targets' contract, isn't bound by the Vault's contract access-controlled functions.
Here is the install
function.
function install(bytes4[] memory _selectors, address[] memory _plugins) external { if (owner != msg.sender) revert NotOwner(owner, msg.sender); uint256 length = _selectors.length; for (uint256 i = 0; i < length; i++) { methods[_selectors[i]] = _plugins[i]; } emit InstallPlugin(_selectors, _plugins); }
Here is the targets code to install plugins
function install(bytes4[] memory _selectors, address[] memory _plugins) external { //if (owner != msg.sender) revert NotOwner(owner, msg.sender); uint256 length = _selectors.length; for (uint256 i = 0; i < length; i++) { methods[_selectors[i]] = _plugins[i]; } //emit InstallPlugin(_selectors, _plugins); }
By commenting out the check the targets' code is free to install any plugin when a DELEGATECALL is executed.
Check the other variables the same way the owner variable is checked.
#0 - 0x0aa0
2022-07-19T15:06:03Z
Duplicate of #200
#1 - HardlyDifficult
2022-07-26T14:57:48Z
This issue seems distinct from #200. Although both touch on executing self destruct, this one is focused on self destructing a specific instance (or making other unintended modifications). The mitigation for this concern (if necessary) may likely be different.
The issue as described seems valid. It assumes a malicious vault owner first installs the ability to make these changes. Then it could be called by anyone, potentially bricking that vault - potentially leading to lost assets for other users of the vault. Given the requirement that the owner makes this possible this seems to be a Medium risk issue.
#2 - HardlyDifficult
2022-07-26T23:56:15Z
Duping to #487
🌟 Selected for report: xiaoming90
Also found by: 0x1f8b, 0x29A, 0x52, 0xA5DF, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 0xsanson, 0xsolstars, 242, 8olidity, Amithuddar, Aymen0909, Bnke0x0, BowTiedWardens, David_, Deivitto, ElKu, Funen, Hawkeye, IllIllI, JC, Kaiziron, Keen_Sheen, Kthere, Kulk0, Kumpa, Lambda, MEP, ReyAdmirado, Rohan16, Ruhum, Sm4rty, TomJ, Tomio, Treasure-Seeker, TrungOre, Tutturu, Viksaa39, Waze, _Adam, __141345__, ak1, apostle0x01, asutorufos, async, ayeslick, aysha, bbrho, benbaessler, berndartmueller, c3phas, cccz, chatch, cloudjunky, codexploder, cryptphi, delfin454000, dipp, durianSausage, dy, exd0tpy, fatherOfBlocks, hake, hansfriese, horsefacts, hubble, joestakey, jonatascm, kebabsec, kenzo, kyteg, mektigboy, neumo, oyc_109, pashov, pedr02b2, peritoflores, rajatbeladiya, rbserver, robee, rokinot, s3cunda, sach1r0, sahar, sashik_eth, scaraven, shenwilly, simon135, sorrynotsorry, sseefried, svskaushik, unforgiven, z3s, zzzitron
61.9381 USDC - $61.94
Underflow in log2ceil_naive()
Its possible to underflow log2ceil_naive()
by passing in 0.
https://github.com/code-423n4/2022-07-fractional/blob/main/src/utils/MerkleBase.sol#L190
If caller passes 0 into log2ceil_naive()
it will get overflow, 115792089237316195423570985008687907853269984665640564039457584007913129639935.
log2ceil_naive
should be internal or private to prevent anyone from calling it
#0 - HardlyDifficult
2022-07-26T19:09:22Z
Merging with #354, https://github.com/code-423n4/2022-07-fractional-findings/issues/129