https://sherlock-files.ams3.digitaloceanspaces.com/twitter_images/56499bb3-18fd-49f4-8a7b-f5954aff5df8.jpg

panprog

Security Researcher

Talented enterpreneur and IT expert

Contact Me

High

17

Solo

39

Total

Medium

33

Solo

55

Total

$529.56K

Total Earnings

#11 All Time

22x

Payouts

gold

14x

1st Places

silver

1x

2nd Places

bronze

1x

3rd Places

All

Sherlock

Code4rena

Jan '25

Perennial V2 Update #4

Perennial V2 Update #4

33,152.17 USDC • 6 total findings • Sherlock • panprog

gold

high

Anyone can steal all funds from the `market` due to incorrect health accounting for pending pnl from difference of intent price and market price when multiple intents are used.

high

`InvariantLib` uses current position for margin check allowing to withdraw collateral while the position decrease is only pending and can cause unexpected immediate user liquidation.

high

Intent orders are guaranteed to execute, but fees from these orders are not accounted in collateral, allowing user to withdraw all collateral ignoring these pending fees.

high

When account is liquidated (protected), liquidator can increase account's position to any value up to `2**62 - 1` breaking all market accounting and stealing all market funds.

medium

Some accounts using Intents to trade might be liquidated while healthy or be unliquidatable while being unhealthy.

medium

Liquidations are temporarily blocked if user's pending position close amount is greater than the latest position size.

Dec '24

DODO

DODO

Collaborative Audit • Sherlock • panprog

Aug '24

Perennial V2 Update #3

Perennial V2 Update #3

64,467.48 USDC • 11 total findings • Sherlock • panprog

gold

high

Anyone can steal all funds from the `market` due to lack of account health accounting for pending pnl from difference of intent price and market price.

high

Anyone can be operator of any account due to lack of access control in `MarketFactory.updateExtension`

high

Market coordinator can steal all market collateral by changing adiabatic fees

high

Market coordinator can liquidate all users in the market

high

Market coordinator can steal all market collateral by abusing very low value of `scale`

high

Market coordinator can set `staleAfter` to a huge value allowing anyone to steal all market collateral when there are no transactions for some time

medium

`MultiInvoker` and `Manager` orders execution can be DOS in key moments if AAVE/Compound utilization is at 100%

medium

`MultiInvoker` and `Manager` operations might revert due to assumption of 1 `DSU` = 1 `USDC`

medium

`MultiInvoker`, `Manager` and `Account` unexpected reverts in certain conditions due to AAVE reverting on deposits and withdrawals with 0 amount

medium

`Controller`'s core function of Rebalance will not rebalance when rebalance is needed in some cases, breaking core functionality

medium

Market coordinator can set proportional and adiabatic fees much higher than limited by protocol due to fixed point truncation

Jul '24

Aloe Update

Aloe Update

21,500 USDC • Sherlock • panprog

gold

Findings not publicly available for private contests.

MakerDAO Endgame

MakerDAO Endgame

59,168.80 USDC • Sherlock • panprog

gold

May '24

Kwenta x Perennial Integration Update

Kwenta x Perennial Integration Update

11,226.70 USDC • Sherlock • panprog

gold

Mar '24

Perennial V2 Update #2

Perennial V2 Update #2

94,014.34 USDC • 9 total findings • Sherlock • panprog

gold

high

Vault global shares and assets change will mismatch local shares and assets change during settlement due to incorrect `_withoutSettlementFeeGlobal` formula

high

Empty orders do not request from oracle and during settlement they use an invalid oracle version with `price=0` which messes up a lot of fees and funding accounting leading to loss of funds for the makers

high

Requested oracle versions, which have expired, must return this oracle version as invalid, but they return it as a normal version with previous version's price instead

medium

All transactions to claim assets from the vault will revert in some situations due to double subtraction of the claimed assets in market position allocations calculation.

medium

If referral or liquidator is the same address as the account, then liquidation/referral fees will be lost due to local storage being overwritten after the `claimable` amount is credited to liquidator or referral

medium

Vault and oracle keepers DoS in some situations due to `market.update(account,max,max,max,0,false)`

medium

Vault checkpoints slightly incorrect conversion from assets to shares leads to slow loss of funds for long-time vault depositors

medium

When vault's market weight is set to 0 to remove the market from the vault, vault's leverage in this market is immediately set to max leverage risking position liquidation

medium

Makers can lose funds from price movement even when no long and short positions are opened, due to incorrect distribution of adiabatic fees exposure between makers

Feb '24

Smilee Finance

Smilee Finance

76,214.00 USDC • 9 total findings • Sherlock • panprog

gold

high

The sign of delta hedge amount can be reversed by malicious user due to incorrect condition in `FinanceIGDelta.deltaHedgeAmount`

high

