Welcome to my Web3 bug bounty and security research repository. This space is dedicated to documenting my journey into the depths of smart contract security. Here, you will find detailed analyses, proof-of-concept exploits, and vulnerability reports for various protocols. My mission is to help secure the decentralized future by identifying critical vulnerabilities before they can be exploited.
This collection represents not just technical findings, but also a commitment to rigorous analysis, clear communication, and continuous learning within the ever-evolving landscape of blockchain security.
I believe that robust smart contract security goes beyond surface-level scanning. My approach is rooted in a deep, fundamental understanding of a protocol's architecture and economic design. I focus on:
- Logic-First Analysis: Deconstructing the intricate state machines and internal logic of smart contracts to uncover hidden assumptions and edge cases.
- Economic & Incentive Analysis: Examining how financial primitives can be manipulated and how economic incentives can be misaligned to create attack vectors.
- Adversarial Mindset: Thinking like an attacker to foresee non-obvious paths that could lead to fund loss, protocol insolvency, or deadlocks.
- Constructive Reporting: Providing clear, actionable, and well-documented reports with runnable Proof-of-Concepts to help development teams quickly understand, replicate, and mitigate the identified risks.
This section contains a selection of my findings from a deep dive into the Lido Dual Governance and Escrow mechanism. Each report includes a detailed breakdown, a runnable Proof-of-Concept, and my personal reflections on the outcome.
- Vulnerability: The
Escrow.solcontract's RageQuit process placed excessive trust in the configuration of the externalWithdrawalQueue.sol. By maliciously settingmaxStETHWithdrawalAmountto a near-zero value, a compromised governance could permanently trap all user funds within theEscrowcontract. - Impact: Permanent freezing of all user funds participating in the RageQuit, with no recovery mechanism.
- Root Cause: A functional deadlock caused by a reverting external call that was not properly handled.
- Lesson Learned: This report highlighted the critical importance of defensive programming in smart contracts, especially when interacting with external contracts whose state can be modified by privileged roles. Even though the scenario relied on a compromised governance (which was deemed out-of-scope), it demonstrated my ability to trace complex interactions and identify critical failure points. This experience reinforced the principle that protocols should not only be secure in their own logic but also resilient against the potential misconfiguration or malicious action of their dependencies.
- Vulnerability: A logic flaw in how the
requestNextWithdrawalsBatchfunction handled "dust" amounts (small remainders from integer division) allowed an attacker to prematurely and permanently close the withdrawal queue. - Impact: Permanent freezing of a portion of user funds. An unprivileged attacker could deposit a crafted amount to ensure some of another user's funds would become irrecoverable dust.
- Root Cause: Improper state management when handling residual balances that were below a minimum threshold but greater than zero.
- Lesson Learned: This finding was a valuable lesson in the nuances of smart contract accounting. The root cause was identified as a "1-2 wei corner case," a known issue related to stETH's share calculation mechanism. While my report presented a novel way to weaponize this known issue to cause fund loss, it underscored the rule that vulnerabilities stemming from a documented and accepted root cause are often out of scope. It was a masterclass in understanding the difference between finding a new flaw versus finding a new exploit for an old, accepted flaw.
- Vulnerability: A state management flaw in the
Escrowcontract's accounting library (AssetsAccounting.sol) allowed for a "double spend" of a user'sunstETHNFT. An attacker could lock an NFT, withdraw it, and still have the protocol account for it as if it were finalized, creating a permanent deficit. - Impact: Protocol Insolvency. The attack created a quantifiable "bad debt" in the protocol's ledger, socialized across all honest users.
- Root Cause: Improper state transition logic. The status of a withdrawn asset was not cleared correctly, leaving a dangling state record that could be triggered a second time.
- Lesson Learned: This report was a deep dive into state management and accounting integrity. While I correctly identified a valid state management flaw, the Lido team demonstrated that their internal accounting logic in another part of the contract (
accountUnstETHUnlock) effectively mitigated the double-spend risk. My key takeaway was that assessing the true impact of a vulnerability is as critical as finding the vulnerability itself. A technical flaw without a real, exploitable economic consequence is not a critical vulnerability. This experience sharpened my ability to evaluate the full context and internal mitigating controls of a protocol.
- Vulnerability: An attacker could maliciously call the
accountUnstETHLockfunction with the victim's address but an empty input array. Due to a lack of input validation, this action would unconditionally reset the victim's asset lock timer to the current block timestamp without locking any new assets. - Impact: Temporary loss of funds availability (Griefing). This attack could repeatedly prevent a targeted user from withdrawing their funds once their lock period had expired, causing disruption and potential opportunity costs for the victim.
- Root Cause: A combination of an uninitialized local variable and a failure to validate for empty input arrays, leading to an unconditional state change (
lastAssetsLockTimestampupdate) even when no core action (locking assets) was performed. - Lesson Learned: This investigation taught me a valuable lesson in the importance of business risk assessment in bug bounties. While I successfully demonstrated a technically valid griefing attack, the Lido team classified it as an "Acceptable Risk." Their reasoning was that the attack had a non-trivial gas cost for the attacker but yielded no financial profit, only the temporary inconvenience of a single user. This experience highlighted that the severity of a bug is not just about its technical feasibility, but a practical calculation of its impact, the attacker's incentive, and the cost to exploit versus the damage inflicted. It's a crucial reminder that project teams often view security through a lens of pragmatic risk management.
- Vulnerability: The
calcRequestAmountsfunction used a "divide-before-multiply" pattern, a known anti-pattern in Solidity for integer arithmetic. This led to precision loss, causing any remainder "dust" that was smaller than the minimum request amount to be permanently discarded during calculations. - Impact: Permanent loss of user funds (dust). Although the individual loss was minimal, it represented a flaw in a core financial library that should, in principle, never lose user assets due to calculation errors.
- Root Cause: The use of integer division (
/) to determinerequestsCountbefore calculating the remainder, instead of using the precise modulo (%) operator first. - Lesson Learned: This finding led to a fascinating debate on the definition of a "bug" versus an "intended feature." From a technical purist's viewpoint, any non-zero loss of funds from a calculation is a flaw. However, the Lido team clarified that the function's sole purpose was to calculate the number of full batches, and the leftover dust was considered an acceptable and "intended precision loss" from a business logic perspective. This experience was a masterclass in understanding that in the world of bug bounties, if a project can reasonably justify a behavior as intended for their specific business logic, they have the final say, even if it contradicts common best practices.
- Smart Contract Auditing: Deep analysis of Solidity code for logic flaws, access control issues, re-entrancy, and other common/uncommon vulnerabilities.
- DeFi Security: Understanding of complex financial protocols, economic exploits, oracle manipulation, and tokenomics.
- Testing & Verification: Proficiency in using Foundry to write comprehensive tests and create isolated, runnable Proof-of-Concept exploits.
- Technical Communication: Authoring detailed, clear, and professional vulnerability reports that are easy for developers to understand and act upon.
The world of Web3 security is a marathon, not a sprint. I am constantly learning, researching new attack vectors, and honing my skills. My goal is to continue contributing to the security of the ecosystem, collaborate with top-tier teams, and help build a more resilient decentralized world.
I am always open to discussing security, collaborating on research, or exploring new opportunities.
- Email: wc065426@gmail.com
- LinkedIn: linkedin.com/in/yu-wei-chang