Utilization rate for bonding curve purposes is calculated for a total of bull and bear usage, which can be abused to steal all vault funds

medium

If the vault's side token balance is 0 or a tiny amount, then most if not all IG Bear trades will revert due to incorrect check of computation error during delta hedge amount calculation

medium

Transferring ERC20 Vault tokens to another address and then withdrawing from the vault breaks `totalDeposit` accounting which is tied to deposit addresses

medium

PositionManager will revert when trying to return back to user excess of the premium transferred from the user when minting position

medium

PositionManager will revert all `mint` attempts when trying to `safeApprove` `dvp` address to spend tokens if it hasn't spent all tokens approved previously

medium

PositionManager will revert all `mint` attempts if actual premium charged is greater than premium calculated from oracle price.

medium

FeeManager `receiveFee` and `trackVaultFee` functions allow anyone to call it with user-provided dvp/vault address and add any arbitrary feeAmount to any address, breaking fees accounting and temporarily bricking DVP smart contract

medium

Trading out of the money options has delta = 0 which breaks protocol assumptions of traders profit being fully hedged and can result in a loss of funds to LPs

100x

100x

32,342.19 USDC • Sherlock • panprog

gold

Findings not publicly available for private contests.

Jan '24

SYMM IO

SYMM IO

8,181.86 USDC • Sherlock • panprog

gold

Dec '23

DODO

DODO

Collaborative Audit • Sherlock • panprog

Oct '23

Perennial V2 Update #1

Perennial V2 Update #1

52,516.71 USDC • 11 total findings • Sherlock • panprog

gold

high

Vault max redeem calculations limit redeem amount to the smallest position size in underlying markets which can lead to very small max redeem amount even with huge TVL vault

high

Liquidator can liquidate user while increasing user position to any value, stealing all Market funds or bricking the contract

high

Vault leverage can be increased to any value up to min margin requirement due to incorrect `maxRedeem` calculations with closable and `LEVERAGE_BUFFER`

medium

It is possible to open and liquidate your own position in 1 transaction to overcome efficiency and liquidity removal limits at almost no cost

medium

Invalid oracle version can cause the `maker` position to exceed `makerLimit`, temporarily or permanently bricking the Market contract

medium

`KeeperOracle.request` adds only the first pair of market+account addresses per oracle version to callback list, ignoring all the subsequent ones

medium

`KeeperOracle.commit` will revert and won't work for all markets if any single `Market` is paused.

medium

Vault `_maxDeposit` incorrect calculation allows to bypass vault deposit cap

medium

Pending keeper and position fees are not accounted for in vault collateral calculation which can be abused to liquidate vault when it's small

medium

`MultiInvoker._latest` will return `latestPrice = 0` when latest oracle version is invalid causing liquidation to send 0 fee to liquidator or incorrect order execution

medium

`MultiInvoker._latest` calculates incorrect closable for the current oracle version causing some liquidations to revert

Aloe

Aloe

5,408.57 USDC • 4 total findings • Sherlock • panprog

silver

high

It is possible to frontrun liquidations with self liquidation with high strain value to clear warning and keep unhealthy positions from liquidation

high

`Borrower`'s `modify`, `liquidate` and `warn` functions use stored (outdated) account liabilities which makes it possible for the user to intentionally put him into bad debt in 1 transaction

medium

Bad debt liquidation doesn't allow liquidator to receive its ETH bonus (ante)

medium

In some situations the liquidation can become unprofitable for liquidators, keeping unhealthy positions

Sep '23

Perennial V2 Fix Review

Perennial V2 Fix Review

22,583.33 USDC • 5 total findings • Sherlock • panprog

gold

medium

During oracle provider switch, if previous provider feed stops working completely, oracle and market will be stuck with user funds locked in the contract

medium

`Vault.update(anyUser,0,0,0)` can be called for free to increase `checkpoint.count` and pay smaller keeper fee than necessary

medium

MultiInvoker liquidation action will revert most of the time due to incorrect closable amount initialization

medium

MultiInvoker liquidation action will revert due to incorrect closable amount calculation for invalid oracle versions

medium

Invalid oracle version can cause the vault to open too large and risky position and get liquidated due to using unadjusted global current position

Aug '23

Symmetrical Update

Symmetrical Update

6,056.16 USDC • 6 total findings • Sherlock • panprog

gold

high

`liquidatePartyA` requires signature which doesn't have nonce, making possible unfair liquidation and loss of funds for all parties

high

`liquidatePositionsPartyA` limits partyB loss to partyB allocated balance, which can lead to inflated partyB balance and loss of funds for protocol users

medium

Position closure might always revert in some cases due to allocatedBalances being unsigned, preventing the user from closing its positions

medium

Position value can fall below minimum acceptable quote value when partially closing positions requested to be closed in full

medium

MultiAccount `depositAndAllocateForAccount` function doesn't scale the allocated amount correctly, failing to allocate enough funds

medium

Wrong calculation of solvency in `fillCloseRequest` prevents the position from being closed even if the user is solvent after position closure

Jul '23

Perennial V2

Perennial V2

13,875.50 USDC • 7 total findings • Sherlock • panprog

gold

high

Oracle request timestamp and pending position timestamp mismatch can make most position updates invalid

high

PythOracle `_recordPrice()` function incorrectly treats `expo` (exponent) from `PythStructs.Price` which can lead to protocol malfunction and loss of funds after oracle switch

high

Invalid oracle versions can cause desync of global and local positions making protocol lose funds and being unable to pay back all users

medium

It is possible to open and liquidate your own position in 1 transaction to overcome efficiency and liquidity removal limits at almost no cost

medium

PythOracle `commit()` function doesn't require (nor stores) pyth price publish timestamp to be after the previous commit's publish timestamp, which makes it possible to manipulate price to unfairly liquidate users and possible stealing protocol funds

medium

During oracle provider switch, if it is impossible to commit the last request of previous provider, then the oracle will get stuck (no price updates) without any possibility to fix it

medium

Bad debt (shortfall) liquidation leaves liquidated user in a negative collateral balance which can cause bank run and loss of funds for the last users to withdraw

Jun '23

Symmetrical

Symmetrical

12,576.88 USDC • 9 total findings • Sherlock • panprog

gold

high

liquidatePositionsPartyB can be used by malicious liquidator to liquidate only select positions which artificially inflates partyA upnl and allows to steal funds

high

PartyA and PartyB nonce is not incremented in any of the liquidation functions which can lead to all protocol funds being stolen in some cases

high

Position closure and position liquidations might always revert in some cases due to allocatedBalances being unsigned, preventing the user from closing its positions or finishing liquidation

medium

Any user can avoid paying most of the protocol fees on short positions, and can unknowingly pay very high fee on long positions

medium

partyA or partyB can be unexpectedly liquidated immediately after opening position if low LIMIT price is provided in the quote

medium

Fees are not returned to partyA from locked quotes if partyB is liquidated

medium

partyA is forever stuck with open positions and partyB is stuck forever in liquidation status if liquidatePositionsPartyB is not called within 2 * liquidationTimeout seconds window

medium

Some actions are allowed on partyB when corresponding partyA is liquidated allowing to steal all protocol funds

medium

Suspended partyB can use another partyA to transfer fraudlent funds via artificial profit/loss

Aug '22

Sentiment

Sentiment

290.24 USDC • 2 total findings • Sherlock • panprog

#20

medium

Re-entrancy with multiple smaller bugs can be used to borrow large amount and lock it in the account

medium

If oracle is set for ERC777 token, re-entrancy is possible to steal all LToken funds

Fraxlend (Frax Finance) contest

Fraxlend (Frax Finance) contest

2,282.09 USDC • 1 total finding • Code4rena • panprog

#8

high

Any borrower with bad debt can be liquidated multiple times to lock funds in the lending pair

Rigor Protocol contest

Rigor Protocol contest

94.87 USDC • 1 total finding • Code4rena • panprog

#44

high

Project funds can be drained by reusing signatures, in some cases

Jul '22

Golom contest

Golom contest

240.1 USDC • Code4rena • panprog

#49

Swivel v3 contest

Swivel v3 contest

3,240.28 USDC • 2 total findings • Code4rena • panprog

#4

medium

With most functions in VaultTracker.sol, users can call them only once after maturity has been reached.

medium

ZcToken.withdraw will send user 0 tokens if called after maturity deadline but before market is set mature

ENS contest

ENS contest

8,671.28 USDC • 4 total findings • Code4rena • panprog

bronze

high

[PNM-001] `PARENT_CANNOT_CONTROL` can be bypassed by maliciously unwrapping parent node

high

It is possible to create fake ERC1155 NameWrapper token for subdomain, which is not owned by NameWrapper

medium

If PARENT_CANNOT_CONTROL is set on subdomain, it can be unwrapped then wrapped by its owner and then parent can control it again before the expiry

medium

BytesUtil.compare returns wrong result on some strings longer than 32 characters

Fractional v2 contest

Fractional v2 contest

1,459.5 USDC • 7 total findings • Code4rena • panprog

#16

high

Proposal which started buyout which fails is able to settle migration as if its buyout succeeded.

high

Any fractions deposited into any proposal can be stolen at any time until it is commited

high

Fund will be stuck if a buyout is started while there are pending migration proposals

high

Steal NFTs from a Vault, and ETH + Fractional tokens from users.

high

Division rounding can make fraction-price lower than intended (down to zero)

high

Migration::withdrawContribution falsely assumes that user should get exactly his original contribution back

high

```migrateFractions``` may be called more than once by the same user which may lead to loss of tokens for other users